From 149a4048ee21cff5cacfdbaebdd50ac1af72b3d9 Mon Sep 17 00:00:00 2001 From: zzh <838331105@qq.com> Date: Tue, 6 Jan 2026 09:15:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E4=B8=AAtopic?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E4=B8=8B=E5=8F=91=E6=97=B6=E4=B8=8D=E4=BC=9A?= =?UTF-8?q?=E4=BA=AE=E7=81=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 192 insertions(+), 13 deletions(-) diff --git a/main.c b/main.c index 081450d..c1d97af 100644 --- a/main.c +++ b/main.c @@ -19,6 +19,35 @@ extern void uuid_unparse(uuid_t uu, char *out); jt_led_or_group_package_t tags; jt_led_or_group_package_t led_ctrl; +// 灯光命令队列结构体 - 解决竞态条件问题 +#define MAX_LIGHT_COMMANDS 32 + +typedef struct { + char deviceName[16]; // 设备名称(12位十六进制) + char fullTagId[16]; // 完整的灯条ID + char taskId[64]; // 任务ID + uint16_t tagCodeHead; // 灯条ID头部 + uint32_t tagCode; // 灯条ID + uint8_t color; // 颜色设置 + uint8_t sound; // 声音设置 + uint8_t flash; // 闪烁设置 + int duration; // 持续时间 + int beep; // 蜂鸣器状态 + int flash_value; // 闪烁值(用于上报) + int light_r; // 红色 + int light_g; // 绿色 + int light_b; // 蓝色 + bool is_valid; // 命令是否有效 + uint64_t sequence; // 序列号,用于跟踪 +} light_command_t; + +// 命令队列和相关变量 +light_command_t light_commands[MAX_LIGHT_COMMANDS]; +int light_command_head = 0; +int light_command_tail = 0; +pthread_mutex_t lightCommandMutex = PTHREAD_MUTEX_INITIALIZER; +uint64_t command_sequence = 0; + // 函数声明 void light_status_report(void); void update_app(void); @@ -128,7 +157,7 @@ int fd; int UPCASE=0; int count_value=0; int getPayloadTime=100*1000;//usecond -char softwareVersion[16]="2.1.26"; +char softwareVersion[16]="2.1.27"; //char stationsn[16]="d126ei4lj4cc00";//TJ250995217957 //char productid[8]="10045"; //char appSecret[64]="s3izIliw0CF48Pcsi16rjOmoFRf5WEt8"; @@ -194,6 +223,13 @@ void add_pending_light_task(uint16_t tagCodeHead, uint32_t tagCode, const char * void report_light_success(uint16_t tagCodeHead, uint32_t tagCode); void report_light_off(uint16_t tagCodeHead, uint32_t tagCode); +// 命令队列操作函数 +int add_light_command(const char *deviceName, const char *taskId, uint16_t tagCodeHead, uint32_t tagCode, + uint8_t color, uint8_t sound, uint8_t flash, int duration, + int beep, int flash_value, int r, int g, int b); +int get_light_command(light_command_t *cmd); +void clear_light_command_queue(void); + /*================================================================================*/ // 上报灯条子设备登录 void report_lightbar_login(uint16_t tagCodeHead, uint32_t tagCode) { @@ -407,6 +443,83 @@ void report_light_off(uint16_t tagCodeHead, uint32_t tagCode) { LOG_I("No pending light task found for light-off report for tag %08X\n", tagCode); } +/*================================================================================*/ +// 命令队列操作函数实现 + +// 添加灯光命令到队列 +int add_light_command(const char *deviceName, const char *taskId, uint16_t tagCodeHead, uint32_t tagCode, + uint8_t color, uint8_t sound, uint8_t flash, int duration, + int beep, int flash_value, int r, int g, int b) { + pthread_mutex_lock(&lightCommandMutex); + + // 检查队列是否已满 + int next_tail = (light_command_tail + 1) % MAX_LIGHT_COMMANDS; + if (next_tail == light_command_head) { + LOG_I("Light command queue is full!\n"); + pthread_mutex_unlock(&lightCommandMutex); + return -1; + } + + // 添加新命令 + light_command_t *cmd = &light_commands[light_command_tail]; + memset(cmd, 0, sizeof(light_command_t)); + + strncpy(cmd->deviceName, deviceName, sizeof(cmd->deviceName) - 1); + strncpy(cmd->fullTagId, deviceName, sizeof(cmd->fullTagId) - 1); + strncpy(cmd->taskId, taskId, sizeof(cmd->taskId) - 1); + cmd->tagCodeHead = tagCodeHead; + cmd->tagCode = tagCode; + cmd->color = color; + cmd->sound = sound; + cmd->flash = flash; + cmd->duration = duration; + cmd->beep = beep; + cmd->flash_value = flash_value; + cmd->light_r = r; + cmd->light_g = g; + cmd->light_b = b; + cmd->is_valid = true; + cmd->sequence = ++command_sequence; + + LOG_I("Added light command to queue - device: %s, seq: %llu, RGB: %d,%d,%d\n", + deviceName, cmd->sequence, r, g, b); + + light_command_tail = next_tail; + pthread_mutex_unlock(&lightCommandMutex); + return 0; +} + +// 从队列获取灯光命令 +int get_light_command(light_command_t *cmd) { + pthread_mutex_lock(&lightCommandMutex); + + if (light_command_head == light_command_tail) { + // 队列为空 + pthread_mutex_unlock(&lightCommandMutex); + return -1; + } + + // 获取命令 + *cmd = light_commands[light_command_head]; + light_command_head = (light_command_head + 1) % MAX_LIGHT_COMMANDS; + + LOG_I("Got light command from queue - device: %s, seq: %llu\n", + cmd->deviceName, cmd->sequence); + + pthread_mutex_unlock(&lightCommandMutex); + return 0; +} + +// 清空命令队列 +void clear_light_command_queue(void) { + pthread_mutex_lock(&lightCommandMutex); + light_command_head = 0; + light_command_tail = 0; + memset(light_commands, 0, sizeof(light_commands)); + LOG_I("Light command queue cleared\n"); + pthread_mutex_unlock(&lightCommandMutex); +} + /*================================================================================*/ // 上报灯条子设备登出 void report_lightbar_logout(uint16_t tagCodeHead, uint32_t tagCode) { @@ -1946,11 +2059,25 @@ void *thread_uart_recv_ack(void *arg){ if(ret>0){ LOG_I("ack:%x\n",parm_ack); if(parm_ack==0x2323){ + // 【关键修改】从命令队列获取命令,而不是使用全局变量 + light_command_t cmd; + if(get_light_command(&cmd) != 0) { + LOG_I("No light command in queue, using fallback global variables\n"); + // 队列为空时的回退处理(保持兼容性) + memset(&cmd, 0, sizeof(cmd)); + strncpy(cmd.deviceName, g_mqtt_deviceName, sizeof(cmd.deviceName) - 1); + cmd.color = changecolor; + cmd.sound = changesound; + cmd.flash = changeflash; + cmd.tagCode = strtol(lightsn1, NULL, 16); + } + + // 使用队列中的命令参数构建控制包 jt_led_or_group_package_t led_ctrl={ - .s.color=changecolor, - .s.sound=changesound, + .s.color=cmd.color, + .s.sound=cmd.sound, .s.single=0, - .s.flash=changeflash, + .s.flash=cmd.flash, };//0xC1 11000001 flash高位 jt_led_or_group_package_t group={ .group=groupno, @@ -2005,9 +2132,10 @@ void *thread_uart_recv_ack(void *arg){ uint32_t tag9=strtol("014BEE",NULL,16); 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 tag1=cmd.tagCode; + LOG_I("Using command from queue - device: %s, seq: %llu, tag1=%08X, RGB: %d,%d,%d\n", + cmd.deviceName, cmd.sequence, tag1, cmd.light_r, cmd.light_g, cmd.light_b); uint32_t tag2=strtol(lightsn2,NULL,16); uint32_t tag3=strtol(lightsn3,NULL,16); uint32_t tag4=strtol(lightsn4,NULL,16); @@ -2129,7 +2257,9 @@ void *thread_uart_recv_ack(void *arg){ } if(isLightOnById){ - uart_data_send_lighton_by_id(&uartSend,0x00,0xFF,0x00000000,0xFFFFFFFF,led_ctrl,0x0000); + // 【关键修改】使用从队列获取的命令参数 + uart_data_send_lighton_by_id(&uartSend,0x00,0xFF,cmd.tagCode,cmd.tagCode,led_ctrl,0x0000); + LOG_I("LightOnById: sent command for device %s, tagCode=%08X\n", cmd.deviceName, cmd.tagCode); isLightOnById=false; } @@ -2596,6 +2726,7 @@ void *thread_mqtt_recv(void *arg){ // 解析params中的各个字段 char params_str[1024] = {0}; + char params_json[1024] = {0}; // 【修复】移到外面,扩大作用域 char color_json[512] = {0}; // 提前声明color_json int params_ret = get_string_from_json_string_by_key(payload, "params", params_str, sizeof(params_str)); LOG_I("get_string_from_json_string_by_key return: %d\n", params_ret); @@ -2605,6 +2736,13 @@ void *thread_mqtt_recv(void *arg){ if(strlen(params_str) == 0) { LOG_I("params_str is empty, trying direct parse from payload\n"); // 直接从payload解析各个字段 + + // 【新增】解析LightSwitch字段 + int light_switch = 1; // 默认为开灯 + if(get_int_from_json_string_by_key(payload, "LightSwitch", &light_switch) == 0) { + LOG_I("Direct parse LightSwitch = %d\n", light_switch); + } + int beep_enable = 0; get_int_from_json_string_by_key(payload, "beep", &beep_enable); LOG_I("Direct parse Beep = %d\n", beep_enable); @@ -2638,10 +2776,15 @@ void *thread_mqtt_recv(void *arg){ LOG_I("color_json: %s\n", color_json); } else { // 包装params_str为有效的JSON对象 - char params_json[1024] = {0}; snprintf(params_json, sizeof(params_json), "{%s}", params_str); LOG_I("params_json: %s\n", params_json); + // 【新增】解析LightSwitch字段 + int light_switch = 1; // 默认为开灯 + if(get_int_from_json_string_by_key(params_json, "LightSwitch", &light_switch) == 0) { + LOG_I("Parse LightSwitch = %d\n", light_switch); + } + int beep_enable = 0; get_int_from_json_string_by_key(params_json, "beep", &beep_enable); LOG_I("Beep = %d\n", beep_enable); @@ -2693,8 +2836,24 @@ void *thread_mqtt_recv(void *arg){ LOG_I("RGB values: R=%d, G=%d, B=%d\n", r_val, g_val, b_val); // 根据RGB值设置颜色(0=不亮, 1=亮) - if(r_val == 0 && g_val == 0 && b_val == 0) { - changecolor = 0; // 不亮 + // 【修复】先保存原始RGB值,用于判断是否是关灯命令 + bool is_off_command = false; + + // 如果LightSwitch=0,标记为关灯命令 + int light_switch = 1; + if(strlen(params_str) > 0) { + get_int_from_json_string_by_key(params_json, "LightSwitch", &light_switch); + } else { + get_int_from_json_string_by_key(payload, "LightSwitch", &light_switch); + } + + if(light_switch == 0) { + is_off_command = true; + LOG_I("LightSwitch=0 detected, this is an OFF command\n"); + } + + if(r_val == 0 && g_val == 0 && b_val == 0 && !is_off_command) { + changecolor = 0; // 不亮(非关灯命令时的默认值) } else if(r_val == 1 && g_val == 0 && b_val == 0) { changecolor = 4; // 红色 } else if(r_val == 0 && g_val == 1 && b_val == 0) { @@ -2709,8 +2868,10 @@ void *thread_mqtt_recv(void *arg){ changecolor = 3; // 青色 } else if(r_val == 1 && g_val == 1 && b_val == 1) { changecolor = 7; // 白色 + } else if(is_off_command) { + changecolor = 0; // 关灯命令强制设置为不亮 } - LOG_I("changecolor=%d\n", changecolor); + LOG_I("changecolor=%d (is_off_command=%d)\n", changecolor, is_off_command); // 判断任务类型:根据method字段判断是灯条任务还是OTA任务 char method[128] = {0}; @@ -2753,7 +2914,7 @@ void *thread_mqtt_recv(void *arg){ sscanf(head, "%hx", &tagCodeHead); sscanf(tail, "%x", &tagCode); - // 获取后6位设置到lightsn1 + // 获取后6位设置到lightsn1(保留兼容性) char *last6 = fullTagId + 6; memset(lightsn1, 0, sizeof(lightsn1)); strncpy(lightsn1, last6, 6); @@ -2765,6 +2926,16 @@ void *thread_mqtt_recv(void *arg){ if(strlen(taskId) > 0) { add_pending_light_task(tagCodeHead, tagCode, taskId, changesound, flash_value, r_val, g_val, b_val, mqtt_parm.msg_duration); } + + // 【关键修改】将命令添加到队列,而不是设置全局变量 + // 这样可以避免快速连续命令时的竞态条件 + if(add_light_command(g_mqtt_deviceName, taskId, tagCodeHead, tagCode, + changecolor, changesound, changeflash, mqtt_parm.msg_duration, + changesound, flash_value, r_val, g_val, b_val) == 0) { + LOG_I("Light command added to queue successfully\n"); + } else { + LOG_I("Failed to add light command to queue - queue full!\n"); + } } } } else { @@ -2998,6 +3169,14 @@ int main(int argc, char *argv[]) char networktype[32]={0}; LOG_I("version:%s\n",softwareVersion); + + // 【新增】初始化命令队列 + memset(light_commands, 0, sizeof(light_commands)); + light_command_head = 0; + light_command_tail = 0; + command_sequence = 0; + LOG_I("Light command queue initialized\n"); + system("insmod /system/lib/modules/wk2xxx_spi.ko"); system("timedatectl set-timezone Asia/Shanghai"); uart_open(&uartSend,"/dev/ttyS0");//U12 ttyS0,U14 ttyS4,U21 ttysWK0 U13 ttysWK1 U15 ttysWK2 U22 ttysWK3 U20 ttyS1