#include "data_changes.h"
#include "ras_common.h"
extern PIRSensor_p sensor;
extern g4_module_ctx_t* g_ctx_air780;
global_state_t g_state = {
.ina219 = NULL,
.dht11_pin = 21,
.restart_gpio = 12,
.current_lat = 0.0f,
.current_lng = 0.0f,
.has_valid_gps = 0,
.last_th = -1000.0f,
.last_rh = -1000.0f,
.last_percent = -1000.0f,
.last_reported_percent = -1000.0f,
.last_lat_for_dist = 0.0f,
.last_lng_for_dist = 0.0f,
.last_csq_rssi = -1,
.first_sample_done = 0,
.keep_running = 1,
.data_thread_running = 0,
.data_thread = 0,
.restart_thread = 0
};
// Thing_Model_t g_thing_Model;
void stop_all_threads(void);
// 同步 module info 的互斥锁
extern pthread_mutex_t g_module_info_mutex;
// ==================== GPS 回调 ====================
void my_gps_data_handle(const gps_paresd_data_t* data)
{
if (!data || data->lat[0] == '\0' || data->lng[0] == '\0') return;
//printf("纬度: %s, 经度: %s\n", data->lat, data->lng);
float lat_raw = atof(data->lat);
float lng_raw = atof(data->lng);
if (lat_raw != 0.0f && lng_raw != 0.0f) {
// 转换 DDMM.MMMM 格式到 DD.DDDDDD 十进制度数
float lat_deg = floorf(lat_raw / 100.0f);
float lat_min = lat_raw - lat_deg * 100.0f;
g_state.current_lat = lat_deg + lat_min / 60.0f;
float lng_deg = floorf(lng_raw / 100.0f);
float lng_min = lng_raw - lng_deg * 100.0f;
g_state.current_lng = lng_deg + lng_min / 60.0f;
g_state.has_valid_gps = 1;
// 生成百度坐标字符串
zuobiao_dta(lng_raw, lat_raw, g_state.buf_lat_lng, sizeof(g_state.buf_lat_lng));
printf("转换后坐标: %s (WGS84: %.6f, %.6f)\n", g_state.buf_lat_lng, g_state.current_lng, g_state.current_lat);
writeFilegps(g_state.buf_lat_lng, "zuobiao.txt");
} else {
// printf("GPS 数据无效(0.0)\n");
// printf("经纬度:%s\n",g_state.buf_lat_lng);
}
}
// ==================== 重新初始化硬件 ====================
int reinitialize_hardware(void)
{
printf("重新初始化硬件...\n");
// 重新初始化 INA219
if (g_state.ina219) {
ina219_close(g_state.ina219);
}
g_state.ina219 = start_init_in291();
if (!g_state.ina219) {
fprintf(stderr, "[ERROR] INA219 重新初始化失败\n");
return -1;
}
// 重新初始化 DHT11
if (!dht11_init(g_state.dht11_pin)) {
fprintf(stderr, "[ERROR] DHT11 重新初始化失败\n");
return -1;
}
// 重新初始化 GPIO
if (qckg_init(g_state.restart_gpio) != 0) {
fprintf(stderr, "[ERROR] GPIO 重新初始化失败\n");
return -1;
}
// 重新初始化 4G 模块
g4_module_config_t config = {
.serial_device = "/dev/ttyAMA0",
.baud_rate = 9600,
.timeout_seconds = 3,
.max_retry = 3
};
if (start_air780_debug(config) == 0) {
fprintf(stderr, "[ERROR] 4G 模块重新启动成功\n");
// 重置状态变量
g_state.last_th = -1000.0f;
g_state.last_rh = -1000.0f;
g_state.last_percent = -1000.0f;
g_state.last_reported_percent = -1000.0f;
g_state.last_csq_rssi = -1;
//清空GPS全局变量
memset(g_state.buf_lat_lng, 0, sizeof(g_state.buf_lat_lng));
g_state.current_lat = 0.0f;
g_state.current_lng = 0.0f;
g_state.has_valid_gps = 0;
printf("重新初始化GPS模块...\n");
set_gps_data_callback(my_gps_data_handle);
sleep(1); // 等待旧线程退出
gps_data_init_with_device("/dev/ttyAMA1");
// 重置状态变量
g_state.first_sample_done = 0;
printf("硬件重新初始化成功\n");
return 0;
}
return 0;
}
// ==================== 信号处理函数 ====================
void signal_handler(int sig) {
printf("\n接收到信号 %d,准备退出...\n", sig);
g_state.keep_running = 0;
}
// ==================== 数据采集线程 ====================
void* pthread_data_change(void* arg)
{
printf("数据采集线程启动\n");
// 等待完成,设置超时时间
int timeout = 300; // 超时
int wait_count = 0;
while (g_ctx_air780->current_step != STEP_COMPLETE) {
sleep(1); // 等待1秒
wait_count++;
if (wait_count >= timeout) {
printf("等待超时,当前步骤: %d\n", g_ctx_air780->current_step);
break;
}
}
//等待温湿度数据读取成功
int temp_humid_timeout = 360; // 温湿度读取超时时间(秒)
int temp_humid_wait_count = 0;
int temp_humid_valid = 0;
printf("等待温湿度传感器数据...\n");
while (!temp_humid_valid && temp_humid_wait_count < temp_humid_timeout) {
// 尝试读取温湿度数据
DHT11_Data_t d = dht11_read_data(g_state.dht11_pin);
if (d.humidity_integer != 0 || d.temperature_integer != 0) {
float current_rh = (float)d.humidity_integer + (float)d.humidity_decimal / 10.0f;
float current_th = (float)d.temperature_integer + (float)d.temperature_decimal / 10.0f;
if (current_th > -40.0f && current_th < 80.0f && current_rh >= 0.0f && current_rh <= 100.0f) {
printf("成功读取温湿度: 温度%.1f℃, 湿度%.1f%%\n", current_th, current_rh);
temp_humid_valid = 1;
break;
}
}
temp_humid_wait_count++;
if (temp_humid_wait_count % 5 == 0) {
printf("等待温湿度数据... (%d/%d 秒)\n", temp_humid_wait_count, temp_humid_timeout);
}
sleep(1);
}
if (!temp_humid_valid) {
printf("警告: 温湿度读取异常,继续执行...\n");
}
if (g_ctx_air780->current_step == STEP_COMPLETE) {
// printf("步骤完成,继续执行...\n");
// if(get_ip_address(g_state.reportInfo_Device_Status.ipAddress,sizeof(g_state.reportInfo_Device_Status.ipAddress))
// &&get_rpi_serial(g_state.reportInfo_Device_Status.deviceSN, sizeof(g_state.reportInfo_Device_Status.deviceSN))
// &&get_device_model(g_state.reportInfo_Device_Status.deviceModel,sizeof(g_state.reportInfo_Device_Status.deviceModel))
// &&get_firmware_version(g_state.reportInfo_Device_Status.firmwareVersion, sizeof(g_state.reportInfo_Device_Status.firmwareVersion))
// &&get_hardware_nrevisio(g_state.reportInfo_Device_Status.hardwareVersion, sizeof(g_state.reportInfo_Device_Status.hardwareVersion)))
// {
// printf("设备信息获取成功\n");
// memcpy(g_state.reportInfo_Device_Status.sdCardStatus,"正常",sizeof(g_state.reportInfo_Device_Status.sdCardStatus));
// if(sensor != NULL)
// {
// g_state.reportInfo_Device_Status.motionDetectEnable = 1;
// }else{
// g_state.reportInfo_Device_Status.motionDetectEnable = 0;
// }
// vp_reportinfo_Device_Status(&g_state.reportInfo_Device_Status);
// }
}
else {
printf("步骤未完成,当前状态: %d\n", g_ctx_air780->current_step);
}
while ((g_state.data_thread_running)&&(g_ctx_air780->current_step == STEP_COMPLETE)) {
sleep(10);
// 1. 网络路由
char out_route[32] = {0};
route_select(out_route, sizeof(out_route));
// 2. 电量
float bus_voltage = -1.0f;
if (g_state.ina219) {
bus_voltage = ina219_get_bus_voltage_V(g_state.ina219);
}
float current_percent = (bus_voltage - 6.0f) / 2.17f * 100.0f;
current_percent = fmaxf(0.0f, fminf(100.0f, current_percent));
printf("当前电量%.1f\n",current_percent);
// 3. 温湿度
DHT11_Data_t d = dht11_read_data(g_state.dht11_pin);
float current_th = -1.0f, current_rh = -1.0f;
if (d.humidity_integer != 0 || d.temperature_integer != 0) {
current_rh = (float)d.humidity_integer + (float)d.humidity_decimal / 10.0f;
current_th = (float)d.temperature_integer + (float)d.temperature_decimal / 10.0f;
printf("温度%.1f, 湿度%.1f\n", current_th, current_rh);
}
// 4. 网络状态 + CSQ 解析
int current_csq_rssi = update_network_info(out_route);
update_device_info();
// 5. 判断是否需要上报
int should_report_1 = 0;
int should_report_2 = 0;
int should_report_3 = 0;
// 路由变化检测
if (strcmp(out_route, g_state.last_route_show) != 0) {
should_report_3 = 1;
printf("路由变化: %s -> %s,触发上报\n", g_state.last_route_show, out_route);
memset(g_state.last_route_show, 0, sizeof(g_state.last_route_show));
size_t route_len = strlen(out_route);
size_t copy_len = (route_len < sizeof(g_state.last_route_show)) ? route_len : (sizeof(g_state.last_route_show) - 1);
memcpy(g_state.last_route_show, out_route, copy_len);
}
if (g_state.has_valid_gps && g_state.first_sample_done) {
if (g_state.last_lat_for_dist == 0.0f && g_state.last_lng_for_dist == 0.0f) {
g_state.last_lat_for_dist = g_state.current_lat;
g_state.last_lng_for_dist = g_state.current_lng;
printf("[DEBUG] 初始化参考坐标: lat=%.6f, lng=%.6f\n", g_state.last_lat_for_dist, g_state.last_lng_for_dist);
}
printf("[DEBUG] 距离计算: 上次(%.6f, %.6f) -> 当前(%.6f, %.6f)\n", g_state.last_lat_for_dist, g_state.last_lng_for_dist, g_state.current_lat, g_state.current_lng);
float dist = haversine_distance_m(
g_state.last_lat_for_dist, g_state.last_lng_for_dist,
g_state.current_lat, g_state.current_lng
);
printf("[DEBUG] 计算距离: %.2f 米\n", dist);
if (dist > 40.0f) {
should_report_1 = 1;
printf("[DEBUG] 更新参考坐标: lat=%.6f, lng=%.6f\n", g_state.current_lat, g_state.current_lng);
g_state.last_lat_for_dist = g_state.current_lat;
g_state.last_lng_for_dist = g_state.current_lng;
SAFE_MEMCPY(g_state.lng_lat, g_state.buf_lat_lng, sizeof(g_state.lng_lat));
printf("位置变化 %.1f 米,触发上报\n", dist);
}
}
//温湿度变化检测
if (current_th >= 0 && g_state.last_th >= 0 && fabsf(current_th - g_state.last_th) > 2.0f) {
should_report_2 = 1;
printf("温度变化 %.1f℃,触发上报\n", fabsf(current_th - g_state.last_th));
}
if (current_rh >= 0 && g_state.last_rh >= 0 && fabsf(current_rh - g_state.last_rh) > 3.0f) {
should_report_2 = 1;
printf("湿度变化 %.1f%%,触发上报\n", fabsf(current_rh - g_state.last_rh));
}
// 电量累计变化检测
if (g_state.last_reported_percent >= 0) {
float accumulated_change = fabsf(current_percent - g_state.last_reported_percent);
if (accumulated_change >= 1.0f) {
should_report_2 = 1;
g_state.last_reported_percent = current_percent;
printf("电量累计变化 %.1f%%,触发上报\n", accumulated_change);
}
}
// 保存旧值
int old_csq = g_state.last_csq_rssi;
// 更新 g_state.last_csq_rssi
if (current_csq_rssi >= 0) {
g_state.last_csq_rssi = current_csq_rssi;
}
// 判断是否需要上报
if (current_csq_rssi >= 0) {
if (old_csq == -1) {
// 首次有效值,触发上报
should_report_3 = 1;
printf("首次获取有效 CSQ: %d,触发上报\n", current_csq_rssi);
} else if (abs(current_csq_rssi - old_csq) > 6) {
should_report_3 = 1;
printf("CSQ 变化 %d -> %d,触发上报\n", old_csq, current_csq_rssi);
}
}
// 首次采集
if (!g_state.first_sample_done) {
printf("首次采集上报\n");
should_report_2 = 1;
should_report_1 = 1;
should_report_3 = 1;
g_state.first_sample_done = 1;
g_state.last_reported_percent = current_percent;
if (g_state.has_valid_gps) {
should_report_1 = 1;
g_state.last_lat_for_dist = g_state.current_lat;
g_state.last_lng_for_dist = g_state.current_lng;
SAFE_MEMCPY(g_state.lng_lat, g_state.buf_lat_lng, sizeof(g_state.lng_lat));
}
if (current_csq_rssi >= 0) {
g_state.last_csq_rssi = current_csq_rssi;
}
memset(g_state.last_route_show, 0, sizeof(g_state.last_route_show));
size_t route_len = strlen(out_route);
size_t copy_len = (route_len < sizeof(g_state.last_route_show)) ? route_len : (sizeof(g_state.last_route_show) - 1);
memcpy(g_state.last_route_show, out_route, copy_len);
printf("首次采集,上报\n");
} else {
if (current_csq_rssi >= 0) {
g_state.last_csq_rssi = current_csq_rssi;
}
}
// 更新其他"上次值"
g_state.last_percent = current_percent;
if(current_th >= 0) {
// 更新结构体
g_state.reportInfo_Location_Power_TemperatureHumidity.th = (current_th < 0) ? -1.0f : roundf(current_th * 100.0f) / 100.0f;
g_state.reportInfo_Location_Power_TemperatureHumidity.rh = current_rh;
}
snprintf(g_state.reportInfo_Location_Power_TemperatureHumidity.percent,
sizeof(g_state.reportInfo_Location_Power_TemperatureHumidity.percent),
"%.1f", current_percent);
// 6. 执行上报
vp_reportInfo_Information(&g_state.reportInfo_Information);
usleep(1000000);
if (should_report_2&&g_state.reportInfo_Location_Power_TemperatureHumidity.th >= 0&&g_state.reportInfo_Location_Power_TemperatureHumidity.rh >= 0) {
vp_reportInfo_Power_TemperatureHumidity(&g_state.reportInfo_Location_Power_TemperatureHumidity);
// 上报后更新温湿度和电量的上报基准值
if (current_th >= 0) g_state.last_th = current_th;
if (current_rh >= 0) g_state.last_rh = current_rh;
g_state.last_reported_percent = current_percent;
usleep(1000000);
}
if (should_report_3) {
vp_reportInfo_Network_Status(&g_state.reportInfo_Network_Status);
usleep(1000000);
}
if(should_report_1){
vp_reportInfo_Location(g_state.lng_lat);
usleep(1000000);
}
}
cleanup_resources();
printf("数据采集线程退出\n");
return NULL;
}
// ==================== 重启检测线程 ====================
void* pthread_data_restart(void* arg)
{
int gpio_pin = (int)(intptr_t)arg;
time_t start_time = 0;
int high_detected = 0;
time_t last_restart_time = 0; // 上次重启时间
const int RESTART_COOLDOWN = 10; // 重启冷却时间(秒)
printf("重启检测线程启动,监控GPIO%d\n", gpio_pin);
while (g_state.keep_running) {
int state = qckg_read(gpio_pin);
if (state == 1) {
if (!high_detected) {
start_time = time(NULL);
high_detected = 1;
printf("检测到高电平,开始计时...\n");
} else {
if (difftime(time(NULL), start_time) >= 3.0) {
time_t current_time = time(NULL);
// 检查冷却时间
if (difftime(current_time, last_restart_time) < RESTART_COOLDOWN) {
printf("重启操作过于频繁(冷却时间剩余: %.0f秒)\n",
RESTART_COOLDOWN - difftime(current_time, last_restart_time));
high_detected = 0;
start_time = 0;
continue;
}
printf("高电平持续3秒,触发硬件重新初始化\n");
last_restart_time = current_time;
// 清理资源
stop_all_threads();
printf("等待硬件稳定...\n");
sleep(2);
if (reinitialize_hardware() == 0) {
memset(&g_state.reportInfo_Information, 0, sizeof(g_state.reportInfo_Information));
memset(&g_state.reportInfo_Network_Status, 0, sizeof(g_state.reportInfo_Network_Status));
memset(&g_state.reportInfo_Location_Power_TemperatureHumidity, 0, sizeof(g_state.reportInfo_Location_Power_TemperatureHumidity));
memset(&g_state.reportInfo_Device_Status, 0, sizeof(g_state.reportInfo_Device_Status));
printf("硬件重新初始化成功\n");
// 重新启动数据采集线程
g_state.data_thread_running = 1;
if (pthread_create(&g_state.data_thread, NULL, pthread_data_change, NULL) != 0) {
fprintf(stderr, "重新创建数据采集线程失败\n");
g_state.data_thread_running = 0;
} else {
printf("数据采集线程重新启动成功\n");
}
} else {
fprintf(stderr, "硬件重新初始化失败\n");
}
// 重置检测状态
high_detected = 0;
start_time = 0;
}
}
} else {
if (high_detected) {
printf("高电平中断,重置计时\n");
high_detected = 0;
start_time = 0;
}
}
usleep(100000); // 100ms
}
printf("重启检测线程退出\n");
return NULL;
}
// ==================== 外部接口 ====================
int data_change()
{
if (g_state.data_thread != 0) {
printf("数据采集线程已在运行\n");
return 0;
}
// 初始化硬件
// wiring_init();
// g_state.dht11_pin = 21;
// g_state.restart_gpio = 17;
// 初始化硬件
if (reinitialize_hardware() == 0) {
g_state.data_thread_running=1;
int ret = pthread_create(&g_state.data_thread, NULL, pthread_data_change, NULL);
if (ret != 0) {
fprintf(stderr, "创建数据采集线程失败: %d\n", ret);
g_state.data_thread_running = 0;
return -1;
}
}else
{
printf("初始化硬件失败\n");
}
printf("数据采集启动成功\n");
return 0;
}
int restart()
{
if (g_state.restart_thread != 0) {
printf("重启检测线程已在运行\n");
return 0;
}
// const int gpio_pin = 17;
int ret = pthread_create(&g_state.restart_thread, NULL, pthread_data_restart, (void*)(intptr_t)g_state.restart_gpio);
if (ret != 0) {
fprintf(stderr, "创建重启检测线程失败: %d\n", ret);
return -1;
}
printf("重启检测启动成功\n");
return 0;
}
// 停止所有线程
void stop_all_threads(void)
{
printf("停止所有线程...\n");
g_state.data_thread_running = 0;
if (g_state.data_thread) {
pthread_join(g_state.data_thread, NULL);
g_state.data_thread = 0;
}
cleanup_resources();
printf("所有线程已停止\n");
} 这个是相关代码
最新发布