From 48e7151ac006da33069eff1774584f55785aef40 Mon Sep 17 00:00:00 2001 From: zzh <838331105@qq.com> Date: Tue, 30 Dec 2025 09:37:45 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=81=AF=E6=9D=A1=E4=B8=8A?= =?UTF-8?q?=E6=8A=A5tag=E4=B8=8E=E6=94=B6=E5=88=B0=E7=9A=84tag=E4=B8=8D?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.c | 199 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 82 deletions(-) diff --git a/main.c b/main.c index 298733b..1ac2fff 100644 --- a/main.c +++ b/main.c @@ -75,28 +75,32 @@ int tagCount=0; #define HEARTBEAT_TIMEOUT_SEC (30 * 60) // 30分钟超时 #define MAX_LIGHTBAR_NUM 5000 typedef struct { - uint32_t tagCode; // 灯条ID - time_t lastHeartbeat; // 最后心跳时间 - bool isOnline; // 是否在线 + uint16_t tagCodeHead; // 灯条ID头部 + uint32_t tagCode; // 灯条ID主体 + char fullTagId[16]; // 完整的灯条ID (12位十六进制) + 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; // 亮灯任务确认相关 -#define MAX_PENDING_LIGHT_TASKS 50 +#define MAX_PENDING_LIGHT_TASKS 1024 typedef struct { - uint32_t tagCode; // 灯条ID(tag的后6位) - char taskId[64]; // 任务ID - int beep; // 蜂鸣器状态(0或1) - int flash; // 闪烁状态(0或1) - int light_r; // 红色(0或1) - int light_g; // 绿色(0或1) - int light_b; // 蓝色(0或1) - bool reported; // 是否已上报亮灯成功 - bool lightOffReported; // 是否已上报灭灯 - time_t createTime; // 创建时间 - int duration; // 亮灯持续时间(秒) + uint16_t tagCodeHead; // 灯条ID头部 + uint32_t tagCode; // 灯条ID主体(tag的后6位) + char fullTagId[16]; // 完整的灯条ID (12位十六进制) + char taskId[64]; // 任务ID + int beep; // 蜂鸣器状态(0或1) + int flash; // 闪烁状态(0或1) + int light_r; // 红色(0或1) + int light_g; // 绿色(0或1) + int light_b; // 蓝色(0或1) + int duration; // 持续时间(秒) + time_t reportTime; // 上报时间 + bool reported; // 是否已上报 + bool lightOffReported; // 是否已上报灭灯 } pending_light_task_t; pending_light_task_t pendingLightTasks[MAX_PENDING_LIGHT_TASKS] = {0}; int pendingLightTaskCount = 0; @@ -105,6 +109,7 @@ pthread_mutex_t lightTaskMutex = PTHREAD_MUTEX_INITIALIZER; // 按键防抖相关 #define MAX_KEY_DEBOUNCE 50 typedef struct { + uint16_t tagCodeHead; // 灯条ID头部 uint32_t tagCode; time_t lastKeyTime; } key_debounce_t; @@ -182,16 +187,16 @@ void *thread_light_off_check(void *arg); void *thread_simulate_light(void *arg); void *thread_all_light(void *arg); void *thread_simulate_mqtt_topic(void *arg); -void update_lightbar_heartbeat(uint32_t tagCode); -void report_lightbar_login(uint32_t tagCode); -void report_lightbar_logout(uint32_t tagCode); -void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int flash, int r, int g, int b, int duration); -void report_light_success(uint32_t tagCode); -void report_light_off(uint32_t tagCode); +void update_lightbar_heartbeat(uint16_t tagCodeHead, uint32_t tagCode); +void report_lightbar_login(uint16_t tagCodeHead, uint32_t tagCode); +void report_lightbar_logout(uint16_t tagCodeHead, uint32_t tagCode); +void add_pending_light_task(uint16_t tagCodeHead, uint32_t tagCode, const char *taskId, int beep, int flash, int r, int g, int b, int duration); +void report_light_success(uint16_t tagCodeHead, uint32_t tagCode); +void report_light_off(uint16_t tagCodeHead, uint32_t tagCode); /*================================================================================*/ // 上报灯条子设备登录 -void report_lightbar_login(uint32_t tagCode) { +void report_lightbar_login(uint16_t tagCodeHead, uint32_t tagCode) { char subDeviceKey[32] = {0}; char topic[256] = {0}; char payload[512] = {0}; @@ -200,8 +205,8 @@ void report_lightbar_login(uint32_t tagCode) { char timestamp_str[32] = {0}; struct timeval tv; - // 构建subDeviceKey: AD10 + tagCode (十六进制) - snprintf(subDeviceKey, sizeof(subDeviceKey), "AD10%08X", tagCode); + // 构建subDeviceKey: 使用完整的tagID (tagCodeHead + tagCode) + snprintf(subDeviceKey, sizeof(subDeviceKey), "%04X%08X", tagCodeHead, tagCode); // 获取当前时间戳(毫秒) gettimeofday(&tv, NULL); @@ -233,12 +238,12 @@ void report_lightbar_login(uint32_t tagCode) { /*================================================================================*/ // 添加待确认的亮灯任务 -void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int flash, int r, int g, int b, int duration) { +void add_pending_light_task(uint16_t tagCodeHead, uint32_t tagCode, const char *taskId, int beep, int flash, int r, int g, int b, int duration) { pthread_mutex_lock(&lightTaskMutex); // 检查是否已存在 for (int i = 0; i < pendingLightTaskCount; i++) { - if (pendingLightTasks[i].tagCode == tagCode && !pendingLightTasks[i].reported) { + if (pendingLightTasks[i].tagCode == tagCode && pendingLightTasks[i].tagCodeHead == tagCodeHead && !pendingLightTasks[i].reported) { // 更新任务信息 strncpy(pendingLightTasks[i].taskId, taskId, sizeof(pendingLightTasks[i].taskId) - 1); pendingLightTasks[i].beep = beep; @@ -247,7 +252,7 @@ void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int pendingLightTasks[i].light_g = g; pendingLightTasks[i].light_b = b; pendingLightTasks[i].duration = duration; - pendingLightTasks[i].createTime = time(NULL); + pendingLightTasks[i].reportTime = time(NULL); LOG_I("Updated pending light task for tag %08X, taskId: %s, beep: %d, flash: %d, RGB: %d,%d,%d, duration: %d\n", tagCode, taskId, beep, flash, r, g, b, duration); pthread_mutex_unlock(&lightTaskMutex); @@ -257,7 +262,9 @@ void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int // 添加新任务 if (pendingLightTaskCount < MAX_PENDING_LIGHT_TASKS) { + pendingLightTasks[pendingLightTaskCount].tagCodeHead = tagCodeHead; pendingLightTasks[pendingLightTaskCount].tagCode = tagCode; + snprintf(pendingLightTasks[pendingLightTaskCount].fullTagId, sizeof(pendingLightTasks[pendingLightTaskCount].fullTagId), "%04X%08X", tagCodeHead, tagCode); strncpy(pendingLightTasks[pendingLightTaskCount].taskId, taskId, sizeof(pendingLightTasks[pendingLightTaskCount].taskId) - 1); pendingLightTasks[pendingLightTaskCount].beep = beep; @@ -267,7 +274,7 @@ void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int pendingLightTasks[pendingLightTaskCount].light_b = b; pendingLightTasks[pendingLightTaskCount].reported = false; pendingLightTasks[pendingLightTaskCount].lightOffReported = false; - pendingLightTasks[pendingLightTaskCount].createTime = time(NULL); + pendingLightTasks[pendingLightTaskCount].reportTime = time(NULL); pendingLightTasks[pendingLightTaskCount].duration = duration; LOG_I("Added pending light task for tag %08X, taskId: %s, beep: %d, flash: %d, RGB: %d,%d,%d, duration: %d\n", tagCode, taskId, beep, flash, r, g, b, duration); @@ -281,22 +288,18 @@ void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int /*================================================================================*/ // 上报亮灯成功 -void report_light_success(uint32_t tagCode) { +void report_light_success(uint16_t tagCodeHead, uint32_t tagCode) { pthread_mutex_lock(&lightTaskMutex); // 查找对应的待确认任务 for (int i = 0; i < pendingLightTaskCount; i++) { - if (pendingLightTasks[i].tagCode == tagCode && !pendingLightTasks[i].reported) { + if (pendingLightTasks[i].tagCode == tagCode && pendingLightTasks[i].tagCodeHead == tagCodeHead && !pendingLightTasks[i].reported) { // 构建上报topic和payload char topic[256] = {0}; char payload[1024] = {0}; - char tagStr[16] = {0}; - // 将tagCode转换为字符串(格式:AD10 + 8位十六进制) - snprintf(tagStr, sizeof(tagStr), "AD10%08X", tagCode); - - // 构建topic: /sys/WcSubLightStrip/{deviceName}/thing/property/post - snprintf(topic, sizeof(topic), "/sys/WcSubLightStrip/%s/thing/service/lightOperate/invoke_reply", tagStr); + // 使用完整的tagID + snprintf(topic, sizeof(topic), "/sys/WcSubLightStrip/%s/thing/service/lightOperate/invoke_reply", pendingLightTasks[i].fullTagId); // 获取当前时间戳(毫秒) struct timeval tv; @@ -342,17 +345,16 @@ void report_light_success(uint32_t tagCode) { /*================================================================================*/ // 上报灭灯(调用时必须已持有lightTaskMutex锁) -void report_light_off(uint32_t tagCode) { +void report_light_off(uint16_t tagCodeHead, uint32_t tagCode) { // 查找对应的已上报亮灯成功的任务 for (int i = 0; i < pendingLightTaskCount; i++) { - if (pendingLightTasks[i].tagCode == tagCode && + if (pendingLightTasks[i].tagCode == tagCode && pendingLightTasks[i].tagCodeHead == tagCodeHead && pendingLightTasks[i].reported && !pendingLightTasks[i].lightOffReported) { // 构建上报topic和payload char topic[256] = {0}; char payload[1024] = {0}; - char tagStr[16] = {0}; char uuid_str[37] = {0}; uuid_t uuid; @@ -360,11 +362,8 @@ void report_light_off(uint32_t tagCode) { uuid_generate(uuid); uuid_unparse(uuid, uuid_str); - // 将tagCode转换为字符串(格式:AD10 + 8位十六进制) - snprintf(tagStr, sizeof(tagStr), "AD10%08X", tagCode); - - // 构建topic: /sys/WcSubLightStrip/{deviceName}/thing/property/post - snprintf(topic, sizeof(topic), "/sys/WcSubLightStrip/%s/thing/property/post", tagStr); + // 使用完整的tagID + snprintf(topic, sizeof(topic), "/sys/WcSubLightStrip/%s/thing/property/post", pendingLightTasks[i].fullTagId); // 获取当前时间戳(毫秒) struct timeval tv; @@ -395,6 +394,12 @@ void report_light_off(uint32_t tagCode) { // 标记为已上报灭灯 pendingLightTasks[i].lightOffReported = true; + // 清理已完成的任务 - 将最后一个任务移到当前位置 + if (i < pendingLightTaskCount - 1) { + pendingLightTasks[i] = pendingLightTasks[pendingLightTaskCount - 1]; + } + pendingLightTaskCount--; + return; } } @@ -404,7 +409,7 @@ void report_light_off(uint32_t tagCode) { /*================================================================================*/ // 上报灯条子设备登出 -void report_lightbar_logout(uint32_t tagCode) { +void report_lightbar_logout(uint16_t tagCodeHead, uint32_t tagCode) { char subDeviceKey[32] = {0}; char topic[256] = {0}; char payload[512] = {0}; @@ -413,8 +418,8 @@ void report_lightbar_logout(uint32_t tagCode) { char timestamp_str[32] = {0}; struct timeval tv; - // 构建subDeviceKey: AD10 + tagCode (十六进制) - snprintf(subDeviceKey, sizeof(subDeviceKey), "AD10%08X", tagCode); + // 构建subDeviceKey: 使用完整的tagID (tagCodeHead + tagCode) + snprintf(subDeviceKey, sizeof(subDeviceKey), "%04X%08X", tagCodeHead, tagCode); // 获取当前时间戳(毫秒) gettimeofday(&tv, NULL); @@ -446,13 +451,13 @@ void report_lightbar_logout(uint32_t tagCode) { /*================================================================================*/ // 更新灯条心跳时间 -void update_lightbar_heartbeat(uint32_t tagCode) { +void update_lightbar_heartbeat(uint16_t tagCodeHead, uint32_t tagCode) { pthread_mutex_lock(&heartbeatMutex); // 查找是否已存在该灯条 int found = -1; for (int i = 0; i < lightbarHeartbeatCount; i++) { - if (lightbarHeartbeat[i].tagCode == tagCode) { + if (lightbarHeartbeat[i].tagCode == tagCode && lightbarHeartbeat[i].tagCodeHead == tagCodeHead) { found = i; break; } @@ -465,26 +470,30 @@ void update_lightbar_heartbeat(uint32_t tagCode) { lightbarHeartbeat[found].lastHeartbeat = now; if (!lightbarHeartbeat[found].isOnline) { lightbarHeartbeat[found].isOnline = true; - LOG_I("Lightbar %08X back online\n", tagCode); + LOG_I("Lightbar %04X%08X back online\n", tagCodeHead, tagCode); // 只有MQTT连接后才上报登录 if (isMqttConnected) { - report_lightbar_login(tagCode); + report_lightbar_login(tagCodeHead, tagCode); } else { LOG_I("MQTT not connected yet, skip lightbar login report\n"); } } - } 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); - // 只有MQTT连接后才上报登录 - if (isMqttConnected) { - report_lightbar_login(tagCode); - } else { - LOG_I("MQTT not connected yet, skip lightbar login report\n"); + } else { + // 添加新的灯条记录 + if (lightbarHeartbeatCount < MAX_LIGHTBAR_NUM) { + lightbarHeartbeat[lightbarHeartbeatCount].tagCodeHead = tagCodeHead; + lightbarHeartbeat[lightbarHeartbeatCount].tagCode = tagCode; + snprintf(lightbarHeartbeat[lightbarHeartbeatCount].fullTagId, sizeof(lightbarHeartbeat[lightbarHeartbeatCount].fullTagId), "%04X%08X", tagCodeHead, tagCode); + lightbarHeartbeat[lightbarHeartbeatCount].lastHeartbeat = now; + lightbarHeartbeat[lightbarHeartbeatCount].isOnline = true; + lightbarHeartbeatCount++; + LOG_I("New lightbar %04X%08X registered, total: %d\n", tagCodeHead, tagCode, lightbarHeartbeatCount); + // 只有MQTT连接后才上报登录 + if (isMqttConnected) { + report_lightbar_login(tagCodeHead, tagCode); + } else { + LOG_I("MQTT not connected yet, skip lightbar login report\n"); + } } } @@ -510,7 +519,7 @@ void *thread_heartbeat_check(void *arg) { 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); - report_lightbar_logout(lightbarHeartbeat[i].tagCode); + report_lightbar_logout(lightbarHeartbeat[i].tagCodeHead, lightbarHeartbeat[i].tagCode); } } } @@ -532,10 +541,24 @@ void *thread_light_off_check(void *arg) { pthread_mutex_lock(&lightTaskMutex); + // 先清理已完成的任务 + for (int i = 0; i < pendingLightTaskCount; ) { + if (pendingLightTasks[i].reported && pendingLightTasks[i].lightOffReported) { + // 清理已完成的任务 - 将最后一个任务移到当前位置 + if (i < pendingLightTaskCount - 1) { + pendingLightTasks[i] = pendingLightTasks[pendingLightTaskCount - 1]; + } + pendingLightTaskCount--; + // 不增加i,因为当前位置现在是新任务 + } else { + i++; + } + } + for (int i = 0; i < pendingLightTaskCount; i++) { // 只检查已上报亮灯成功但未上报灭灯的任务 if (pendingLightTasks[i].reported && !pendingLightTasks[i].lightOffReported) { - time_t elapsed = now - pendingLightTasks[i].createTime; + time_t elapsed = now - pendingLightTasks[i].reportTime; // 检查是否超过持续时间 if (elapsed >= pendingLightTasks[i].duration) { @@ -543,7 +566,7 @@ void *thread_light_off_check(void *arg) { pendingLightTasks[i].tagCode, (long)elapsed, pendingLightTasks[i].duration); // 上报灭灯 - report_light_off(pendingLightTasks[i].tagCode); + report_light_off(pendingLightTasks[i].tagCodeHead, pendingLightTasks[i].tagCode); } } } @@ -2162,7 +2185,7 @@ void *thread_uart_recv_data(void *arg){ parmAck,tagCodeHead,tagCode,tagSignal,totalLen,tagFeature,count,batteryV,version,ledCtrl,signCode,reserve,lableParm); // 检查是否有待确认的亮灯任务,如果tag匹配则上报亮灯成功 - report_light_success(tagCode); + report_light_success(tagCodeHead, tagCode); isStopBroadcastBegin=true; //sleep(2); @@ -2196,7 +2219,7 @@ void *thread_uart_recv_back(void *arg){ PutDataIntoQueue(tagCode,batteryV,reserve); if(tagFeature==0xFF){ //LOG_I("heart beat from lightbar %06X\n", tagCode); - update_lightbar_heartbeat(tagCode); + update_lightbar_heartbeat(tagCodeHead, tagCode); }else if(tagFeature==0xFD){ LOG_I("key pressed from tag %08X\n", tagCode); @@ -2208,7 +2231,7 @@ void *thread_uart_recv_back(void *arg){ // 查找是否已有该tag的记录 for (int i = 0; i < keyDebounceCount; i++) { - if (keyDebounceList[i].tagCode == tagCode) { + if (keyDebounceList[i].tagCode == tagCode && keyDebounceList[i].tagCodeHead == tagCodeHead) { debounceIndex = i; if (now - keyDebounceList[i].lastKeyTime < 2) { shouldProcess = false; @@ -2223,7 +2246,8 @@ void *thread_uart_recv_back(void *arg){ if (debounceIndex >= 0) { keyDebounceList[debounceIndex].lastKeyTime = now; } else if (keyDebounceCount < MAX_KEY_DEBOUNCE) { - keyDebounceList[keyDebounceCount].tagCode = tagCode; + keyDebounceList[keyDebounceCount].tagCodeHead = tagCodeHead; + keyDebounceList[keyDebounceCount].tagCode = tagCode; keyDebounceList[keyDebounceCount].lastKeyTime = now; keyDebounceCount++; } @@ -2242,7 +2266,7 @@ void *thread_uart_recv_back(void *arg){ pendingLightTasks[i].reported && !pendingLightTasks[i].lightOffReported) { LOG_I("Key pressed - triggering immediate light-off for tag %08X (with task)\n", tagCode); - report_light_off(tagCode); + report_light_off(tagCodeHead, tagCode); found = true; break; } @@ -2260,7 +2284,8 @@ void *thread_uart_recv_back(void *arg){ uuid_generate(uuid); uuid_unparse(uuid, uuid_str); - snprintf(tagStr, sizeof(tagStr), "AD10%08X", tagCode); + // 使用完整的tagID + snprintf(tagStr, sizeof(tagStr), "%04X%08X", tagCodeHead, tagCode); snprintf(topic, sizeof(topic), "/sys/WcSubLightStrip/%s/thing/property/post", tagStr); struct timeval tv; @@ -2711,24 +2736,34 @@ void *thread_mqtt_recv(void *arg){ strncpy(mqtt_parm.msg_sn, g_mqtt_deviceName, sizeof(mqtt_parm.msg_sn) - 1); LOG_I("Set light bar ID: %s\n", mqtt_parm.msg_sn); - // 获取后6位并设置到lightsn1 + // 获取完整的12位设备ID int len = strlen(g_mqtt_deviceName); - if(len >= 6) { - char *last6 = g_mqtt_deviceName + (len - 6); + if(len == 12) { + char fullTagId[13] = {0}; + strncpy(fullTagId, g_mqtt_deviceName, 12); + + // 解析前4位作为tagCodeHead和后8位作为tagCode + uint16_t tagCodeHead = 0; + uint32_t tagCode = 0; + char head[5] = {0}; + char tail[9] = {0}; + + strncpy(head, fullTagId, 4); + strncpy(tail, fullTagId + 4, 8); + sscanf(head, "%hx", &tagCodeHead); + sscanf(tail, "%x", &tagCode); + + // 获取后6位设置到lightsn1 + char *last6 = fullTagId + 6; memset(lightsn1, 0, sizeof(lightsn1)); strncpy(lightsn1, last6, 6); - LOG_I("Set lightsn1 (last 6 digits): %s\n", lightsn1); - - // 将后6位转换为uint32_t并添加到待确认任务列表 - uint32_t tagCode = 0; - sscanf(last6, "%x", &tagCode); - LOG_I("Converted tagCode: %08X\n", tagCode); + LOG_I("Full tag ID: %s, head: %04X, tail: %08X, lightsn1: %s\n", fullTagId, tagCodeHead, tagCode, lightsn1); // 添加待确认的亮灯任务,传入真实的beep、flash、RGB数据 // flash值需要转换:changeflash=1表示常亮(上报0),changeflash=3表示闪烁(上报1) int flash_value = (changeflash == 3) ? 1 : 0; if(strlen(taskId) > 0) { - add_pending_light_task(tagCode, taskId, changesound, flash_value, r_val, g_val, b_val, mqtt_parm.msg_duration); + add_pending_light_task(tagCodeHead, tagCode, taskId, changesound, flash_value, r_val, g_val, b_val, mqtt_parm.msg_duration); } } }