From 30700b9178b2bc6e154e7d6c6bc7622b3f126791 Mon Sep 17 00:00:00 2001 From: zzh <838331105@qq.com> Date: Wed, 24 Dec 2025 10:25:33 +0800 Subject: [PATCH] =?UTF-8?q?=20=E6=9B=B4=E6=96=B0=E4=BA=AE=E7=81=AF?= =?UTF-8?q?=E6=88=90=E5=8A=9F=E4=B8=8A=E6=8A=A5,mqtt=20=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=88=90=E5=8A=9F=E6=97=B6=E9=9A=8F=E6=9C=BA=E9=97=AA=E7=83=81?= =?UTF-8?q?=E9=BB=84=E7=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.c | 189 ++++++++++++++++++++++++++++++++++++---- mqtt_utils/mqtt_utils.c | 73 +++++++++++++++- 2 files changed, 239 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index e667c02..8f88225 100644 --- a/main.c +++ b/main.c @@ -68,7 +68,7 @@ int tagCount=0; // 心跳检测相关 #define HEARTBEAT_TIMEOUT_SEC (30 * 60) // 30分钟超时 -#define MAX_LIGHTBAR_NUM 200 +#define MAX_LIGHTBAR_NUM 5000 typedef struct { uint32_t tagCode; // 灯条ID time_t lastHeartbeat; // 最后心跳时间 @@ -77,6 +77,23 @@ typedef struct { lightbar_heartbeat_t lightbarHeartbeat[MAX_LIGHTBAR_NUM] = {0}; int lightbarHeartbeatCount = 0; pthread_mutex_t heartbeatMutex = PTHREAD_MUTEX_INITIALIZER; + +// 亮灯任务确认相关 +#define MAX_PENDING_LIGHT_TASKS 50 +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; // 是否已上报 + time_t createTime; // 创建时间 +} pending_light_task_t; +pending_light_task_t pendingLightTasks[MAX_PENDING_LIGHT_TASKS] = {0}; +int pendingLightTaskCount = 0; +pthread_mutex_t lightTaskMutex = PTHREAD_MUTEX_INITIALIZER; pthread_t pt_heartbeat_check; int lightbars_size=0; int lightbars_count=0; @@ -149,6 +166,8 @@ 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); +void report_light_success(uint32_t tagCode); /*================================================================================*/ // 上报灯条子设备登录 @@ -192,6 +211,112 @@ void report_lightbar_login(uint32_t tagCode) { mqtt_utils_publish(&mqtt_config, topic, 0, payload, strlen(payload)); } +/*================================================================================*/ +// 添加待确认的亮灯任务 +void add_pending_light_task(uint32_t tagCode, const char *taskId, int beep, int flash, int r, int g, int b) { + pthread_mutex_lock(&lightTaskMutex); + + // 检查是否已存在 + for (int i = 0; i < pendingLightTaskCount; i++) { + if (pendingLightTasks[i].tagCode == tagCode && !pendingLightTasks[i].reported) { + // 更新任务信息 + strncpy(pendingLightTasks[i].taskId, taskId, sizeof(pendingLightTasks[i].taskId) - 1); + pendingLightTasks[i].beep = beep; + pendingLightTasks[i].flash = flash; + pendingLightTasks[i].light_r = r; + pendingLightTasks[i].light_g = g; + pendingLightTasks[i].light_b = b; + pendingLightTasks[i].createTime = time(NULL); + LOG_I("Updated pending light task for tag %08X, taskId: %s, beep: %d, flash: %d, RGB: %d,%d,%d\n", + tagCode, taskId, beep, flash, r, g, b); + pthread_mutex_unlock(&lightTaskMutex); + return; + } + } + + // 添加新任务 + if (pendingLightTaskCount < MAX_PENDING_LIGHT_TASKS) { + pendingLightTasks[pendingLightTaskCount].tagCode = tagCode; + strncpy(pendingLightTasks[pendingLightTaskCount].taskId, taskId, + sizeof(pendingLightTasks[pendingLightTaskCount].taskId) - 1); + pendingLightTasks[pendingLightTaskCount].beep = beep; + pendingLightTasks[pendingLightTaskCount].flash = flash; + pendingLightTasks[pendingLightTaskCount].light_r = r; + pendingLightTasks[pendingLightTaskCount].light_g = g; + pendingLightTasks[pendingLightTaskCount].light_b = b; + pendingLightTasks[pendingLightTaskCount].reported = false; + pendingLightTasks[pendingLightTaskCount].createTime = time(NULL); + LOG_I("Added pending light task for tag %08X, taskId: %s, beep: %d, flash: %d, RGB: %d,%d,%d\n", + tagCode, taskId, beep, flash, r, g, b); + pendingLightTaskCount++; + } else { + LOG_I("Pending light task queue full!\n"); + } + + pthread_mutex_unlock(&lightTaskMutex); +} + +/*================================================================================*/ +// 上报亮灯成功 +void report_light_success(uint32_t tagCode) { + pthread_mutex_lock(&lightTaskMutex); + + // 查找对应的待确认任务 + for (int i = 0; i < pendingLightTaskCount; i++) { + if (pendingLightTasks[i].tagCode == tagCode && !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); + + // 获取当前时间戳(毫秒) + struct timeval tv; + gettimeofday(&tv, NULL); + long long timestamp = (long long)tv.tv_sec * 1000 + tv.tv_usec / 1000; + + // 使用任务中的真实数据构建payload + // light是一个struct,包含R、G、B三个bool字段 + snprintf(payload, sizeof(payload), + "{\"id\":\"%s\",\"code\":0,\"msg\":\"success\",\"data\":{\"beep\":{\"value\":%d,\"time\":%lld},\"flash\":{\"value\":%d,\"time\":%lld},\"light\":{\"value\":{\"R\":%d,\"G\":%d,\"B\":%d},\"time\":%lld}},\"method\":\"thing.service.lightOperate.invoke\",\"time\":%lld}", + pendingLightTasks[i].taskId, + pendingLightTasks[i].beep, + timestamp, + pendingLightTasks[i].flash, + timestamp, + pendingLightTasks[i].light_r, + pendingLightTasks[i].light_g, + pendingLightTasks[i].light_b, + timestamp, + timestamp); + + LOG_I("Reporting light success - topic: %s\n", topic); + LOG_I("Reporting light success - payload: %s\n", payload); + LOG_I("Task ID: %s, beep: %d, flash: %d, RGB: %d,%d,%d\n", + pendingLightTasks[i].taskId, pendingLightTasks[i].beep, + pendingLightTasks[i].flash, pendingLightTasks[i].light_r, + pendingLightTasks[i].light_g, pendingLightTasks[i].light_b); + + // 发送MQTT消息 + mqtt_utils_publish(&mqtt_config, topic, 0, payload, strlen(payload)); + + // 标记为已上报 + pendingLightTasks[i].reported = true; + + pthread_mutex_unlock(&lightTaskMutex); + return; + } + } + + LOG_I("No pending light task found for tag %08X\n", tagCode); + pthread_mutex_unlock(&lightTaskMutex); +} + /*================================================================================*/ // 上报灯条子设备登出 void report_lightbar_logout(uint32_t tagCode) { @@ -1756,6 +1881,8 @@ void *thread_uart_recv_ack(void *arg){ uint32_t tag10=strtol("014BF0",NULL,16); #else uint32_t tag1=strtol(lightsn1,NULL,16); + LOG_I("lightsn1=%s, tag1=%08X, tag_bytes: %02X %02X %02X\n", + lightsn1, tag1, (tag1>>16)&0xFF, (tag1>>8)&0xFF, tag1&0xFF); uint32_t tag2=strtol(lightsn2,NULL,16); uint32_t tag3=strtol(lightsn3,NULL,16); uint32_t tag4=strtol(lightsn4,NULL,16); @@ -1931,6 +2058,10 @@ void *thread_uart_recv_data(void *arg){ &count,&batteryV,&version,&ledCtrl,&signCode,&reserve,&lableParm); LOG_I("recv_data:%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); + + // 检查是否有待确认的亮灯任务,如果tag匹配则上报亮灯成功 + report_light_success(tagCode); + isStopBroadcastBegin=true; //sleep(2); } @@ -2245,6 +2376,9 @@ void *thread_mqtt_recv(void *arg){ items_size = 0; colors_size = 0; + // 清空设备名称,避免串用上一次的值 + //memset(g_mqtt_deviceName, 0, sizeof(g_mqtt_deviceName)); + // 解析新格式payload LOG_I("Parsing new payload format with params\n"); @@ -2300,10 +2434,10 @@ void *thread_mqtt_recv(void *arg){ LOG_I("Beep = %d\n", beep_enable); changesound = beep_enable ? 1 : 0; - int flashing_enable = 0; - get_int_from_json_string_by_key(params_json, "flashing", &flashing_enable); - changeflash = flashing_enable ? 3 : 1; // 3=闪烁, 1=常亮 - LOG_I("Flashing = %d, changeflash = %d\n", flashing_enable, changeflash); + int flash_enable = 0; + get_int_from_json_string_by_key(params_json, "flash", &flash_enable); + changeflash = flash_enable ? 3 : 1; // 1=闪烁, 3=常亮(注意:flash=1表示闪烁) + LOG_I("Flash = %d, changeflash = %d\n", flash_enable, changeflash); int duration = 0; get_int_from_json_string_by_key(params_json, "duration", &duration); @@ -2372,6 +2506,11 @@ void *thread_mqtt_recv(void *arg){ items_size = 1; lightbars_size = 1; + // 解析id字段 + char taskId[64] = {0}; + get_string_from_json_string_by_key(payload, "id", taskId, sizeof(taskId)); + LOG_I("Task ID: %s\n", taskId); + // 从topic解析出的deviceName获取设备ID if(strlen(g_mqtt_deviceName) > 0) { LOG_I("Device ID from topic: %s\n", g_mqtt_deviceName); @@ -2387,6 +2526,18 @@ void *thread_mqtt_recv(void *arg){ 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); + + // 添加待确认的亮灯任务,传入真实的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); + } } } } else { @@ -2845,13 +2996,13 @@ int main(int argc, char *argv[]) // } #if 1 - ret = pthread_create(&pt_simulate_light,NULL,thread_simulate_light,NULL); - if(ret!=0){ - LOG_I("pthread_create simulate_light fail\n"); - }else{ - LOG_I("pthread_create simulate_light success\n"); - pthread_detach(pt_simulate_light); - } + //ret = pthread_create(&pt_simulate_light,NULL,thread_simulate_light,NULL); + //if(ret!=0){ + // LOG_I("pthread_create simulate_light fail\n"); + //}else{ + // LOG_I("pthread_create simulate_light success\n"); + // pthread_detach(pt_simulate_light); + //} ret = pthread_create(&pt_all_light,NULL,thread_all_light,NULL); if(ret!=0){ @@ -2861,13 +3012,13 @@ int main(int argc, char *argv[]) pthread_detach(pt_all_light); } - ret = pthread_create(&pt_simulate_mqtt_topic,NULL,thread_simulate_mqtt_topic,NULL); - if(ret!=0){ - LOG_I("pthread_create simulate_mqtt_topic fail\n"); - }else{ - LOG_I("pthread_create simulate_mqtt_topic success\n"); - pthread_detach(pt_simulate_mqtt_topic); - } + //ret = pthread_create(&pt_simulate_mqtt_topic,NULL,thread_simulate_mqtt_topic,NULL); + //if(ret!=0){ + // LOG_I("pthread_create simulate_mqtt_topic fail\n"); + //}else{ + // LOG_I("pthread_create simulate_mqtt_topic success\n"); + // pthread_detach(pt_simulate_mqtt_topic); + //} #endif #if 0 readresult=file_to_buffer("mqttRawPassword",&len); diff --git a/mqtt_utils/mqtt_utils.c b/mqtt_utils/mqtt_utils.c index fd50a31..387905e 100644 --- a/mqtt_utils/mqtt_utils.c +++ b/mqtt_utils/mqtt_utils.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include "mqtt_utils.h" @@ -120,7 +123,55 @@ json_error: json_object_put(root); } +// 黄灯闪烁相关 +static pthread_t pt_yellow_led_flash; +static volatile bool yellow_led_flash_running = false; +static pthread_mutex_t yellow_led_mutex = PTHREAD_MUTEX_INITIALIZER; + +void *thread_yellow_led_flash(void *arg); + +void *thread_yellow_led_flash(void *arg) { + LOG_I("Yellow LED flash thread started\n"); + + // 初始化随机种子 + srand((unsigned int)time(NULL)); + + while (yellow_led_flash_running) { + // 生成随机延时 (100ms - 500ms) + int delay_us = 100000 + (rand() % 400000); // 100000-500000 微秒 + + // 点亮黄灯 + system("echo 1 > /sys/class/gpio/gpio114/value"); + + // 随机延时保持亮 + usleep(delay_us); + + // 检查是否需要退出 + if (!yellow_led_flash_running) break; + + // 熄灭黄灯 + system("echo 0 > /sys/class/gpio/gpio114/value"); + + // 随机延时保持灭 + usleep(delay_us); + } + + // 确保退出时灯是灭的 + system("echo 0 > /sys/class/gpio/gpio114/value"); + LOG_I("Yellow LED flash thread exited\n"); + return NULL; +} + void mqtt_net_failure(int *failure_times){ + // 停止黄灯闪烁 + pthread_mutex_lock(&yellow_led_mutex); + if (yellow_led_flash_running) { + yellow_led_flash_running = false; + pthread_join(pt_yellow_led_flash, NULL); + LOG_I("Yellow LED flash thread stopped\n"); + } + pthread_mutex_unlock(&yellow_led_mutex); + system("echo 0 > /sys/class/gpio/gpio114/value"); if(failure_times != NULL){ (*failure_times)++; @@ -257,12 +308,12 @@ int mqtt_utils_message_arrived(void *context, char *topicName, int topicLen, MQT char field2[256] = {0}; if (mqtt_utils_parse_sys_lightOperate_invoke_topic(topicName, field1, sizeof(field1), field2, sizeof(field2)) == 0) { - // LOG_I("lightOperate/invoke 匹配字段: productKey=%s, deviceName=%s\n", field1, field2); + LOG_I("lightOperate/invoke 匹配字段: productKey=%s, deviceName=%s\n", field1, field2); // 将deviceName存储到全局变量中 memset(g_mqtt_deviceName, 0, sizeof(g_mqtt_deviceName)); strncpy(g_mqtt_deviceName, field2, sizeof(g_mqtt_deviceName) - 1); } else { - // LOG_I("lightOperate/invoke topic字段解析失败: %s\n", topicName); + LOG_I("lightOperate/invoke topic字段解析失败: %s\n", topicName); } } @@ -330,7 +381,21 @@ void mqtt_utils_connected(void *context, char *cause){ // LOG_I("公共topic订阅请求结果: %d\n", public_subscribe_result); // LOG_I("=== 公共topic订阅完成 ===\n"); - system("echo 1 > /sys/class/gpio/gpio114/value");//yellow ok + // 启动黄灯闪烁线程 + pthread_mutex_lock(&yellow_led_mutex); + if (!yellow_led_flash_running) { + yellow_led_flash_running = true; + int ret = pthread_create(&pt_yellow_led_flash, NULL, thread_yellow_led_flash, NULL); + if (ret != 0) { + LOG_I("Failed to create yellow LED flash thread, using constant on\n"); + yellow_led_flash_running = false; + system("echo 1 > /sys/class/gpio/gpio114/value");//yellow ok + } else { + pthread_detach(pt_yellow_led_flash); + LOG_I("Yellow LED flash thread started\n"); + } + } + pthread_mutex_unlock(&yellow_led_mutex); station_status_report(); // 设置MQTT连接标志 @@ -512,7 +577,7 @@ int mqtt_utils_init(mqtt_utils_t *mqtt_config) sprintf(subscribeTopics[subscribeTopicCount++], "/iot/estation%s/bind", mqtt_conf->username); sprintf(subscribeTopics[subscribeTopicCount++], "/iot/estation%s/group", mqtt_conf->username); sprintf(subscribeTopics[subscribeTopicCount++], "/iot%s/thing/ota/upgrade", mqtt_conf->username); - sprintf(subscribeTopics[subscribeTopicCount++], "/sys/WcSubLightStrip/AD1000014C11/thing/service/lightOperate/invoke"); + // 只使用通配符订阅,覆盖所有设备的lightOperate消息 sprintf(subscribeTopics[subscribeTopicCount++], "/sys/+/+/thing/service/lightOperate/invoke"); // LOG_I("设置了%d个订阅topic:\n", subscribeTopicCount);