修复灯条上报tag与收到的tag不正确的问题

This commit is contained in:
zzh 2025-12-30 09:37:45 +08:00
parent e8ecd07272
commit 48e7151ac0

199
main.c
View File

@ -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; // 灯条IDtag的后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);
}
}
}