修复多个topic同时下发时不会亮灯问题

This commit is contained in:
zzh 2026-01-06 09:15:16 +08:00
parent 94e0a87858
commit 149a4048ee

205
main.c
View File

@ -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