diff --git a/main.c b/main.c index 32706fe..6524253 100644 --- a/main.c +++ b/main.c @@ -55,6 +55,19 @@ bool isStopBroadcastBegin=false; bool isOtaEnable=false; jt_only_tag_t onlyTags[200]={0}; int tagCount=0; + +// 心跳检测相关 +#define HEARTBEAT_TIMEOUT_SEC (30 * 60) // 30分钟超时 +#define MAX_LIGHTBAR_NUM 200 +typedef struct { + uint32_t tagCode; // 灯条ID + time_t lastHeartbeat; // 最后心跳时间 + bool isOnline; // 是否在线 +} lightbar_heartbeat_t; +lightbar_heartbeat_t lightbarHeartbeat[MAX_LIGHTBAR_NUM] = {0}; +int lightbarHeartbeatCount = 0; +pthread_mutex_t heartbeatMutex = PTHREAD_MUTEX_INITIALIZER; +pthread_t pt_heartbeat_check; int lightbars_size=0; int lightbars_count=0; uint8_t changecolor=0; @@ -116,6 +129,72 @@ int mqtt_port=1883; void hmacsha1_hex(char *key, char* data, char *signhex, int signhex_len); void *thread_mqtt_status_check(void *arg); void *thread_station_heartbeat(void *arg); +void *thread_heartbeat_check(void *arg); +void update_lightbar_heartbeat(uint32_t tagCode); + +/*================================================================================*/ +// 更新灯条心跳时间 +void update_lightbar_heartbeat(uint32_t tagCode) { + pthread_mutex_lock(&heartbeatMutex); + + // 查找是否已存在该灯条 + int found = -1; + for (int i = 0; i < lightbarHeartbeatCount; i++) { + if (lightbarHeartbeat[i].tagCode == tagCode) { + found = i; + break; + } + } + + time_t now = time(NULL); + + if (found >= 0) { + // 更新已存在灯条的心跳时间 + lightbarHeartbeat[found].lastHeartbeat = now; + if (!lightbarHeartbeat[found].isOnline) { + lightbarHeartbeat[found].isOnline = true; + LOG_I("Lightbar %08X back online\n", tagCode); + } + } else if (lightbarHeartbeatCount < MAX_LIGHTBAR_NUM) { + // 添加新灯条 + lightbarHeartbeat[lightbarHeartbeatCount].tagCode = tagCode; + lightbarHeartbeat[lightbarHeartbeatCount].lastHeartbeat = now; + lightbarHeartbeat[lightbarHeartbeatCount].isOnline = true; + lightbarHeartbeatCount++; + LOG_I("New lightbar %08X registered, total: %d\n", tagCode, lightbarHeartbeatCount); + } + + pthread_mutex_unlock(&heartbeatMutex); +} + +// 心跳检测线程 - 每分钟检查一次 +void *thread_heartbeat_check(void *arg) { + LOG_I("Heartbeat check thread started\n"); + + while (1) { + sleep(60); // 每60秒检查一次 + + time_t now = time(NULL); + + pthread_mutex_lock(&heartbeatMutex); + + for (int i = 0; i < lightbarHeartbeatCount; i++) { + if (lightbarHeartbeat[i].isOnline) { + time_t elapsed = now - lightbarHeartbeat[i].lastHeartbeat; + if (elapsed > HEARTBEAT_TIMEOUT_SEC) { + lightbarHeartbeat[i].isOnline = false; + LOG_I("!!! Lightbar %06X OFFLINE - no heartbeat for %ld seconds (>%d sec)\n", + lightbarHeartbeat[i].tagCode, (long)elapsed, HEARTBEAT_TIMEOUT_SEC); + } + } + } + + pthread_mutex_unlock(&heartbeatMutex); + } + + return NULL; +} + /*================================================================================*/ void doCommand_help(int argc, char *argv[]) { @@ -1421,11 +1500,12 @@ void *thread_uart_recv_back(void *arg){ while(1){ uart_data_receive_data_back(&uartRecvBack,&parmAck,&tagCodeHead,&tagCode,&tagSignal,&totalLen,&tagFeature, &count,&batteryV,&version,&ledCtrl,&signCode,&reserve,&lableParm); - LOG_I("recv_back:%04x,%04x,tag:%08x,%02x,%02x,%02x,%02x,battery:%02x,%04x,%02x,%04x,reserve:%04x,%08x\n", - parmAck,tagCodeHead,tagCode,tagSignal,totalLen,tagFeature,count,batteryV,version,ledCtrl,signCode,reserve,lableParm); + //LOG_I("recv_back:%04x,%04x,tag:%08x,%02x,%02x,%02x,%02x,battery:%02x,%04x,%02x,%04x,reserve:%04x,%08x\n", + //parmAck,tagCodeHead,tagCode,tagSignal,totalLen,tagFeature,count,batteryV,version,ledCtrl,signCode,reserve,lableParm); PutDataIntoQueue(tagCode,batteryV,reserve); if(tagFeature==0xFF){ - LOG_I("heart beat\n"); + //LOG_I("heart beat from lightbar %06X\n", tagCode); + update_lightbar_heartbeat(tagCode); }else if(tagFeature==0xFD){ LOG_I("key\n"); }else if(tagFeature==0xFC){ @@ -1620,13 +1700,13 @@ void *thread_station_heartbeat(void *arg){ json_object_object_add(root, "eStationInfor", estation_info); const char *json_string = json_object_to_json_string(root); - LOG_I("station_heartbeat:%s\n", json_string); + //LOG_I("station_heartbeat:%s\n", json_string); // 发送心跳到 /estation/{ID}/heartbeat topic char topic[128] = {0}; snprintf(topic, sizeof(topic), "/estation/%s/heartbeat", stationsn); // 这里需要使用MQTT发送函数,暂时用LOG输出 - LOG_I("Sending heartbeat to topic: %s\n", topic); + //LOG_I("Sending heartbeat to topic: %s\n", topic); json_object_put(root); } @@ -2153,6 +2233,14 @@ int main(int argc, char *argv[]) LOG_I("pthread_create station_heartbeat success\n"); pthread_detach(pt_station_heartbeat); } + + ret = pthread_create(&pt_heartbeat_check,NULL,thread_heartbeat_check,NULL); + if(ret!=0){ + LOG_I("pthread_create heartbeat_check fail\n"); + }else{ + LOG_I("pthread_create heartbeat_check success\n"); + pthread_detach(pt_heartbeat_check); + } #if 0 readresult=file_to_buffer("mqttRawPassword",&len); if(readresult!=NULL){