AP05/main.c

3576 lines
139 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "main.h"
#define PRINT_TIME_TAG
#define DBG_TAG "main"
#define DBG_LVL DBG_INFO
#include "debug_print.h"
#include <sys/prctl.h>
#include <sys/statvfs.h>
#include "curl_arm64/include/curl.h"
#include "redis_sn/redis_sn_client.h"
#if 0
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/serial.h>
#define DMA_START_TX _IOW('U', 0x10, struct dma_config)
struct dma_config {
void *buf;
size_t len;
};
#endif
pthread_t pt_uart_send;
pthread_t pt_uart_recv_ack;
pthread_t pt_uart_recv_data;
pthread_t pt_uart_recv_back;
pthread_t pt_vm_heartbeat;
pthread_t pt_mqtt_recv;
pthread_t pt_readqr; // 禁用二维码扫描线程
pthread_t pt_ota;
pthread_t pt_doota;
pthread_t pt_mqtt;
pthread_t pt_removelog;
pthread_t pt_reboot;
pthread_t pt_watchdog;
pthread_t pt_tagsearch;
pthread_t pt_removeduplicatetag;
pthread_t pt_simulate_3027; // 模拟3027任务线程
uart_utils_t uartSend = {0};
uart_utils_t uartRecvData = {0};
uart_utils_t uartRecvBack = {0};
mqtt_parm_t mqtt_parm={0};
mqtt_utils_t mqtt_config;
struct input_event buff;
bool isTimeToReboot=false;
bool isLightOn=false;
bool isLightOnByRule=false;
bool isLabelUp=false;
bool isSearchLabel=false;
bool isSearchReport=false;
bool isSearchLabelOn=false;
bool isSearchLabelOntest=false;
bool isLightEnable=true;
bool isSendComEnd=true;
bool isOtaEnable=false;
bool isLEDOtaSuccess=false;
bool isAPOtaSuccess=false;
bool isAPBack=false;
jt_only_tag_t onlyTags[5000]={0};
jt_only_tag_t onlyTagsNew[5000]={0};
int tagCount=0;
int tagCountNew=0;
int tagIndex=0;
int otaCount=0;
int fd;
int UPCASE=0;
int count_value=0;
int getPayloadTime=120*1000;//usecond
char softwareVersion[16]="1.1.40";
char stationsn[16]="TJ251372224247";//TJ250995217957
char productid[8]="10045";
char appKey[32]="fdhQmhqhvbL1cf1K9mUqt";
char appSecret[64]="s3izIliw0CF48Pcsi16rjOmoFRf5WEt8";
char mqttRawPassword[64]="";
char input_value[1024]={0};//94b4e39caf1d45ee9a071d701cc037b4
char input_value_copy[1024]={0};
char *getDevRegisterStatusUrl="https://gaea-zt-express.com/device/modifyRegisterInfo";
//char *logUploadUrl="http://pda.pupumall.net:1180/open/api/device/log/upload";
char *getDevRawPasswordUrl="https://gaea.zt-express.com/device/modifyRegisterInfo";
char *hostDomain="tx-mqtt.zt-express.com";
char lightsn1[32]={0};
char lightsn2[32]={0};
char lightsn3[32]={0};
char lightsn4[32]={0};
char lightsn5[32]={0};
char lightsn6[32]={0};
char lightsn7[32]={0};
char lightsn8[32]={0};
char lightsn9[32]={0};
char lightsn10[32]={0};
char lightsn11[32]={0};
char lightsn12[32]={0};
char lightsn13[32]={0};
char lightsn14[32]={0};
char lightsn15[32]={0};
char lightsn16[32]={0};
char lightsn17[32]={0};
char lightsn18[32]={0};
char lightsn19[32]={0};
char lightsn20[32]={0};
char lightsn21[32]={0};
char lightsn22[32]={0};
char lightsn23[32]={0};
char lightsn24[32]={0};
char lightsn25[32]={0};
char lightsn26[32]={0};
char lightsn27[32]={0};
char lightsn28[32]={0};
char lightsn29[32]={0};
char lightsn30[32]={0};
int searchTimeOut=0;
int searchTimeOld=0;
int searchTimeNew=0;
int lightsnNum=0;
int mqtt_port=1883;
uint32_t Tag1=0;
uint32_t Tag2=0;
uint32_t Tag3=0;
uint32_t Tag4=0;
uint32_t Tag5=0;
static time_t last_2323_time = 0; // 记录上次收到0x2323的时间
static bool waiting_for_4646 = false; // 是否在等待0x4646
// ====== 3015合并点亮相关全局变量 ======
#define MAX_LIGHTSN_BUFFER 4096
static char lightsn_buffer[MAX_LIGHTSN_BUFFER][32] = {0};
static char color_buffer[MAX_LIGHTSN_BUFFER][8] = {0}; // 颜色缓冲区与sn一一对应
static char sound_buffer[MAX_LIGHTSN_BUFFER][8] = {0}; // 声音缓冲区
static char flash_buffer[MAX_LIGHTSN_BUFFER][8] = {0}; // 闪光缓冲区
static int lightsn_buffer_count = 0;
static time_t first_3015_time = 0;
static bool is_3015_collecting = false;
static pthread_mutex_t lightsn_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
// 3022合包缓存定义放在文件顶部或main函数外部
#define LABEL_BATCH_SIZE 20
static uint32_t tags_buf[LABEL_BATCH_SIZE] = {0};
static uint8_t lable1_buf[LABEL_BATCH_SIZE] = {0};
static uint16_t lable2_buf[LABEL_BATCH_SIZE] = {0};
static uint32_t lable3_buf[LABEL_BATCH_SIZE] = {0};
static int label_buf_count = 0;
static time_t label_buf_first_time = 0;
// 函数声明
void *thread_timeout_check(void *arg);
void *thread_3015_lighton_merge(void *arg);
void *thread_label_batch_send(void *arg);
void *thread_simulate_3027_task(void *arg);
int getLedOtaVersion(char *filename);
int getApOtaVersion(char *filename,char *modename);
void hmacsha1(char *key,char* data,char *signbase64,int signbase64_len);
void light_off_tag_report(uint32_t name,uint16_t batteryv);
void light_battery_report(uint32_t tagCode, uint16_t batteryV);
void search_tag_report();
void copyOnlyTag(void);
// 安全的命令执行函数
static int safe_exec_cmd(const char *cmd) {
LOG_I("Executing command: %s\n", cmd);
int ret = system(cmd);
if (ret != 0) {
LOG_E("Command failed: %s, return code: %d, error: %s", cmd, ret, strerror(errno));
// 如果是init.d脚本失败记录更多信息
if (strstr(cmd, "/etc/init.d/tx_server") != NULL) {
FILE *log_file = fopen("/var/log/tx_server_restart.log", "a");
if (log_file != NULL) {
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
char time_str[26];
strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);
fprintf(log_file, "[%s] DEBUG: Command that failed: %s\n", time_str, cmd);
fprintf(log_file, "[%s] DEBUG: Return code: %d\n", time_str, ret);
fprintf(log_file, "[%s] DEBUG: errno: %d (%s)\n", time_str, errno, strerror(errno));
// 检查脚本是否存在且可执行
if (access("/etc/init.d/tx_server", F_OK) == 0) {
fprintf(log_file, "[%s] DEBUG: Script exists\n", time_str);
if (access("/etc/init.d/tx_server", X_OK) == 0) {
fprintf(log_file, "[%s] DEBUG: Script is executable\n", time_str);
} else {
fprintf(log_file, "[%s] DEBUG: Script is NOT executable\n", time_str);
}
} else {
fprintf(log_file, "[%s] DEBUG: Script does NOT exist\n", time_str);
}
fclose(log_file);
}
}
return -1;
}
LOG_I("Command succeeded: %s\n", cmd);
return 0;
}
// 兼容的服务重启函数支持systemctl和init.d两种方式
int restart_tx_server_service(void) {
// 首先尝试使用systemctl方式
if (access("/bin/systemctl", F_OK) == 0) {
LOG_I("Using systemctl to restart tx_server service\n");
int ret = safe_exec_cmd("systemctl restart tx_server");
if (ret == 0) {
LOG_I("Successfully restarted tx_server using systemctl\n");
return 0;
} else {
LOG_W("systemctl restart failed, trying init.d method\n");
}
}
// 如果systemctl不可用或失败尝试使用init.d方式
if (access("/etc/init.d/tx_server", F_OK) == 0) {
LOG_I("Using init.d script to restart tx_server service\n");
// 详细诊断信息
FILE *log_file = fopen("/var/log/tx_server_restart.log", "a");
if (log_file != NULL) {
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
char time_str[26];
strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);
// 记录执行前的系统状态
fprintf(log_file, "[%s] INFO: Starting tx_server restart process\n", time_str);
fprintf(log_file, "[%s] INFO: Current UID: %d, GID: %d\n", time_str, getuid(), getgid());
// 检查脚本权限
struct stat st;
if (stat("/etc/init.d/tx_server", &st) == 0) {
fprintf(log_file, "[%s] INFO: Script permissions: %o\n", time_str, st.st_mode & 0777);
fprintf(log_file, "[%s] INFO: Script owner: %d, group: %d\n", time_str, st.st_uid, st.st_gid);
}
// 检查当前进程状态
fprintf(log_file, "[%s] INFO: Current working directory: ", time_str);
char cwd[256];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
fprintf(log_file, "%s\n", cwd);
} else {
fprintf(log_file, "unknown\n");
}
// 检查环境变量
fprintf(log_file, "[%s] INFO: PATH=%s\n", time_str, getenv("PATH") ? getenv("PATH") : "not set");
fclose(log_file);
}
system("echo 0 > /sys/class/gpio/gpio1/value");
int ret = safe_exec_cmd("/etc/init.d/tx_server restart");
log_file = fopen("/var/log/tx_server_restart.log", "a");
if (log_file != NULL) {
time_t now = time(NULL);
struct tm *tm_info = localtime(&now);
char time_str[26];
strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);
if (ret == 0) {
fprintf(log_file, "[%s] SUCCESS: tx_server restarted successfully using init.d\n", time_str);
LOG_I("Successfully restarted tx_server using init.d\n");
} else {
fprintf(log_file, "[%s] FAILED: tx_server restart failed using init.d (return code: %d)\n", time_str, ret);
fprintf(log_file, "[%s] ERROR: errno=%d, error=%s\n", time_str, errno, strerror(errno));
LOG_E("init.d restart also failed\n");
// 尝试获取更多错误信息
FILE *cmd_output = popen("/etc/init.d/tx_server restart 2>&1", "r");
if (cmd_output != NULL) {
char buffer[1024];
fprintf(log_file, "[%s] DEBUG: Command output:\n", time_str);
while (fgets(buffer, sizeof(buffer), cmd_output) != NULL) {
fprintf(log_file, "[%s] DEBUG: %s", time_str, buffer);
}
pclose(cmd_output);
}
}
fclose(log_file);
}
if (ret == 0) {
return 0;
}
} else {
LOG_E("Neither systemctl nor init.d script found for tx_server\n");
}
LOG_E("All service restart methods failed\n");
return -1;
}
/*================================================================================*/
void doCommand_help(int argc, char *argv[])
{
printf("************************************************************\r\n"\
"all commands are case insensitive\r\n"\
"help print this message\r\n"\
"SND [01-60] set sound S01-S60\r\n"\
"************************************************************\r\n");
}
static int safe_rename(const char *src, const char *dst) {
if (rename(src, dst) != 0) {
LOG_E("Failed to rename %s to %s: %s", src, dst, strerror(errno));
return -1;
}
return 0;
}
static int safe_remove_dir(const char *path) {
if (rmdir(path) != 0) {
LOG_E("Failed to remove directory %s: %s", path, strerror(errno));
return -1;
}
return 0;
}
static int safe_remove_file(const char *path) {
if (unlink(path) != 0) {
LOG_E("Failed to remove file %s: %s", path, strerror(errno));
return -1;
}
return 0;
}
static int safe_mkdir(const char *path) {
if (mkdir(path, 0755) != 0 && errno != EEXIST) {
LOG_E("Failed to create directory %s: %s", path, strerror(errno));
return -1;
}
return 0;
}
void doCommand(int argc, char *argv[])
{
//sendData(argv[1],argv[0]);
}
__command_initialize("RON", doCommand);
__command_initialize("help",doCommand_help);
/*================================================================================*/
void do_removelog(void)
{
LOG_I("%s\n",__func__);
FILE *fp;
char buffer[5];
char syscmd[32];
int logcount=0;
fp=popen("ls Log.*|wc -l", "r");
if (fp) {
fgets(buffer,sizeof(buffer),fp);
logcount=atoi(buffer);
pclose(fp);
}
LOG_I("logcount:%d\n",logcount);
if(logcount>=2){
sprintf(syscmd,"ls Log.*|head -%d|xargs rm -fr",logcount-1);
LOG_I("%s\n",syscmd);
system(syscmd);
}else{
LOG_I("logcount less than 3,not remove\n");
}
}
// 获取CPU使用率
float get_cpu_usage() {
FILE *fp;
char buf[256];
unsigned long long user1, nice1, system1, idle1, iowait1, irq1, softirq1, steal1;
unsigned long long user2, nice2, system2, idle2, iowait2, irq2, softirq2, steal2;
fp = fopen("/proc/stat", "r");
fgets(buf, sizeof(buf), fp);
sscanf(buf, "cpu %llu %llu %llu %llu %llu %llu %llu %llu", &user1, &nice1, &system1, &idle1, &iowait1, &irq1, &softirq1, &steal1);
fclose(fp);
usleep(1000000); // 1秒采样
fp = fopen("/proc/stat", "r");
fgets(buf, sizeof(buf), fp);
sscanf(buf, "cpu %llu %llu %llu %llu %llu %llu %llu %llu", &user2, &nice2, &system2, &idle2, &iowait2, &irq2, &softirq2, &steal2);
fclose(fp);
unsigned long long total1 = user1+nice1+system1+idle1+iowait1+irq1+softirq1+steal1;
unsigned long long total2 = user2+nice2+system2+idle2+iowait2+irq2+softirq2+steal2;
unsigned long long idle_diff = idle2 - idle1;
unsigned long long total_diff = total2 - total1;
if (total_diff == 0) return 0.0;
return 100.0 * (1.0 - (float)idle_diff / total_diff);
}
// 获取内存信息
void get_mem_usage(long *total, long *free, long *available, long *used, float *percent) {
FILE *fp = fopen("/proc/meminfo", "r");
char key[64];
long value;
char unit[16];
long mem_total = 0, mem_free = 0, mem_available = 0, buffers = 0, cached = 0;
while (fscanf(fp, "%63s %ld %15s\n", key, &value, unit) == 3) {
if (strcmp(key, "MemTotal:") == 0) mem_total = value;
else if (strcmp(key, "MemFree:") == 0) mem_free = value;
else if (strcmp(key, "MemAvailable:") == 0) mem_available = value;
else if (strcmp(key, "Buffers:") == 0) buffers = value;
else if (strcmp(key, "Cached:") == 0) cached = value;
}
fclose(fp);
*total = mem_total / 1024;
*free = mem_free / 1024;
*available = mem_available / 1024;
*used = (*total) - (*available);
*percent = (*total) ? 100.0 * (*used) / (*total) : 0.0;
}
// 获取磁盘信息
void get_disk_usage(const char *path, long *total, long *free, long *used, float *percent) {
struct statvfs stat;
if (statvfs(path, &stat) == 0) {
*total = (stat.f_blocks * stat.f_frsize) / 1024 / 1024;
*free = (stat.f_bfree * stat.f_frsize) / 1024 / 1024;
*used = *total - *free;
*percent = (*total) ? 100.0 * (*used) / (*total) : 0.0;
} else {
*total = *free = *used = 0;
*percent = 0.0;
}
}
void removeLog(){
int len=0;
char *savedtime=NULL;
char nowtime[16]={0};
long now=0;
long saved=0;
while(1){
now=getCurrentTime();
sprintf(nowtime,"%ld",now);
savedtime=file_to_buffer("logTime",&len);
if(savedtime==NULL){
buffer_to_file("logTime",nowtime,strlen(nowtime),"wb");
savedtime=file_to_buffer("logTime",&len);
}
saved=atol(savedtime);
LOG_I("now=%ld,saved=%ld,nowtime=%s,savedtime=%s\n",now,saved,nowtime,savedtime);
if(now-saved>=(60*60*24*2)){
//if(now-saved>=10){
buffer_to_file("logTime",nowtime,strlen(nowtime),"wb");
do_removelog();
}
sleep(60*60*1);
}
}
void checkOtaKey(void){
int len=0;
int keycount=0;
char *readresult=NULL;
while(1){
if(isOtaEnable){
system("echo 0 > /sys/class/gpio/gpio113/value");
sleep(1);
system("echo 1 > /sys/class/gpio/gpio113/value");
sleep(1);
}else{
readresult=file_to_buffer("/sys/class/gpio/gpio63/value",&len);
//LOG_I("resetKey:%s\n",readresult);
if(readresult!=NULL){
if(strcmp(readresult,"0\n")==0){
keycount++;
if(keycount==3){
keycount=0;
isOtaEnable=true;
isLEDOtaSuccess=false;
isAPOtaSuccess=false;
isSendComEnd=true;
LOG_I("OTA enable\n");
}
}
free(readresult);
}
usleep(100*1000);
}
}
}
void otaLeds(){
#if 0
int len=0,ver=0;
char *readresult=NULL;
char filename[128]={};
uint16_t data_crc=0;
ver=getLedOtaVersion(filename);
LOG_I("ota %s ver:%d\n",filename,ver);
readresult=file_to_buffer(filename,&len);
if(readresult!=NULL){
isSendComEnd=false;
LOG_I("data len:%d\n",len);
data_crc=CRC16_XMODEM(readresult,len);
LOG_I("crc :%04x\n",data_crc);
uart_data_send_head_ledota(&uartSend,len,data_crc,ver);//0xFF降级
usleep(72*1000);
int i=0;
for(i=0;i<len/4096;i++){
uart_data_send_ledota(&uartSend,readresult+i*4096,4096);
usleep(72*1000);
}
uart_data_send_ledota(&uartSend,readresult+i*4096,len%4096);
}
#else
int len=0,ver=0;
char *readresult=NULL;
char filename[128]={};
uint8_t senddata[4096]={};
uint16_t data_crc=0;
ver=getLedOtaVersion(filename);
LOG_I("ota %s ver:%d\n",filename,ver);
readresult=file_to_buffer(filename,&len);
if(readresult!=NULL){
isSendComEnd=false;
LOG_I("data len:%d\n",len);
data_crc=CRC16_XMODEM(readresult,len);
LOG_I("crc :%04x\n",data_crc);
uart_data_send_head_ledota(&uartSend,len,data_crc,ver);//0xFF降级
int i=0;
for(i=0;i<len/4096;i++){
memset(senddata,0,4096);
memcpy(senddata,readresult+i*4096,4096);
uart_data_send_ledota(&uartSend,senddata,4096);
}
memset(senddata,0,4096);
memcpy(senddata,readresult+i*4096,len%4096);
uart_data_send_ledota(&uartSend,senddata,len%4096);
free(readresult);
}
#endif
}
void otaAp(){
int len=0,ver=0;
char *readresult=NULL;
char filename[128]={};
char modename[32]={};
uint8_t dataori[2048]={0};
uint16_t data_crc=0;
uint16_t p_num=0;
ver=getApOtaVersion(filename,modename);
LOG_I("ota %s mode:%s ver:%d\n",filename,modename,ver);
readresult=file_to_buffer(filename,&len);
if(len%2048!=0){
p_num=len/2048 + 1;
}else{
p_num=len/2048;
}
if(readresult!=NULL){
isSendComEnd=false;
LOG_I("data len:%d\n",len);
if(strcmp(modename,"GTMODE")==0){
uart_data_send_head_apota(&uartSend,len,p_num);
usleep(60*1000);
memset(dataori,0,2048);
memcpy(dataori,readresult,2048);
data_crc=CRC16_APOTA(dataori,2048);
LOG_I("crc :%04x\n",data_crc);
uart_data_send_apota(&uartSend,dataori,len,p_num,data_crc);
while(!isAPBack){
usleep(60*1000);
}
int i=0;
for(i=1;i<len/2048;i++){
isAPBack=false;
memset(dataori,0,2048);
memcpy(dataori,readresult+i*2048,2048);
data_crc=CRC16_APOTA(dataori,2048);
LOG_I("crc :%04x\n",data_crc);
uart_data_send_apota(&uartSend,dataori,2048,i,data_crc);
while(!isAPBack){
usleep(60*1000);
}
}
if(len%2048!=0){
memset(dataori,0,2048);
memcpy(dataori,readresult+i*2048,len%2048);
data_crc=CRC16_APOTA(dataori,2048);
LOG_I("crc :%04x\n",data_crc);
uart_data_send_apota(&uartSend,dataori,2048,i,data_crc);
}
}else if(strcmp(modename,"DTMODE")==0){
}if(strcmp(modename,"HTMODE")==0){
}
free(readresult);
}
}
void enableWatchDog() {
// 使用 /dev/watchdog 设备,第一次喂狗自动开启看门狗
// 超时时间固定为5s不喂狗时默认关闭
LOG_I("watchdog will be enabled on first feed\n");
}
void feedWatchDog() {
// 使用 /dev/watchdog 设备喂狗
// 超时时间固定为5s喂狗命令: echo "" > /dev/watchdog
int fd;
int gpio_fd = open("/sys/class/gpio/gpio112/value", O_WRONLY);
int led_state = 0;
while(1) {
fd = open("/dev/watchdog", O_WRONLY);
if (fd < 0) {
LOG_I("can not open /dev/watchdog: %s\n", strerror(errno));
sleep(1);
continue;
}
write(fd, "", 1);
close(fd);
// 喂狗时翻转 gpio112 灯状态
if (gpio_fd >= 0) {
led_state = !led_state;
write(gpio_fd, led_state ? "1" : "0", 1);
}
sleep(1); // 每2秒喂一次狗超时时间为5s
}
if (gpio_fd >= 0) {
close(gpio_fd);
}
}
// GPIO118控制函数
void setGpio118Low() {
int fd = open("/sys/class/gpio/gpio118/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio118 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "0", 1);
close(fd);
LOG_I("GPIO118 set to LOW\n");
}
void setGpio118High() {
int fd = open("/sys/class/gpio/gpio118/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio118 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "1", 1);
close(fd);
LOG_I("GPIO118 set to HIGH\n");
}
// GPIO113控制函数
void setGpio113High() {
int fd = open("/sys/class/gpio/gpio113/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio113 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "1", 1);
close(fd);
LOG_I("GPIO113 set to HIGH\n");
}
// GPIO114控制函数
void setGpio114High() {
int fd = open("/sys/class/gpio/gpio114/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio114 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "1", 1);
close(fd);
LOG_I("GPIO114 set to HIGH\n");
}
void setGpio113Low() {
int fd = open("/sys/class/gpio/gpio113/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio113 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
close(fd);
LOG_I("GPIO113 set to LOW\n");
}
// GPIO115控制函数
void setGpio115High() {
int fd = open("/sys/class/gpio/gpio115/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio115 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "1", 1);
close(fd);
LOG_I("GPIO115 set to HIGH\n");
}
void setGpio115Low() {
int fd = open("/sys/class/gpio/gpio115/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio115 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
close(fd);
LOG_I("GPIO115 set to LOW\n");
}
// GPIO117控制函数
void setGpio117High() {
int fd = open("/sys/class/gpio/gpio117/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio117 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
usleep(100*1000);
write(fd, "1", 1);
close(fd);
LOG_I("GPIO117 set to HIGH\n");
}
void setGpio117Low() {
int fd = open("/sys/class/gpio/gpio117/value", O_WRONLY);
if (fd < 0) {
LOG_I("Failed to open gpio117 value: %s\n", strerror(errno));
return;
}
write(fd, "0", 1);
close(fd);
LOG_I("GPIO117 set to LOW\n");
}
void rebootSystem(void){
while(!isTimeToReboot){
if(!isTimeToReboot){
struct tm *result;
time_t timep;
time (&timep);
result = localtime(&timep);
if(result->tm_hour==0 && result->tm_min==0 && result->tm_sec==10){
isTimeToReboot=true;
LOG_I("prepare to reboot\n");
}
}
sleep(1);
}
system("sync");
sleep(10);
system("sync");
system("reboot");
}
int readQrcode()
{
fd = open("/dev/input/event2", O_RDONLY);
if (fd < 0)
{
LOG_I("can not open scanner input event2!\n");
goto error;
}
while (1)
{
while (read(fd, &buff, sizeof(struct input_event)) == 0)
{
;
}
if (buff.type == EV_KEY){
if(buff.value==0){
#if 0
LOG_I("type:%d code:%d value:%d\n", buff.type, buff.code, buff.value);
#else
switch(buff.code){
case 2:
if(UPCASE==1){
input_value[count_value]='!';
}else{
input_value[count_value]='1';
}
UPCASE=0;
count_value++;
break;
case 3:
if(UPCASE==1){
input_value[count_value]='@';
}else{
input_value[count_value]='2';
}
UPCASE=0;
count_value++;
break;
case 4:
if(UPCASE==1){
input_value[count_value]='#';
}else{
input_value[count_value]='3';
}
UPCASE=0;
count_value++;
break;
case 5:
if(UPCASE==1){
input_value[count_value]='$';
}else{
input_value[count_value]='4';
}
UPCASE=0;
count_value++;
break;
case 6:
if(UPCASE==1){
input_value[count_value]='%';
}else{
input_value[count_value]='5';
}
UPCASE=0;
count_value++;
break;
case 7:
if(UPCASE==1){
input_value[count_value]='^';
}else{
input_value[count_value]='6';
}
UPCASE=0;
count_value++;
break;
case 8:
if(UPCASE==1){
input_value[count_value]='&';
}else{
input_value[count_value]='7';
}
UPCASE=0;
count_value++;
break;
case 9:
if(UPCASE==1){
input_value[count_value]='*';
}else{
input_value[count_value]='8';
}
UPCASE=0;
count_value++;
break;
case 10:
if(UPCASE==1){
input_value[count_value]='(';
}else{
input_value[count_value]='9';
}
UPCASE=0;
count_value++;
break;
case 11:
if(UPCASE==1){
input_value[count_value]=')';
}else{
input_value[count_value]='0';
}
UPCASE=0;
count_value++;
break;
case 12:
if(UPCASE==1){
input_value[count_value]='_';
}else{
input_value[count_value]='-';
}
UPCASE=0;
count_value++;
break;
case 13:
if(UPCASE==1){
input_value[count_value]='+';
}else{
input_value[count_value]='=';
}
UPCASE=0;
count_value++;
break;
case 16:
if(UPCASE==1){
input_value[count_value]='Q';
}else{
input_value[count_value]='q';
}
UPCASE=0;
count_value++;
break;
case 17:
if(UPCASE==1){
input_value[count_value]='W';
}else{
input_value[count_value]='w';
}
UPCASE=0;
count_value++;
break;
case 18:
if(UPCASE==1){
input_value[count_value]='E';
}else{
input_value[count_value]='e';
}
UPCASE=0;
count_value++;
break;
case 19:
if(UPCASE==1){
input_value[count_value]='R';
}else{
input_value[count_value]='r';
}
UPCASE=0;
count_value++;
break;
case 20:
if(UPCASE==1){
input_value[count_value]='T';
}else{
input_value[count_value]='T';
}
UPCASE=0;
count_value++;
break;
case 21:
if(UPCASE==1){
input_value[count_value]='Y';
}else{
input_value[count_value]='y';
}
UPCASE=0;
count_value++;
break;
case 22:
if(UPCASE==1){
input_value[count_value]='U';
}else{
input_value[count_value]='u';
}
UPCASE=0;
count_value++;
break;
case 23:
if(UPCASE==1){
input_value[count_value]='I';
}else{
input_value[count_value]='i';
}
UPCASE=0;
count_value++;
break;
case 24:
if(UPCASE==1){
input_value[count_value]='O';
}else{
input_value[count_value]='o';
}
UPCASE=0;
count_value++;
break;
case 25:
if(UPCASE==1){
input_value[count_value]='P';
}else{
input_value[count_value]='p';
}
UPCASE=0;
count_value++;
break;
case 26:
if(UPCASE==1){
input_value[count_value]='{';
}else{
input_value[count_value]='[';
}
UPCASE=0;
count_value++;
break;
case 27:
if(UPCASE==1){
input_value[count_value]='}';
}else{
input_value[count_value]=']';
}
UPCASE=0;
count_value++;
break;
case 28:
input_value[count_value]='\0';
//LOG_I("%s\n",input_value);
memset(input_value_copy,0,1024);
memcpy(input_value_copy,input_value,1024);
memset(input_value,0,1024);
count_value=0;
int ret=-1;
pthread_t pt_handleqrcode;
ret = pthread_create(&pt_handleqrcode,NULL,actHandleQrcode,input_value_copy);
if(ret!=0){
LOG_I("pthread_create handleqrcode fail\n");
}else{
pthread_detach(pt_handleqrcode);
}
break;
case 30:
if(UPCASE==1){
input_value[count_value]='A';
}else{
input_value[count_value]='a';
}
UPCASE=0;
count_value++;
break;
case 31:
if(UPCASE==1){
input_value[count_value]='S';
}else{
input_value[count_value]='s';
}
UPCASE=0;
count_value++;
break;
case 32:
if(UPCASE==1){
input_value[count_value]='D';
}else{
input_value[count_value]='d';
}
UPCASE=0;
count_value++;
break;
case 33:
if(UPCASE==1){
input_value[count_value]='F';
}else{
input_value[count_value]='f';
}
UPCASE=0;
count_value++;
break;
case 34:
if(UPCASE==1){
input_value[count_value]='G';
}else{
input_value[count_value]='g';
}
UPCASE=0;
count_value++;
break;
case 35:
if(UPCASE==1){
input_value[count_value]='H';
}else{
input_value[count_value]='h';
}
UPCASE=0;
count_value++;
break;
case 36:
if(UPCASE==1){
input_value[count_value]='J';
}else{
input_value[count_value]='j';
}
UPCASE=0;
count_value++;
break;
case 37:
if(UPCASE==1){
input_value[count_value]='K';
}else{
input_value[count_value]='k';
}
UPCASE=0;
count_value++;
break;
case 38:
if(UPCASE==1){
input_value[count_value]='L';
}else{
input_value[count_value]='l';
}
UPCASE=0;
count_value++;
break;
case 39:
if(UPCASE==1){
input_value[count_value]=':';
}else{
input_value[count_value]=';';
}
UPCASE=0;
count_value++;
break;
case 40:
if(UPCASE==1){
input_value[count_value]='"';
}else{
input_value[count_value]='\'';
}
UPCASE=0;
count_value++;
break;
case 42:
UPCASE=1;
break;
case 43:
if(UPCASE==1){
input_value[count_value]='|';
}else{
input_value[count_value]='\\';
}
UPCASE=0;
count_value++;
break;
case 44:
if(UPCASE==1){
input_value[count_value]='Z';
}else{
input_value[count_value]='z';
}
UPCASE=0;
count_value++;
break;
case 45:
if(UPCASE==1){
input_value[count_value]='X';
}else{
input_value[count_value]='x';
}
UPCASE=0;
count_value++;
break;
case 46:
if(UPCASE==1){
input_value[count_value]='C';
}else{
input_value[count_value]='c';
}
UPCASE=0;
count_value++;
break;
case 47:
if(UPCASE==1){
input_value[count_value]='V';
}else{
input_value[count_value]='v';
}
UPCASE=0;
count_value++;
break;
case 48:
if(UPCASE==1){
input_value[count_value]='B';
}else{
input_value[count_value]='b';
}
UPCASE=0;
count_value++;
break;
case 49:
if(UPCASE==1){
input_value[count_value]='N';
}else{
input_value[count_value]='n';
}
UPCASE=0;
count_value++;
break;
case 50:
if(UPCASE==1){
input_value[count_value]='M';
}else{
input_value[count_value]='m';
}
UPCASE=0;
count_value++;
break;
case 51:
if(UPCASE==1){
input_value[count_value]='<';
}else{
input_value[count_value]=',';
}
UPCASE=0;
count_value++;
break;
case 52:
if(UPCASE==1){
input_value[count_value]='>';
}else{
input_value[count_value]='.';
}
UPCASE=0;
count_value++;
break;
case 53:
if(UPCASE==1){
input_value[count_value]='?';
}else{
input_value[count_value]='/';
}
UPCASE=0;
count_value++;
break;
}
#endif
}
}
}
close(fd);
return 0;
error:
return 1;
}
#if 0
void writeWpa(char *filename,char *ssid,char *psw){
LOG_I("%s\n",__func__);
buffer_to_file(filename,"# WPA-PSK/TKIP\n",strlen("# WPA-PSK/TKIP\n"),"wb");
buffer_to_file(filename,"ap_scan=1\n",strlen("ap_scan=1\n"),"a");
buffer_to_file(filename,"ctrl_interface=/var/run/wpa_supplicant\n",strlen("ctrl_interface=/var/run/wpa_supplicant\n"),"a");
buffer_to_file(filename,"network={\n",strlen("network={\n"),"a");
buffer_to_file(filename,"ssid=\"",strlen("ssid=\""),"a");
buffer_to_file(filename,ssid,strlen(ssid),"a");
buffer_to_file(filename,"\"",strlen("\""),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"key_mgmt=WPA-PSK\n",strlen("key_mgmt=WPA-PSK\n"),"a");
buffer_to_file(filename,"proto=WPA RSN\n",strlen("proto=WPA RSN\n"),"a");
buffer_to_file(filename,"pairwise=CCMP TKIP\n",strlen("pairwise=CCMP TKIP\n"),"a");
buffer_to_file(filename,"group=CCMP TKIP\n",strlen("group=CCMP TKIP\n"),"a");
buffer_to_file(filename,"psk=\"",strlen("psk=\""),"a");
buffer_to_file(filename,psw,strlen(psw),"a");
buffer_to_file(filename,"\"",strlen("\""),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"}\n",strlen("}\n"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
}
void writeWlan(char *filename,char *netway,char *gate,char *ip){
LOG_I("%s\n",__func__);
buffer_to_file(filename,"METHOD=",strlen("METHOD="),"wb");
buffer_to_file(filename,netway,strlen(netway),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
if(strcmp(netway,"STATIC")==0){
buffer_to_file(filename,"IPADDR=",strlen("IPADDR="),"a");
buffer_to_file(filename,ip,strlen(ip),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"NETMASK=255.255.255.0\n",strlen("NETMASK=255.255.255.0\n"),"a");
buffer_to_file(filename,"GATEWAY=",strlen("GATEWAY="),"a");
buffer_to_file(filename,gate,strlen(gate),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
}
}
#endif
void writeNetworkInterface(char *filename,char *dest){
buffer_to_file(filename,"# interfaces(5) file used by ifup(8) and ifdown(8)",
strlen("# interfaces(5) file used by ifup(8) and ifdown(8)"),"wb");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"# Include files from /etc/network/interfaces.d:",strlen("# Include files from /etc/network/interfaces.d:"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"source-directory /etc/network/interfaces.d",strlen("source-directory /etc/network/interfaces.d"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"auto lo",strlen("auto lo"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"iface lo inet loopback",strlen("iface lo inet loopback"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"auto eth0",strlen("auto eth0"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"iface eth0 inet dhcp",strlen("iface eth0 inet dhcp"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"# address 192.168.1.100",strlen("# address 192.168.1.100"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"# netmask 255.255.255.0",strlen("# netmask 255.255.255.0"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"# gateway 192.168.1.1",strlen("# gateway 192.168.1.1"),"a");
buffer_to_file(filename,"\n",strlen("\n"),"a");
buffer_to_file(filename,"hwaddress ether ",strlen("hwaddress ether "),"a");
buffer_to_file(filename,dest,strlen(dest),"a");
system("sync");
}
char* insert_colon(const char* src, int interval) {
if (!src || interval <= 0) return NULL;
size_t len = strlen(src);
if (len == 0) { // 空字符串返回空
char* res = malloc(1);
if (res) res[0] = '\0';
return res;
}
// 计算新字符串长度
size_t sections = (len + interval - 1) / interval; // 总段数
size_t new_len = len + (sections - 1); // 新长度 = 原长 + 冒号数
char* new_str = malloc(new_len + 1); // 分配内存:ml-citation{ref="2" data="citationList"}
if (!new_str) return NULL;
size_t src_idx = 0, dst_idx = 0;
while (src_idx < len) {
// 计算本次复制的字符数
size_t copy_size = (len - src_idx < (size_t)interval) ? (len - src_idx) : (size_t)interval;
memcpy(new_str + dst_idx, src + src_idx, copy_size); // 块复制:ml-citation{ref="3" data="citationList"}
src_idx += copy_size;
dst_idx += copy_size;
// 非末尾段时插入冒号
if (src_idx < len) new_str[dst_idx++] = ':';
}
new_str[dst_idx] = '\0'; // 终止符:ml-citation{ref="7" data="citationList"}
return new_str;
}
void *actHandleQrcode(void *parm){
char *str=(char *)parm;
LOG_I("scan:%s\n",str);
// 检查是否为T或D开头的生产批次号码
if((str[0] == 'T' || str[0] == 'D') && strlen(str) > 1) {
LOG_I("检测到生产批次号码: %s\n", str);
char sn_buffer[64] = {0};
char mac_buffer[32] = {0};
// 从Redis中根据批次号码查找对应的SN和MAC
int result = get_sn_mac_by_batch_number(str, sn_buffer, sizeof(sn_buffer), mac_buffer, sizeof(mac_buffer));
if(result == 0) {
// 成功获取到SN和MAC保存到文件
LOG_I("根据批次号码获取到SN: %s, MAC: %s\n", sn_buffer, mac_buffer);
// 保存SN到文件
buffer_to_file("savedDevSn", sn_buffer, strlen(sn_buffer), "wb");
LOG_I("已保存SN到文件: %s\n", sn_buffer);
// 保存原始MAC到文件
buffer_to_file("savedDevMac", mac_buffer, strlen(mac_buffer), "wb");
LOG_I("已保存MAC到文件: %s\n", mac_buffer);
// 格式化MAC地址并更新网络接口配置
char* formatted_mac = insert_colon(mac_buffer, 2);
if(formatted_mac != NULL) {
LOG_I("格式化后的MAC: %s\n", formatted_mac);
writeNetworkInterface("/etc/network/interfaces", formatted_mac);
writeNetworkInterface("/etc/network/interfaces.default", formatted_mac);
free(formatted_mac);
}
// 更新全局变量stationsn
if(strlen(sn_buffer) < sizeof(stationsn)) {
strcpy(stationsn, sn_buffer);
LOG_I("已更新全局stationsn: %s\n", stationsn);
}
// 发送审计记录到Redis
if(send_audit_to_redis(str, mac_buffer, sn_buffer) == 0) {
LOG_I("审计记录已发送到Redis: batch=%s, mac=%s, sn=%s\n", str, mac_buffer, sn_buffer);
} else {
LOG_I("发送审计记录到Redis失败\n");
}
} else {
LOG_I("根据批次号码 %s 未找到对应的SN和MAC\n", str);
}
pthread_exit(NULL);
return NULL;
}
if(strstr(str,"{")!=NULL){
#if 0
char deviceSecret[64]={0};
char deviceCode[64]={0};
char netWorkType[64]={0};
char netWorkSsid[64]={0};
char netWorkPassword[64]={0};
get_string_from_json_string_by_key_unescape(str, "deviceSecret",deviceSecret,64);
LOG_I("deviceSecret:%s\n",deviceSecret);
get_string_from_json_string_by_key_unescape(str, "deviceCode",deviceCode,64);
LOG_I("deviceCode:%s\n",deviceCode);
if(strcmp(deviceSecret,"")!=0 && strcmp(deviceCode,"")!=0){
buffer_to_file("deviceSecret",deviceSecret,strlen(deviceSecret),"wb");
buffer_to_file("savedDevSn",deviceCode,strlen(deviceCode),"wb");
}
get_string_from_json_string_by_key_unescape(str, "netWorkType",netWorkType,64);
LOG_I("netWorkType:%s\n",netWorkType);
if(strcmp(netWorkType,"net_wifi")==0){
buffer_to_file("nettype","net_wifi",strlen("net_wifi"),"wb");
get_string_from_json_string_by_key_unescape(str, "netWorkSsid",netWorkSsid,64);
LOG_I("netWorkSsid:%s\n",netWorkSsid);
get_string_from_json_string_by_key_unescape(str, "netWorkPassword",netWorkPassword,64);
LOG_I("netWorkPassword:%s\n",netWorkPassword);
if(strcmp(netWorkSsid,"")!=0 && strcmp(netWorkPassword,"")!=0){
writeWpa("/etc/wpa_supplicant.conf",netWorkSsid,netWorkPassword);
sleep(1);
system("reboot");
}else{
}
}else if(strcmp(netWorkType,"net_wired")==0){
buffer_to_file("nettype","net_wired",strlen("net_wired"),"wb");
LOG_I("use wired\n");
sleep(1);
system("reboot");
}else if(strcmp(netWorkType,"net_mobile")==0){
buffer_to_file("nettype","net_mobile",strlen("net_mobile"),"wb");
LOG_I("use mobile\n");
sleep(1);
system("reboot");
}
#endif
}else{
if(strstr(str,"TJ")!=NULL && strlen(str)==27){
LOG_I("ok\n");
char *result=NULL;
char *p;
result=strtok_r(str,":",&p);
while(result!=NULL){
if(strstr(result,"TJ")!=NULL){
LOG_I("save sn:%s\n",result);
buffer_to_file("savedDevSn",result,strlen(result),"wb");
}else{
LOG_I("save mac:%s\n",result);
buffer_to_file("savedDevMac",result,strlen(result),"wb");
char* destmac = insert_colon(result, 2);
LOG_I("formatted mac:%s\n",destmac);
writeNetworkInterface("/etc/network/interfaces",destmac);
writeNetworkInterface("/etc/network/interfaces.default",destmac);
}
result=strtok_r(NULL,",",&p);
}
}
}
pthread_exit(NULL);
}
char *file_to_buffer(const char *pathname, unsigned int *size){
FILE *fp = NULL;
char *temp = NULL;
fp = fopen(pathname, "rb");
if(fp==NULL){
//LOG_I("open %s error\n", pathname);
}else{
fseek(fp,0,2);
*size = ftell(fp);
rewind(fp);
temp = (char *)malloc(*size);
fread(temp, 1, *size, fp);
fclose(fp);
}
return temp;
}
/*================================================================================*/
void showShellInfo(char *command){
FILE *fp;
char buffer[512]={0};
fp=popen(command, "r");
if (fp) {
fread(buffer,1,sizeof(buffer),fp);
pclose(fp);
LOG_I("\n%s",buffer);
}
}
void getTimeStr(char *buffer,int len){
time_t timep;
struct tm *p;
time (&timep);
p=localtime(&timep);
strftime (buffer,len,"%Y-%m-%d %H:%M:%S",p);
}
long getCurrentTime(){
struct timeval begin;
gettimeofday(&begin,NULL);
long long beginTime = (long long)begin.tv_sec * 1000 + (long long)begin.tv_usec / 1000;
long last=beginTime/1000;
return last;
}
void myrand(char *randnum,int len){
int i;
srand((unsigned)time(0));
for(i=0;i<=len-1;i++)
randnum[i]=rand()%10 +'0';
randnum[len]='\0';
}
void removeSpaces(char *str) {
int i = 0, j = 0;
while (str[i] != '\0') {
if (str[i] != ' ') {
str[j++] = str[i];
}
i++;
}
str[j] = '\0';
}
void test_lighton_search(void){
LOG_I("%s\n",__func__);
isSendComEnd=false;
isLightOn=true;
isLightOnByRule=false;
isLabelUp=false;
isSearchLabel=false;
if(tagCount<=5){
lightsnNum=tagCount;
}else{
lightsnNum=5;
}
LOG_I("tagCount:%d\n",tagCount);
LOG_I("lightsnNum:%d\n",lightsnNum);
for(int i=0;i<lightsnNum;i++){
LOG_I("onlyTags:%08X,%04x\n",onlyTags[i].name,onlyTags[i].battery);
if(i==0){
Tag1=onlyTags[i].name;
}
if(i==1){
Tag2=onlyTags[i].name;
}
if(i==2){
Tag3=onlyTags[i].name;
}
if(i==3){
Tag4=onlyTags[i].name;
}
if(i==4){
Tag5=onlyTags[i].name;
}
}
tagCount=0;
memset(onlyTags,0,sizeof(onlyTags));
uart_data_send_head_lighton(&uartSend,5,lightsnNum);
char *flash="1";
char *light="10";
jt_ledctrl_package_t led_ctrl={
.s.color=4,
.s.sound=1,
.s.flash=1,
};
uart_data_send_lighton_test(&uartSend,led_ctrl.ch,atoi(flash),atoi(light),Tag1,Tag2,Tag3,Tag4,Tag5,lightsnNum);
}
void getDevRawPassword(char *devsn){
LOG_I("devsn:%s\n",devsn);
json_object *root = NULL;
const char *payload = NULL;
char payload_copy[256]={0};
char send_request[256]={0};
char signbase64[256]={0};
char signtmp[256]={0};
char jsondata[256] = {0};
char tmpdata[256] = {0};
//char tmpdata1[64] = {0};
char buffer[512];
FILE *fp;
root = json_object_new_object();
if(root == NULL){
LOG_I("json_object_new_object error\n");
}else{
json_object_object_add(root, "deviceId",json_object_new_string(devsn));
json_object_object_add(root, "oldPassword",json_object_new_string("12345"));
payload = json_object_to_json_string(root);
removeSpaces(payload);
strcpy(signtmp,payload);
strcat(signtmp,appSecret);
//LOG_I("signtmp:%s\n",signtmp);
get_base64_md5_from_string(signbase64, sizeof(signbase64), signtmp, strlen(signtmp));
//LOG_I("signbase64:%s\n",signbase64);
sprintf(send_request,"curl -X POST -H 'x-appKey:%s' -H 'x-datadigest:%s' -H 'Content-Type: application/json' -d '%s' %s",
appKey,signbase64,payload,getDevRawPasswordUrl);
LOG_I("send_request:%s\n",send_request);
fp=popen(send_request,"r");
fgets(buffer,sizeof(buffer),fp);
//get_string_from_json_string_by_key_unescape(buffer, "message", tmpdata1, sizeof(tmpdata1));
//LOG_I("message: %s\n",tmpdata1);
get_string_from_json_string_by_key_unescape(buffer, "result", tmpdata, sizeof(tmpdata));
LOG_I("result: %s\n",tmpdata);
snprintf(jsondata, sizeof(jsondata), "{%s}", tmpdata);
//LOG_I("jsondata:%s\n",jsondata);
get_string_from_json_string_by_key_unescape(jsondata, "password", mqttRawPassword, sizeof(mqttRawPassword));
LOG_I("save mqttRawPassword:%s\n",mqttRawPassword);
if(strcmp(mqttRawPassword,"")!=0){
int result = buffer_to_file("mqttRawPassword",mqttRawPassword,strlen(mqttRawPassword),"wb");
if(result == 0) {
LOG_I("mqttRawPassword saved successfully\n");
sync();
// 首次获取密码成功后启动搜索标签功能(只运行一次)
LOG_I("Starting tag search after first registration...\n");
isSearchLabelOntest = true;
searchTimeOut=5;
searchTimeOld=getCurrentTime();
while(isSearchLabelOntest) {
isSearchLabel=true;
uart_data_send_head_search(&uartSend,5);
sleep(10);
searchTimeNew=getCurrentTime();
LOG_I("searchTimeNew:%d\n",searchTimeNew);
if((searchTimeNew-searchTimeOld)>=searchTimeOut){
isSearchLabelOntest=false;
//search_tag_report();
test_lighton_search();
}
}
// 从savedDevMac文件读取MAC地址
unsigned int mac_file_size = 0;
char *saved_mac = file_to_buffer("savedDevMac", &mac_file_size);
char redis_mac[32] = {0};
char formatted_mac[32] = {0};
if (saved_mac != NULL && mac_file_size > 0) {
strncpy(redis_mac, saved_mac, sizeof(redis_mac) - 1);
redis_mac[sizeof(redis_mac) - 1] = '\0';
free(saved_mac);
LOG_I("Got MAC from saved file: %s\n", redis_mac);
// 格式化MAC地址
if(format_mac_address(redis_mac, formatted_mac, sizeof(formatted_mac)) == 0) {
LOG_I("Formatted MAC: %s\n", formatted_mac);
// 更新/etc/network/interfaces文件中的MAC地址
LOG_I("Updating MAC address in /etc/network/interfaces\n");
// 读取当前的interfaces文件内容
unsigned int file_size = 0;
char *interfaces_content = file_to_buffer("/etc/network/interfaces", &file_size);
if(interfaces_content != NULL) {
// 查找并替换hwaddress ether行
char *hwaddress_line = strstr(interfaces_content, "hwaddress ether");
if(hwaddress_line != NULL) {
// 找到行的结束位置
char *line_end = strchr(hwaddress_line, '\n');
if(line_end != NULL) {
// 构建新的interfaces文件内容
size_t before_len = hwaddress_line - interfaces_content;
size_t after_len = strlen(line_end);
char new_interfaces[4096] = {0};
strncpy(new_interfaces, interfaces_content, before_len);
snprintf(new_interfaces + before_len, sizeof(new_interfaces) - before_len, "hwaddress ether %s%s", formatted_mac, line_end);
// 写入更新后的内容
int write_result = buffer_to_file("/etc/network/interfaces", new_interfaces, strlen(new_interfaces), "wb");
if(write_result == 0) {
LOG_I("MAC address updated in /etc/network/interfaces successfully\n");
sync();
} else {
LOG_I("Failed to update MAC address in /etc/network/interfaces\n");
}
} else {
LOG_I("Could not find end of hwaddress line\n");
}
} else {
LOG_I("hwaddress ether line not found in interfaces file\n");
}
free(interfaces_content);
} else {
LOG_I("Failed to read /etc/network/interfaces file\n");
}
} else {
LOG_I("Failed to format MAC address\n");
}
} else {
LOG_I("Failed to read MAC from saved file\n");
}
} else {
LOG_I("Failed to save mqttRawPassword\n");
}
}
}
}
/*================================================================================*/
void mqtt_init(){
int ret=0;
char username[32] = {0};
char password[32] = {0};
char clientid[256] = {0};
//char clientid[256] = "TJ250995217957|signmethod=hmacsha1|timestamp=1741416329331";
char hostip[16]={0};
//char protocol[64]="mqtt";
//char RawPassword[64]="94b4e39caf1d45ee9a071d701cc037b4";
struct timeval tv;
//MQTTASYNC_TRACE_MAXIMUM
//MQTTASYNC_TRACE_MEDIUM
//MQTTASYNC_TRACE_MINIMUM
//MQTTASYNC_TRACE_PROTOCOL
//MQTTASYNC_TRACE_ERROR
//MQTTASYNC_TRACE_SEVERE
//MQTTASYNC_TRACE_FATAL
//mqtt_config.tracelevel=get_trace_level_by_name("MQTTASYNC_TRACE_PROTOCOL");
gettimeofday(&tv, NULL);
snprintf(clientid,sizeof(clientid),"%s|signmethod=hmacsha1|timestamp=%ld",stationsn,tv.tv_sec*1000+tv.tv_usec);
LOG_I("clientid:%s,mqttRawPassword:%s\n",clientid,mqttRawPassword);
hmacsha1(mqttRawPassword,clientid,password,sizeof(password));
mqtt_config.tracelevel=MQTTASYNC_TRACE_PROTOCOL;
mqtt_config.retain=0;
mqtt_config.port=mqtt_port;
mqtt_config.keepalive=30;
//memset(mqtt_config.protocol,0,sizeof(mqtt_config.protocol));
//memcpy(mqtt_config.protocol,protocol,sizeof(protocol));
memset(mqtt_config.clientid,0,sizeof(mqtt_config.clientid));
memcpy(mqtt_config.clientid,clientid,sizeof(clientid));
snprintf(username, sizeof(username), "%s", stationsn);
LOG_I("username:%s,password:%s\n",username,password);
memset(mqtt_config.productcode, 0, sizeof(mqtt_config.productcode));
memcpy(mqtt_config.productcode, productid, strlen(productid));
memset(mqtt_config.username, 0, sizeof(mqtt_config.username));
memcpy(mqtt_config.username, username, strlen(username));
memset(mqtt_config.password, 0, sizeof(mqtt_config.password));
memcpy(mqtt_config.password, password, strlen(password));
get_ip_by_domain(hostDomain,hostip,16);
memset(mqtt_config.host, 0, sizeof(mqtt_config.host));
memcpy(mqtt_config.host, hostip, strlen(hostip));
mqtt_config.MQTTVersion = 4;
/* will options */
mqtt_config.will_topic = NULL;
mqtt_config.will_payload = NULL;
mqtt_config.will_qos = 2;
mqtt_config.will_retain = 0;
/* TLS options */
mqtt_config.insecure = 0;
mqtt_config.capath = NULL;
mqtt_config.cert = NULL;
mqtt_config.cafile = NULL;
mqtt_config.key = NULL;
mqtt_config.keypass = NULL;
mqtt_config.ciphers = NULL;
ret = sem_init(&mqtt_config.sem_connect, 0, 0);
if (ret != 0)
{
LOG_I("sem_connect init error\n");
goto error;
}
ret = mqtt_utils_init(&mqtt_config);
if (ret < 0)
{
LOG_I("mqtt_utils_init error\n");
ret = -1;
goto error;
}
sem_wait(&mqtt_config.sem_connect);
ret = 0;
error:
return;
}
/*================================================================================*/
void *thread_ota(void *arg){
prctl(PR_SET_NAME, "ota");
//checkOtaKey();
}
void *thread_mqtt(void *arg){
prctl(PR_SET_NAME, "mqtt");
mqtt_init();
}
void *thread_removelog(void *arg){
prctl(PR_SET_NAME, "removelog");
removeLog();
}
void *thread_reboot(void *arg){
prctl(PR_SET_NAME, "reboot");
rebootSystem();
}
void *thread_feed_watchdog(void *arg){
prctl(PR_SET_NAME, "watchdog");
feedWatchDog();
return NULL;
}
#if 1
void *thread_readqr(void *arg){
prctl(PR_SET_NAME, "readqr");
readQrcode();
}
#endif
void *thread_vm_heartbeat(void *arg) {
char *client_id = (char *)arg;
const char *url = "http://180.163.74.83:8428/api/v1/import/prometheus";
char post_data[256];
CURL *curl = curl_easy_init();
if (!curl) {
DEBUG_TX("curl init failed\n");
pthread_exit(NULL);
}
system("ntpdate -u cn.pool.ntp.org");
while (1) {
time_t now = time(NULL);
// Prometheus exposition format
snprintf(post_data, sizeof(post_data),
"client_online{client_id=\"%s\"} %ld\n", client_id, now);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
DEBUG_TX("send to VictoriaMetrics failed: %s\n", curl_easy_strerror(res));
} else {
DEBUG_TX("heartbeat sent: %s", post_data);
}
sleep(3); // 3秒心跳
}
curl_easy_cleanup(curl);
pthread_exit(NULL);
}
void *thread_tag_search_send(void *arg){
prctl(PR_SET_NAME, "tag_search");
while(1){
if(isSearchLabelOn){
sleep(10);
searchTimeNew=getCurrentTime();
if((searchTimeNew-searchTimeOld)>=(searchTimeOut)){
isSearchReport=true;
search_tag_report();
isSearchReport=false;
isSearchLabelOn=false;
}
} else {
usleep(100000); // 休眠100ms
}
}
}
void *thread_do_ota(void *arg){
prctl(PR_SET_NAME, "do_ota");
while(1){
if(isOtaEnable && isSendComEnd && !isLEDOtaSuccess){
sleep(1);
otaLeds();
} else {
usleep(100000); // 休眠100ms
}
}
}
//char *tag_1="00A04CCE";
//char *tag_2="00A04C0E";
//char *tag_3="00A04C0F";
//char *tag_4="00A04C11";
//char *tag_5="00A04CD0";
void *thread_uart_recv_ack(void *arg){
prctl(PR_SET_NAME, "uart_ack");
uint16_t parm_ack;
int ret=0;
while(1){
// 仅在成功收到ACK时打印日志并处理减少超时噪声
ret=uart_data_receive_ack(&uartSend,&parm_ack);
if(ret == sizeof(jt_receive_package_t)){
LOG_I("ack:%x\n",parm_ack);
if(parm_ack==0x2323){
// 记录收到0x2323的时间并设置等待0x4646标志
time(&last_2323_time);
waiting_for_4646 = true;
#if 0
if(isLightOn){
uint32_t tags[30] = {0};
uint8_t tag_leds[30] = {0};
int valid_count = 0;
for (int i = 0; i < lightsn_buffer_count; ++i) {
// 1. SN转MACHEX字符串转uint32_t
if (strlen(lightsn_buffer[i]) == 8) {
tags[valid_count] = (uint32_t)strtoul(lightsn_buffer[i], NULL, 16);
} else {
LOG_I("[WARN] tag[%d] sn格式非法: %s, 跳过", i, lightsn_buffer[i]);
continue;
}
// 2. 颜色+闪光+声音合成LED控制字节协议格式
int flash = (strlen(flash_buffer[i]) > 0) ? atoi(flash_buffer[i]) : atoi(mqtt_parm.msg_flash); // "1"=闪光, "0"=常亮
int sound = (strlen(sound_buffer[i]) > 0) ? atoi(sound_buffer[i]) : atoi(mqtt_parm.msg_sound); // "1"=有声, "0"=无声
int changecolor = 0;
if(strcmp(color_buffer[i],"1")==0){
changecolor=4;
}else if(strcmp(color_buffer[i],"2")==0){
changecolor=6;
}else if(strcmp(color_buffer[i],"3")==0){
changecolor=1;
}else if(strcmp(color_buffer[i],"4")==0){
changecolor=2;
}else if(strcmp(color_buffer[i],"5")==0){
changecolor=3;
}else if(strcmp(color_buffer[i],"6")==0){
changecolor=7;
}else if(strcmp(color_buffer[i],"7")==0){
changecolor=5;
}else if(strcmp(color_buffer[i],"8")==0){
changecolor=0;
}
uint8_t led_val = 0;
if (flash) led_val |= 0x40; // Bit6
if (sound) led_val |= 0x10; // Bit4
led_val |= (changecolor & 0x0F); // 低4位为颜色
tag_leds[valid_count] = led_val;
LOG_I("tag[%d]: sn=%s, color=%s, led=0x%02X ",
valid_count, lightsn_buffer[i], color_buffer[i], tag_leds[valid_count]);
valid_count++;
}
if (valid_count > 0) {
uint8_t changecolor=0;
if(strcmp(mqtt_parm.msg_color,"1")==0){
changecolor=4;
}else if(strcmp(mqtt_parm.msg_color,"2")==0){
changecolor=6;
}else if(strcmp(mqtt_parm.msg_color,"3")==0){
changecolor=1;
}else if(strcmp(mqtt_parm.msg_color,"4")==0){
changecolor=2;
}else if(strcmp(mqtt_parm.msg_color,"5")==0){
changecolor=3;
}else if(strcmp(mqtt_parm.msg_color,"6")==0){
changecolor=7;
}else if(strcmp(mqtt_parm.msg_color,"7")==0){
changecolor=5;
}else if(strcmp(mqtt_parm.msg_color,"8")==0){
changecolor=0;
}
jt_ledctrl_package_t led_ctrl={
.s.color=changecolor,
.s.sound=atoi(mqtt_parm.msg_sound),
.s.flash=atoi(mqtt_parm.msg_flash),
};
uart_data_send_lightband(&uartSend, led_ctrl.ch, atoi(mqtt_parm.msg_flash), atoi(mqtt_parm.msg_lightDuration), tags, tag_leds, valid_count);
}
isLightOn=false;
// 处理完成后清空buffer
pthread_mutex_lock(&lightsn_buffer_mutex);
lightsn_buffer_count = 0;
memset(lightsn_buffer, 0, sizeof(lightsn_buffer));
memset(color_buffer, 0, sizeof(color_buffer));
memset(sound_buffer, 0, sizeof(sound_buffer));
memset(flash_buffer, 0, sizeof(flash_buffer));
pthread_mutex_unlock(&lightsn_buffer_mutex);
}
#endif
#if 1
if(isSearchLabelOn || isSearchLabelOntest){
//LOG_I("isSearchLabel!!!!!!!!!\n");
//uart_data_send_head_search(&uartSend, 110);
//usleep(50000);
uart_data_send_search(&uartSend,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
isSearchLabel=false;
}
#endif
if(isLightOnByRule){
#if 0
uint16_t label2=strtol("FF01",NULL,16)&0xFFFF;
uint32_t label3=strtol("663855c0",NULL,16);
uint16_t flash_i=strtol("1",NULL,16)&0xFFFF;
uint16_t light_d=strtol("5",NULL,16)&0xFFFF;
jt_ledctrl_package_t led_ctrl={
.s.color=1,
.s.sound=1,
.s.flash=1,
};
uart_data_send_light_rule(&uartSend,atoi("03"),label2,label3,
atoi("0"), atoi("0"),atoi("0"),
led_ctrl.ch,
flash_i,light_d);
#else
uint16_t label2=strtol(mqtt_parm.msg_label2,NULL,16)&0xFFFF;
uint32_t label3=strtol(mqtt_parm.msg_label3,NULL,16);
uint16_t flash_i=strtol(mqtt_parm.msg_flashInterval,NULL,16)&0xFFFF;
uint16_t light_d=strtol(mqtt_parm.msg_lightDuration,NULL,16)&0xFFFF;
uint8_t changecolor=0;
//8灭 1红 2黄 3蓝 4绿 5青 6白 7紫 tuxi
//0灭 1蓝 2绿 3青 4红 5紫 6黄 7白 yitaile
if(strcmp(mqtt_parm.msg_color,"1")==0){
changecolor=4;
}else if(strcmp(mqtt_parm.msg_color,"2")==0){
changecolor=6;
}else if(strcmp(mqtt_parm.msg_color,"3")==0){
changecolor=1;
}else if(strcmp(mqtt_parm.msg_color,"4")==0){
changecolor=2;
}else if(strcmp(mqtt_parm.msg_color,"5")==0){
changecolor=3;
}else if(strcmp(mqtt_parm.msg_color,"6")==0){
changecolor=7;
}else if(strcmp(mqtt_parm.msg_color,"7")==0){
changecolor=5;
}else if(strcmp(mqtt_parm.msg_color,"8")==0){
changecolor=0;
}
jt_ledctrl_package_t led_ctrl={
.s.color=changecolor,
.s.sound=atoi(mqtt_parm.msg_sound),
.s.flash=atoi(mqtt_parm.msg_flash),
};
uart_data_send_light_rule(&uartSend,atoi(mqtt_parm.msg_label1),label2,label3,
atoi(mqtt_parm.msg_label1Rule), atoi(mqtt_parm.msg_label2Rule),atoi(mqtt_parm.msg_label3Rule),
led_ctrl.ch,
flash_i,light_d);
#endif
isLightOnByRule=false;
}
if(isLabelUp){
#if 0
time_t now = time(NULL);
if(label_buf_count > 0 && (label_buf_count >= LABEL_BATCH_SIZE || (now - label_buf_first_time) >= 180)) {
uart_data_send_head_lableup(&uartSend, 5, label_buf_count);
usleep(10000);
uart_data_send_lable(&uartSend, tags_buf, lable1_buf, lable2_buf, lable3_buf, label_buf_count);
label_buf_count = 0;
label_buf_first_time = 0;
isLabelUp = false;
}
#endif
}
}else if(parm_ack==0x4646){
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
isSendComEnd=true;
}else if(parm_ack==0x4f4f){
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
isSendComEnd=true;
if(isOtaEnable){
otaCount++;
if(otaCount>=2){
otaCount=0;
isLEDOtaSuccess=true;
isOtaEnable=false;
system("echo 1 > /sys/class/gpio/gpio113/value");
}
}
}else if(parm_ack==0x5252){
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
uart_data_receive_version(&uartSend);
isSendComEnd=true;
isAPOtaSuccess=true;
}else if(parm_ack==0x6464){
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
isSendComEnd=true;
}else if(parm_ack==0x4848){
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
isAPBack=true;
}
}
usleep(100*1000);
}
}
void *thread_uart_recv_data(void *arg){
prctl(PR_SET_NAME, "uart_data");
uint16_t parmAck;
uint32_t tagCode;
uint8_t tagSignal;
uint8_t totalLen;
uint8_t tagFeature;
uint8_t count;
uint16_t batteryV;
uint16_t version;
uint8_t ledCtrl;
uint8_t lable1;
uint16_t lable2;
uint32_t lable3;
#if 1
while(1){
int ret = uart_data_receive_data_back(&uartRecvData,&parmAck,&tagCode,&tagSignal,&totalLen,&tagFeature,
&count,&batteryV,&version,&ledCtrl,&lable1,&lable2,&lable3);
//LOG_I("recv_data:%04x,%08x,%02x,%02x,%02x,%02x,%04x,%04x,%02x,%02x,%04x,%08x\n",parmAck,tagCode,tagSignal,totalLen,
//tagFeature,count,batteryV,version,ledCtrl,lable1,lable2,lable3);
//sleep(2);
if(ret <= 0) {
usleep(1000); // 1ms延时避免空转
} else {
usleep(100); // 0.1ms延时,保证处理效率
}
}
#endif
}
void *thread_uart_recv_back(void *arg){
prctl(PR_SET_NAME, "uart_back");
uint16_t parmAck;
uint32_t tagCode;
uint8_t tagSignal;
uint8_t totalLen;
uint8_t tagFeature;
uint8_t count;
uint16_t batteryV;
uint16_t version;
uint8_t ledCtrl;
uint8_t lable1;
uint16_t lable2;
uint32_t lable3;
while(1){
uart_data_receive_data_back(&uartRecvBack,&parmAck,&tagCode,&tagSignal,&totalLen,&tagFeature,
&count,&batteryV,&version,&ledCtrl,&lable1,&lable2,&lable3);
//LOG_I("recv_back:%04x,%08x,%02x,%02x,%02x,%02x,%04x,%04x,%02x,%02x,%04x,%08x\n",parmAck,tagCode,tagSignal,totalLen,
//tagFeature,count,batteryV,version,ledCtrl,lable1,lable2,lable3);
//if(tagCode>0x90000000){
// PutDataIntoQueue(tagCode,batteryV);
//}
PutDataIntoQueue(tagCode,batteryV);
if(tagFeature==0x83){
LOG_I("search tag:%08x,battery:%04x\n",tagCode,batteryV);
}else if(tagFeature==0x82){
//LOG_I("light down tag:%08x,battery:%04x\n",tagCode,batteryV);
light_off_tag_report(tagCode,batteryV);
//light_battery_report(tagCode,batteryV);
}else if(tagFeature==0x81){
LOG_I("key down tag:%08x,battery:%04x,version:%4x\n",tagCode,batteryV,version);
}else if(tagFeature==0xff){
//LOG_I("heart tag:%08x,battery:%04x,version:%4x\n",tagCode,batteryV,version);
}else if(tagFeature==0x84) {
LOG_I("light on tag:%08x,battery:%04x,version:%4x\n",tagCode,batteryV,version);
}
}
}
void light_off_tag_report(uint32_t name,uint16_t batteryv){
json_object *lights = NULL;
lights=json_object_new_array();
char tagName[9]={0};
char battery[5]={0};
sprintf(tagName,"%08X",name);
sprintf(battery,"%d",batteryv);
json_object *light = json_object_new_object();
json_object_object_add(light, "sn", json_object_new_string(tagName));
json_object_object_add(light, "battery", json_object_new_string(battery));
json_object_array_add(lights,light);
json_object *lights_2 = json_object_new_array();
json_object *light_2 = json_object_new_object();
json_object_object_add(light_2, "sn", json_object_new_string(tagName));
json_object_object_add(light_2, "battery", json_object_new_string(battery));
json_object_array_add(lights_2, light_2);
char myid[32]={0};
myrand(myid,19);
mqtt_server_light_status_report(stationsn,myid,"2",lights);
//mqtt_server_light_status_report_2(stationsn,myid,"2",lights_2);
}
void search_tag_report(){
int report_num=0;
int i=0,j=0,m=0,n=0;
copyOnlyTag();
LOG_I("%s tagCount:%d\n",__func__,tagCount);
LOG_I("%s tagCountNew:%d\n",__func__,tagCountNew);
if(tagCountNew>200){
for(i=0;i<tagCountNew/200;i++){
json_object *lights =json_object_new_array();
json_object *lights2 =json_object_new_array();
for(j=i*200;j<i*200+200;j++){
LOG_I("onlyTags:%08X,%04x\n",onlyTagsNew[j].name,onlyTagsNew[j].battery);
char tagName[9]={0};
char battery[5]={0};
sprintf(tagName,"%08X",onlyTagsNew[j].name);
sprintf(battery,"%d",onlyTagsNew[j].battery);
json_object *light = json_object_new_object();
json_object_object_add(light, "sn", json_object_new_string(tagName));
json_object_object_add(light, "battery", json_object_new_string(battery));
json_object_array_add(lights,light);
json_object *light2 = json_object_new_object();
json_object_object_add(light2, "sn", json_object_new_string(tagName));
json_object_object_add(light2, "battery", json_object_new_string(battery));
json_object_array_add(lights2,light2);
}
report_num+=200;
LOG_I("report_num:%d\n",report_num);
mqtt_server_light_status_report(stationsn,mqtt_parm.msg_messageId,"1",lights);
mqtt_server_light_status_report_test(stationsn,mqtt_parm.msg_messageId,"1",lights2);
}
json_object *lights =json_object_new_array();
json_object *lights2 =json_object_new_array();
for(m=i*200;m<i*200+(tagCountNew%200);m++){
LOG_I("onlyTags:%08X,%04x\n",onlyTagsNew[m].name,onlyTagsNew[m].battery);
char tagName[9]={0};
char battery[5]={0};
sprintf(tagName,"%08X",onlyTagsNew[m].name);
sprintf(battery,"%d",onlyTagsNew[m].battery);
json_object *light = json_object_new_object();
json_object_object_add(light, "sn", json_object_new_string(tagName));
json_object_object_add(light, "battery", json_object_new_string(battery));
json_object_array_add(lights,light);
json_object *light2 = json_object_new_object();
json_object_object_add(light2, "sn", json_object_new_string(tagName));
json_object_object_add(light2, "battery", json_object_new_string(battery));
json_object_array_add(lights2,light2);
}
report_num+=m-i*200;
//report_num+=tagCountNew%200;
LOG_I("report_num:%d\n",report_num);
mqtt_server_light_status_report(stationsn,mqtt_parm.msg_messageId,"1",lights);
mqtt_server_light_status_report_test(stationsn,mqtt_parm.msg_messageId,"1",lights2);
}else{
json_object *lights =json_object_new_array();
json_object *lights2 =json_object_new_array();
for(n=0;n<tagCountNew;n++){
LOG_I("onlyTags:%08X,%04x\n",onlyTagsNew[n].name,onlyTagsNew[n].battery);
char tagName[9]={0};
char battery[5]={0};
sprintf(tagName,"%08X",onlyTagsNew[n].name);
sprintf(battery,"%d",onlyTagsNew[n].battery);
json_object *light = json_object_new_object();
json_object_object_add(light, "sn", json_object_new_string(tagName));
json_object_object_add(light, "battery", json_object_new_string(battery));
json_object_array_add(lights,light);
json_object *light2 = json_object_new_object();
json_object_object_add(light2, "sn", json_object_new_string(tagName));
json_object_object_add(light2, "battery", json_object_new_string(battery));
json_object_array_add(lights2,light2);
}
report_num=tagCountNew;
LOG_I("report_num:%d\n",report_num);
mqtt_server_light_status_report(stationsn,mqtt_parm.msg_messageId,"1",lights);
mqtt_server_light_status_report_test(stationsn,mqtt_parm.msg_messageId,"1",lights2);
}
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
tagCountNew=0;
memset(onlyTagsNew,0,5000);
}
void copyOnlyTag(void){
int i=0;
tagCountNew=0;
for(i=0;i<tagCount;i++){
if(getCurrentTime()-onlyTags[i].time<=60*50){
onlyTagsNew[tagCountNew]=onlyTags[i];
tagCountNew++;
}
}
LOG_I("tagCountNew:%d\n",tagCountNew);
}
void addOnlyTag(uint32_t tagname,uint16_t battery){
int i=0;
if(tagCount==0){
jt_only_tag_t jt_only_tag = {
.name=tagname,
.battery=battery,
.time=getCurrentTime(),
};
onlyTags[tagCount]=jt_only_tag;
tagCount++;
}else{
for(i=0;i<tagCount;i++){
if(tagname==onlyTags[i].name){
onlyTags[i].time=getCurrentTime();
break;
}
}
if(i==tagCount){
jt_only_tag_t jt_only_tag = {
.name=tagname,
.battery=battery,
.time=getCurrentTime(),
};
onlyTags[tagCount]=jt_only_tag;
tagCount++;
}
}
}
void *thread_remove_duplicate_tag(void *arg){
prctl(PR_SET_NAME, "rm_dup_tag");
uint32_t tagname=0;
uint16_t battery=0;
while(1){
if(!isSearchReport){
if(GetDataFromQueue(&tagname,&battery)==0){
//LOG_I("%08x,%04x\n",tagname,battery);
addOnlyTag(tagname,battery);
}
}
}
}
// 检查文件是否存在的函数
static int file_exists(const char *path) {
struct stat st;
return (stat(path, &st) == 0);
}
// 检查压缩包是否解压完成
static int check_unzip_complete(const char *zip_file) {
char cmd[256];
char last_file[256] = {0};
FILE *fp;
// 获取压缩包中最后一个文件
snprintf(cmd, sizeof(cmd), "unzip -l %s | tail -n 1 | awk '{print $4}'", zip_file);
fp = popen(cmd, "r");
if (fp == NULL) {
LOG_E("Failed to execute command: %s", cmd);
return -1;
}
if (fgets(last_file, sizeof(last_file), fp) == NULL) {
LOG_E("Failed to get last file from zip");
pclose(fp);
return -1;
}
pclose(fp);
// 去除换行符
last_file[strcspn(last_file, "\n")] = 0;
// 检查文件是否存在
char full_path[512];
snprintf(full_path, sizeof(full_path), "tx_ota/%s", last_file);
int retry_count = 0;
const int max_retries = 30; // 最多等待30秒
while (!file_exists(full_path) && retry_count < max_retries) {
usleep(1000000); // 等待1秒
retry_count++;
}
if (retry_count >= max_retries) {
LOG_E("Timeout waiting for unzip to complete");
return -1;
}
return 0;
}
void *thread_mqtt_recv(void *arg){
prctl(PR_SET_NAME, "mqtt_recv");
char payload[1024]={0};
char msg_body_value[1024] ={0};
char msg_body[1024] = {0};
char msg_data_value[1024] = {0};
char msg_data[1024] = {0};
char msg_labelconfig_value[1024] = {0};
char msg_labelconfig[1024] = {0};
char msg_lightsn_value[128] = {0};
char msg_lightsn[128] = {0};
while(1){
if(isSendComEnd){
if(GetDataFromMQueue(payload)==0){
//getPayloadTime=120*1000;
LOG_I("payload:%s\n",payload);
get_string_from_json_string_by_key_unescape(payload,"messageId",mqtt_parm.msg_messageId,sizeof(mqtt_parm.msg_messageId));
//LOG_I("messageId:%s\n",mqtt_parm.msg_messageId);
if(isSearchLabelOn){
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"search busy",0,productid);
}else{
get_string_from_json_string_by_key_unescape(payload,"deviceId",mqtt_parm.msg_deviceId,sizeof(mqtt_parm.msg_deviceId));
LOG_I("deviceId:%s\n",mqtt_parm.msg_deviceId);
get_int_from_json_string_by_key(payload,"timestamp",&mqtt_parm.msg_timestamp);
LOG_I("timestamp:%d\n",mqtt_parm.msg_timestamp);
get_string_from_json_string_by_key_unescape(payload, "msg", msg_body_value, sizeof(msg_body_value));
snprintf(msg_body, sizeof(msg_body), "%s", msg_body_value);
LOG_I("msg_body:%s\n",msg_body);
get_string_from_json_string_by_key_unescape(msg_body, "msgType", mqtt_parm.msg_type, sizeof(mqtt_parm.msg_type));
LOG_I("msgType:%s\n",mqtt_parm.msg_type);
get_string_from_json_string_by_key_unescape(msg_body, "data", msg_data_value, sizeof(msg_data_value));
snprintf(msg_data, sizeof(msg_data), "{%s}", msg_data_value);
LOG_I("msg_data:%s\n",msg_data);
if(strcmp(mqtt_parm.msg_type,"1001")==0){
LOG_I("1001 dev disable\n");
isLightEnable=false;
buffer_to_file("LightEnable","disable",strlen("disable"),"wb");
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
}else if(strcmp(mqtt_parm.msg_type,"1002")==0){
LOG_I("1002 dev enable\n");
isLightEnable=true;
buffer_to_file("LightEnable","enable",strlen("enable"),"wb");
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
}else if(strcmp(mqtt_parm.msg_type,"1005")==0){
LOG_I("1005 dev reboot\n");
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
system("sync");
sleep(10);
system("sync");
system("reboot");
}else if(strcmp(mqtt_parm.msg_type,"1014")==0){
LOG_I("1014 update fw\n");
isSendComEnd=false;
get_int_from_json_string_by_key(msg_data, "needWifi", &mqtt_parm.msg_needWifi);
LOG_I("needWifi:%d\n",mqtt_parm.msg_needWifi);
get_string_from_json_string_by_key_unescape(msg_data, "zipPath", mqtt_parm.msg_zipPath, sizeof(mqtt_parm.msg_zipPath));
LOG_I("zipPath:%s\n",mqtt_parm.msg_zipPath);
get_int_from_json_string_by_key(msg_data, "installType", &mqtt_parm.msg_installType);
LOG_I("installType:%d\n",mqtt_parm.msg_installType);
get_int_from_json_string_by_key(msg_data, "immediately", &mqtt_parm.msg_immediately);
LOG_I("immediately:%d\n",mqtt_parm.msg_immediately);
get_int_from_json_string_by_key(msg_data, "installTime", &mqtt_parm.msg_installTime);
LOG_I("installTime:%d\n",mqtt_parm.msg_installTime);
get_string_from_json_string_by_key_unescape(msg_data, "version", mqtt_parm.msg_version, sizeof(mqtt_parm.msg_version));
LOG_I("version:%s\n",mqtt_parm.msg_version);
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
char otaCmd[256]={0};
sprintf(otaCmd,"curl -o /userdata/tx_ota.zip %s",mqtt_parm.msg_zipPath);
//sprintf(otaCmd,"curl -o /root/tx_server https://fscdn.zto.com/cloudm/iot-device-package/7d609af2165b4d14ae318f17659b2fbf.bin");
system(otaCmd);
sleep(15);
system("unzip /userdata/tx_ota.zip");
//system("mv ../tx_ota/* /userdata/ota");
//system("rm -fr /userdata/ota/tx_ota");
system("rm -fr /userdata/ota");
system("mv /userdata/tx_ota /userdata/ota");
system("mv /userdata/ota/ustart.sh /userdata");
system("cp /userdata/ota/tx_server /tmp/tx_server_new");
LOG_I("cp /userdata/ota/tx_server /tmp/tx_server_new\n");
system("chmod +x /tmp/tx_server_new");
system("mv /tmp/tx_server_new /userdata/tx_server");
system("sync");
sleep(2);
restart_tx_server_service();
}else if(strcmp(mqtt_parm.msg_type,"5003")==0){
LOG_I("5003 need report station info\n");
updateStationInfo(mqtt_parm.msg_messageId);
}else if(strcmp(mqtt_parm.msg_type,"5005")==0){
LOG_I("5005 cloud search light\n");
//isSendComEnd=false;
isLightOn=false;
isLightOnByRule=false;
isLabelUp=false;
//isSearchLabel=true;
get_string_from_json_string_by_key_unescape(msg_data, "scene", mqtt_parm.msg_scene, sizeof(mqtt_parm.msg_scene));
LOG_I("scene:%s\n",mqtt_parm.msg_scene);
get_string_from_json_string_by_key_unescape(msg_data, "timeout", mqtt_parm.msg_timeout, sizeof(mqtt_parm.msg_timeout));
LOG_I("timeout:%s\n",mqtt_parm.msg_timeout);
searchTimeOut=atoi(mqtt_parm.msg_timeout);
LOG_I("searchTimeOut:%d\n",searchTimeOut);
searchTimeOld=getCurrentTime();
LOG_I("searchTimeOld:%d\n",searchTimeOld);
uart_data_send_head_search(&uartSend, 120);
isSearchLabelOn=true;
}else if(strcmp(mqtt_parm.msg_type,"3015")==0){
LOG_I("3015 light on (merge mode)\n");
get_string_from_json_string_by_key_unescape(msg_data, "scene", mqtt_parm.msg_scene, sizeof(mqtt_parm.msg_scene));
DEBUG_TX("scene:%s\n",mqtt_parm.msg_scene);
get_string_from_json_string_by_key_unescape(msg_data, "lights", mqtt_parm.msg_lights, sizeof(mqtt_parm.msg_lights));
DEBUG_TX("lights:%s\n",mqtt_parm.msg_lights);
get_size_from_json_string_arry_by_key(msg_data, "lights", &mqtt_parm.msg_opNumber);
DEBUG_TX("lights size = %d\n", mqtt_parm.msg_opNumber);
get_string_from_json_string_by_key_unescape(msg_data, "color", mqtt_parm.msg_color, sizeof(mqtt_parm.msg_color));
DEBUG_TX("color:%s\n",mqtt_parm.msg_color);
get_string_from_json_string_by_key_unescape(msg_data, "sound", mqtt_parm.msg_sound, sizeof(mqtt_parm.msg_sound));
DEBUG_TX("sound:%s\n",mqtt_parm.msg_sound);
get_string_from_json_string_by_key_unescape(msg_data, "flash", mqtt_parm.msg_flash, sizeof(mqtt_parm.msg_flash));
DEBUG_TX("flash:%s\n",mqtt_parm.msg_flash);
get_string_from_json_string_by_key_unescape(msg_data, "flashInterval", mqtt_parm.msg_flashInterval, sizeof(mqtt_parm.msg_flashInterval));
DEBUG_TX("flashInterval:%s\n",mqtt_parm.msg_flashInterval);
get_string_from_json_string_by_key_unescape(msg_data, "lightDuration", mqtt_parm.msg_lightDuration, sizeof(mqtt_parm.msg_lightDuration));
DEBUG_TX("lightDuration:%s\n",mqtt_parm.msg_lightDuration);
pthread_mutex_lock(&lightsn_buffer_mutex);
if (!is_3015_collecting) {
is_3015_collecting = true;
first_3015_time = time(NULL);
lightsn_buffer_count = 0;
memset(lightsn_buffer, 0, sizeof(lightsn_buffer));
memset(color_buffer, 0, sizeof(color_buffer));
memset(sound_buffer, 0, sizeof(sound_buffer));
memset(flash_buffer, 0, sizeof(flash_buffer));
}
int i;
char msg_lightsn_value[128] = {0};
char msg_lightsn[128] = {0};
for (i = 0; i < mqtt_parm.msg_opNumber && lightsn_buffer_count < MAX_LIGHTSN_BUFFER; i++) {
get_string_from_json_string_arry_by_key(msg_data, "lights", msg_lightsn_value, 128, i);
snprintf(msg_lightsn, sizeof(msg_lightsn), "{%s}", msg_lightsn_value);
get_string_from_json_string_by_key_unescape(msg_lightsn, "sn", lightsn_buffer[lightsn_buffer_count], 32);
get_string_from_json_string_by_key_unescape(msg_lightsn, "color", color_buffer[lightsn_buffer_count], 8);
get_string_from_json_string_by_key_unescape(msg_lightsn, "sound", sound_buffer[lightsn_buffer_count], 8);
get_string_from_json_string_by_key_unescape(msg_lightsn, "flash", flash_buffer[lightsn_buffer_count], 8);
if (strlen(color_buffer[lightsn_buffer_count]) == 0) strcpy(color_buffer[lightsn_buffer_count], mqtt_parm.msg_color);
if (strlen(sound_buffer[lightsn_buffer_count]) == 0) strcpy(sound_buffer[lightsn_buffer_count], mqtt_parm.msg_sound);
if (strlen(flash_buffer[lightsn_buffer_count]) == 0) strcpy(flash_buffer[lightsn_buffer_count], mqtt_parm.msg_flash);
LOG_I("buffered sn: %s, color: %s, sound: %s, flash: %s\n", lightsn_buffer[lightsn_buffer_count], color_buffer[lightsn_buffer_count], sound_buffer[lightsn_buffer_count], flash_buffer[lightsn_buffer_count]);
lightsn_buffer_count++;
}
pthread_mutex_unlock(&lightsn_buffer_mutex);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "ok", 1, productid);
}else if(strcmp(mqtt_parm.msg_type,"3022")==0){
LOG_I("3022 updata lable\n");
char sn_str[32] = {0};
char label1_str[8] = {0};
char label2_str[8] = {0};
char label3_str[16] = {0};
get_string_from_json_string_by_key_unescape(msg_data, "sn", sn_str, sizeof(sn_str));
get_string_from_json_string_by_key_unescape(msg_data, "label1", label1_str, sizeof(label1_str));
get_string_from_json_string_by_key_unescape(msg_data, "label2", label2_str, sizeof(label2_str));
get_string_from_json_string_by_key_unescape(msg_data, "label3", label3_str, sizeof(label3_str));
LOG_I("sn:%s\n", sn_str);
LOG_I("label1:%s\n", label1_str);
LOG_I("label2:%s\n", label2_str);
LOG_I("label3:%s\n", label3_str);
if(strcmp(sn_str,"")!=0){
if(label_buf_count == 0) {
label_buf_first_time = time(NULL);
}
tags_buf[label_buf_count] = strtoul(sn_str, NULL, 16);
lable1_buf[label_buf_count] = (uint8_t)atoi(label1_str);
lable2_buf[label_buf_count] = (uint16_t)strtoul(label2_str, NULL, 16);
lable3_buf[label_buf_count] = strtoul(label3_str, NULL, 16);
label_buf_count++;
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "ok", 1, productid);
isSendComEnd = true;
isLightOn = false;
isLightOnByRule = false;
isLabelUp = true;
}else{
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "sn is empty", 0, productid);
}
}else if(strcmp(mqtt_parm.msg_type,"3023")==0){
LOG_I("3023 light on by rule\n");
get_string_from_json_string_by_key_unescape(msg_data, "labelConfig", msg_labelconfig_value, sizeof(msg_labelconfig_value));
snprintf(msg_labelconfig, sizeof(msg_labelconfig), "{%s}", msg_labelconfig_value);
LOG_I("msg_labelconfig:%s\n",msg_labelconfig);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label1", mqtt_parm.msg_label1, sizeof(mqtt_parm.msg_label1));
LOG_I("label1:%s\n",mqtt_parm.msg_label1);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label2", mqtt_parm.msg_label2, sizeof(mqtt_parm.msg_label2));
LOG_I("label2:%s\n",mqtt_parm.msg_label2);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label3", mqtt_parm.msg_label3, sizeof(mqtt_parm.msg_label3));
LOG_I("label3:%s\n",mqtt_parm.msg_label3);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label1Rule", mqtt_parm.msg_label1Rule,
sizeof(mqtt_parm.msg_label1Rule));
LOG_I("label1Rule:%s\n",mqtt_parm.msg_label1Rule);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label2Rule", mqtt_parm.msg_label2Rule,
sizeof(mqtt_parm.msg_label2Rule));
LOG_I("label2Rule:%s\n",mqtt_parm.msg_label2Rule);
get_string_from_json_string_by_key_unescape(msg_labelconfig, "label3Rule", mqtt_parm.msg_label3Rule,
sizeof(mqtt_parm.msg_label3Rule));
LOG_I("label3Rule:%s\n",mqtt_parm.msg_label3Rule);
get_string_from_json_string_by_key_unescape(msg_data, "color", mqtt_parm.msg_color, sizeof(mqtt_parm.msg_color));
LOG_I("color:%s\n",mqtt_parm.msg_color);
get_string_from_json_string_by_key_unescape(msg_data, "sound", mqtt_parm.msg_sound, sizeof(mqtt_parm.msg_sound));
LOG_I("sound:%s\n",mqtt_parm.msg_sound);
get_string_from_json_string_by_key_unescape(msg_data, "flash", mqtt_parm.msg_flash, sizeof(mqtt_parm.msg_flash));
LOG_I("flash:%s\n",mqtt_parm.msg_flash);
get_string_from_json_string_by_key_unescape(msg_data, "flashInterval", mqtt_parm.msg_flashInterval,
sizeof(mqtt_parm.msg_flashInterval));
LOG_I("flashInterval:%s\n",mqtt_parm.msg_flashInterval);
get_string_from_json_string_by_key_unescape(msg_data, "lightDuration", mqtt_parm.msg_lightDuration,
sizeof(mqtt_parm.msg_lightDuration));
LOG_I("lightDuration:%s\n",mqtt_parm.msg_lightDuration);
if(strcmp(msg_labelconfig_value,"")!=0){
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
isSendComEnd=false;
isLightOn=false;
isLightOnByRule=true;
isLabelUp=false;
//isSearchLabel=false;
uart_data_send_head_lightonrule(&uartSend,5);
}else{
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"labelconfig is empty",0,productid);
}
}else if(strcmp(mqtt_parm.msg_type,"3027")==0){
LOG_I("3027 All light on/off 广播点亮\n");
get_string_from_json_string_by_key_unescape(msg_data, "color", mqtt_parm.msg_color, sizeof(mqtt_parm.msg_color));
//strcpy(mqtt_parm.msg_color, "1"); // 默认关闭颜色
LOG_I("color:%s\n",mqtt_parm.msg_color);
get_string_from_json_string_by_key_unescape(msg_data, "sound", mqtt_parm.msg_sound, sizeof(mqtt_parm.msg_sound));
//strcpy(mqtt_parm.msg_sound, "0"); // 默认关闭声音
LOG_I("sound:%s\n",mqtt_parm.msg_sound);
get_string_from_json_string_by_key_unescape(msg_data, "flash", mqtt_parm.msg_flash, sizeof(mqtt_parm.msg_flash));
//strcpy(mqtt_parm.msg_flash, "0"); // 默认关闭闪烁
LOG_I("flash:%s\n",mqtt_parm.msg_flash);
get_string_from_json_string_by_key_unescape(msg_data, "flashInterval", mqtt_parm.msg_flashInterval, sizeof(mqtt_parm.msg_flashInterval));
LOG_I("flashInterval:%s\n",mqtt_parm.msg_flashInterval);
get_string_from_json_string_by_key_unescape(msg_data, "lightDuration", mqtt_parm.msg_lightDuration, sizeof(mqtt_parm.msg_lightDuration));
LOG_I("lightDuration:%s\n",mqtt_parm.msg_lightDuration);
isLightEnable=true;
if(isLightEnable){
LOG_I("isLightEnable1:%d\n",isLightEnable);
//mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"ok",1,productid);
LOG_I("isLightEnable_off:%d\n",isLightEnable);
// 设置规则并广播点亮重置变量防止被3015污染
isSendComEnd=false;
isLightOn=false;
isLightOnByRule=true; // 使用规则控制
isLabelUp=false;
memset(lightsn1, 0, sizeof(lightsn1));
memset(lightsn2, 0, sizeof(lightsn2));
memset(lightsn3, 0, sizeof(lightsn3));
memset(lightsn4, 0, sizeof(lightsn4));
memset(lightsn5, 0, sizeof(lightsn5));
memset(lightsn6, 0, sizeof(lightsn6));
memset(lightsn7, 0, sizeof(lightsn7));
memset(lightsn8, 0, sizeof(lightsn8));
memset(lightsn9, 0, sizeof(lightsn9));
memset(lightsn10, 0, sizeof(lightsn10));
memset(lightsn11, 0, sizeof(lightsn11));
memset(lightsn12, 0, sizeof(lightsn12));
memset(lightsn13, 0, sizeof(lightsn13));
memset(lightsn14, 0, sizeof(lightsn14));
memset(lightsn15, 0, sizeof(lightsn15));
memset(lightsn16, 0, sizeof(lightsn16));
memset(lightsn17, 0, sizeof(lightsn17));
memset(lightsn18, 0, sizeof(lightsn18));
memset(lightsn19, 0, sizeof(lightsn19));
memset(lightsn20, 0, sizeof(lightsn20));
memset(lightsn21, 0, sizeof(lightsn21));
memset(lightsn22, 0, sizeof(lightsn22));
memset(lightsn23, 0, sizeof(lightsn23));
memset(lightsn24, 0, sizeof(lightsn24));
memset(lightsn25, 0, sizeof(lightsn25));
memset(lightsn26, 0, sizeof(lightsn26));
memset(lightsn27, 0, sizeof(lightsn27));
memset(lightsn28, 0, sizeof(lightsn28));
memset(lightsn29, 0, sizeof(lightsn29));
memset(lightsn30, 0, sizeof(lightsn30));
// 设置label1和label2不参与匹配
strcpy(mqtt_parm.msg_label1Rule, "04"); // ∅ 不参与匹配
strcpy(mqtt_parm.msg_label2Rule, "04"); // ∅ 不参与匹配
// 设置label3不等于386cd300的规则
strcpy(mqtt_parm.msg_label3Rule, "03"); // ≠ 不等于
strcpy(mqtt_parm.msg_label3, "386cd300");
// 广播点亮命令
LOG_I("Broadcasting light on command\n");
uart_data_send_head_lightonrule(&uartSend, 5);
// 再次广播,提升可靠性
//usleep(100000); // 等待100ms
//LOG_I("Sending second broadcast\n");
//uart_data_send_head_lightonrule(&uartSend, 5);
}else{
LOG_I("isLightEnable2:%d\n",isLightEnable);
mqtt_service_reply(stationsn,mqtt_parm.msg_messageId,"light disabled",0,productid);
}
} else if(strcmp(mqtt_parm.msg_type,"2333")==0){
LOG_I("2333 文件操作任务\n");
char action[16] = {0};
char filename[128] = {0};
char fullpath[256] = {0};
int op_result = 0;
// 解析action和filename
get_string_from_json_string_by_key_unescape(msg_data, "action", action, sizeof(action));
get_string_from_json_string_by_key_unescape(msg_data, "filename", filename, sizeof(filename));
LOG_I("action: %s, filename: %s\n", action, filename);
// 安全性校验:不允许..和/
if(strstr(filename, "..")){
LOG_I("非法文件名: %s\n", filename);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "invalid filename", 0, productid);
}else if(strlen(filename) == 0){
LOG_I("文件名为空\n");
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "filename empty", 0, productid);
}else{
snprintf(fullpath, sizeof(fullpath), "%s", filename);
if(strcmp(action, "create")==0){
FILE *fp = fopen(fullpath, "w");
if(fp){
fclose(fp);
LOG_I("创建文件成功: %s\n", fullpath);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "create ok", 1, productid);
}else{
LOG_I("创建文件失败: %s, err: %s\n", fullpath, strerror(errno));
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "create failed", 0, productid);
}
}else if(strcmp(action, "delete")==0){
op_result = unlink(fullpath);
if(op_result == 0){
LOG_I("删除文件成功: %s\n", fullpath);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "delete ok", 1, productid);
}else if(errno == ENOENT){
LOG_I("文件不存在, 视为成功: %s\n", fullpath);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "delete ok (not exist)", 1, productid);
}else{
LOG_I("删除文件失败: %s, err: %s\n", fullpath, strerror(errno));
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "delete failed", 0, productid);
}
}else{
LOG_I("未知action: %s\n", action);
mqtt_service_reply(stationsn, mqtt_parm.msg_messageId, "unknown action", 0, productid);
}
}
} else if(strcmp(mqtt_parm.msg_type,"2334")==0){
LOG_I("2334 获取系统资源任务\n");
float cpu_usage = get_cpu_usage();
long mem_total, mem_free, mem_available, mem_used;
float mem_percent;
get_mem_usage(&mem_total, &mem_free, &mem_available, &mem_used, &mem_percent);
long disk_total, disk_free, disk_used;
float disk_percent;
get_disk_usage("/", &disk_total, &disk_free, &disk_used, &disk_percent);
char json[512];
snprintf(json, sizeof(json),
"{\"cpu\":\"%.2f%%\",\"mem_total\":\"%ldMB\",\"mem_used\":\"%ldMB\",\"mem_free\":\"%ldMB\",\"mem_percent\":\"%.2f%%\"," \
"disk_total\":\"%ldMB\",\"disk_used\":\"%ldMB\",\"disk_free\":\"%ldMB\",\"disk_percent\":\"%.2f%%\"}",
cpu_usage, mem_total, mem_used, mem_free, mem_percent,
disk_total, disk_used, disk_free, disk_percent);
mqtt_resource_reply(stationsn, mqtt_parm.msg_messageId, "system", 1, productid, json);
} else if(strcmp(mqtt_parm.msg_type,"2335")==0){
LOG_I("2335 执行命令任务\n");
char cmd[128] = {0};
char result[1024] = {0};
get_string_from_json_string_by_key_unescape(msg_data, "cmd", cmd, sizeof(cmd));
LOG_I("cmd: %s\n", cmd);
if(strstr(cmd, "rm") || strstr(cmd, "reboot") || strstr(cmd, "shutdown")) {
LOG_I("非法或危险命令: %s\n", cmd);
mqtt_resource_reply(stationsn, mqtt_parm.msg_messageId, "system", 0, productid, "invalid or dangerous command");
} else if(strlen(cmd) == 0){
LOG_I("命令为空\n");
mqtt_resource_reply(stationsn, mqtt_parm.msg_messageId, "system", 0, productid, "command empty");
} else {
FILE *fp = popen(cmd, "r");
if(fp){
fread(result, 1, sizeof(result)-1, fp);
pclose(fp);
LOG_I("命令输出: %s\n", result);
mqtt_resource_reply(stationsn, mqtt_parm.msg_messageId, "system", 1, productid, result);
} else {
LOG_I("命令执行失败: %s\n", cmd);
mqtt_resource_reply(stationsn, mqtt_parm.msg_messageId, "system", 0, productid, "command exec failed");
}
}
}
}
}
usleep(getPayloadTime);
}else{
usleep(getPayloadTime);
}
}
}
/*================================================================================*/
void hmacsha1(char *key,char* data,char *signbase64,int signbase64_len){
char result[256]={0};
size_t len=sizeof(result);
//LOG_I("key_len:%d,data_len:%d\n",strlen(key),strlen(data));
hmac_sha1(key,strlen(key),data,strlen(data),result,&len);
//LOG_I("result_len:%d\n",len);
//int t_i;
//for(t_i=0;t_i<len;t_i++)
// printf("%x ",result[t_i]);
Base64_encode( signbase64, signbase64_len, result,strlen(result));
//printf("last:%s\n",signbase64);
}
void getLocalIp(char *local_ip){
char hostname[32]={0};
FILE *fp;
char buffer[64]={0};
//get_ip_by_domain(hostname, local_ip, 32);
fp=popen("ifconfig eth0 | grep 'inet' | awk '{print $2}' | cut -d':' -f2","r");
if (fp) {
fgets(buffer,sizeof(buffer),fp);
//LOG_I("buffer:%s\n",buffer);
memcpy(local_ip,buffer,strlen(buffer)-1);
pclose(fp);
}
}
int getLedOtaVersion(char *filename){
FILE *fp;
char buffer[128]={0};
int ver=0;
fp=popen("ls ota/F8*.bin","r");//tx is F8 begin
if (fp) {
fgets(buffer,sizeof(buffer),fp);
//LOG_I("buffer:%s\n",buffer);
memcpy(filename,buffer,strlen(buffer)-1);
pclose(fp);
}
fp=popen("ls ota/F8*.bin|cut -d'_' -f3|cut -d'.' -f3","r");
if (fp) {
fgets(buffer,sizeof(buffer),fp);
//LOG_I("buffer:%s\n",buffer);
ver=atoi(buffer);
pclose(fp);
}
LOG_I("ver:%d\n",ver);
return ver;
}
int getApOtaVersion(char *filename,char *modename){
FILE *fp;
char buffer[128]={0};
int ver=0;
fp = popen("ls ota/AP*.bin", "r"); // AP begin
if (fp) {
fgets(buffer, sizeof(buffer), fp);
//LOG_I("buffer:%s\n",buffer);
memcpy(filename, buffer, strlen(buffer) - 1);
pclose(fp);
}
fp = popen("ls ota/AP*.bin|cut -d'_' -f6|cut -d'.' -f3", "r");
if (fp) {
fgets(buffer, sizeof(buffer), fp);
//LOG_I("buffer:%s\n",buffer);
ver = atoi(buffer);
LOG_I("ver:%d\n", ver);
pclose(fp);
}
fp = popen("ls ota/AP*.bin|cut -d'_' -f3", "r");
if (fp) {
fgets(buffer, sizeof(buffer), fp);
//LOG_I("buffer:%s\n",buffer);
memcpy(modename, buffer, strlen(buffer) - 1);
pclose(fp);
}
return ver;
}
void saveStartUpTime(){
system("rm ./startUpTime");
struct timeval tv;
char startUpTime[32] = {0};
gettimeofday(&tv, NULL);
snprintf(startUpTime,sizeof(startUpTime),"%ld",tv.tv_sec);
buffer_to_file("startUpTime",startUpTime,strlen(startUpTime),"wb");
}
void calculateStartUpTime(char *startTime){
char *result=NULL;
struct timeval tv;
int len=0;
result=file_to_buffer("startUpTime",&len);
if(result!=NULL){
LOG_I("startUpTime:%s\n",result);
gettimeofday(&tv, NULL);
LOG_I("nowUpTime:%ld\n",tv.tv_sec);
snprintf(startTime,11,"%ld",tv.tv_sec-atoi(result));
}
}
void updateStationInfo(char *msg_id){
char local_ip[32] = {0};
char startTime[11]={0};
getLocalIp(local_ip);
LOG_I("local_ip:%s\n",local_ip);
calculateStartUpTime(startTime);
LOG_I("Time:%s\n",startTime);
mqtt_server_station_status_report(msg_id,productid,stationsn,local_ip,softwareVersion,"1",startTime);
mqtt_server_station_status_report_test(msg_id,productid,stationsn,local_ip,softwareVersion,"1",startTime);
}
bool timeNew(){
struct timeval tv;
gettimeofday(&tv, NULL);
long gettime=tv.tv_sec*1000+tv.tv_usec;
LOG_I("gettime:%ld\n",gettime);
if(gettime<1744000000000){
return false;
}
return true;
}
//==========================================================================================
int main(int argc, char *argv[])
{
int ret = -1;
uint32_t can_id;
char recv_data[8]={0};
char command_buffer[256] = "";
uint32_t len=0;
int getTimeCount=0;
char *readresult=NULL;
char networktype[32]={0};
pthread_t timeout_thread; // 添加超时检测线程变量
char syscmd[256]={0};
LOG_I("version:%s\n",softwareVersion);
FILE *fp = fopen("/userdata/tx_version", "w");
if (fp) {
fprintf(fp, "%s\n", softwareVersion);
fclose(fp);
} else {
LOG_I("Failed to write /userdata/tx_version\n");
}
#if 1
//system("insmod /system/lib/modules/wk2xxx_spi.ko"); //改版后没有此模块
snprintf(syscmd, sizeof(syscmd), "ls Log.*|xargs rm -fr");
system(syscmd);
// 设置时区为 Asia/Shanghai直接修改 /etc/localtime 软链接
unlink("/etc/localtime");
symlink("/usr/share/zoneinfo/Asia/Shanghai", "/etc/localtime");
// 导出 GPIO 63
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "63", 2);
close(fd);
}
}
// 设置 GPIO 63 方向为 in
{
int fd = open("/sys/class/gpio/gpio63/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "in", 2);
close(fd);
}
}
// 导出 GPIO 113
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "112", 3);
write(fd, "113", 3);
write(fd, "114", 3);
write(fd, "115", 3);
write(fd, "117", 3);
close(fd);
}
}
{
int fd = open("/sys/class/gpio/gpio112/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
}
}
// 设置 GPIO 113 方向为 out
{
int fd = open("/sys/class/gpio/gpio113/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
}
}
#if 0
// 导出 GPIO 118
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "118", 3);
close(fd);
}
}
// 设置 GPIO 118 方向为 out
{
int fd = open("/sys/class/gpio/gpio118/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
}
}
#endif
// 导出 GPIO 115
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "115", 3);
close(fd);
}
}
// 设置 GPIO 115 方向为 out
{
int fd = open("/sys/class/gpio/gpio115/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
}
}
// 导出 GPIO 117
{
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "117", 3);
close(fd);
}
}
// 设置 GPIO 117 方向为 out
{
int fd = open("/sys/class/gpio/gpio117/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
}
}
#endif
//setGpio118Low();
setGpio113High();
setGpio114High();
setGpio115High();
setGpio117High();
#if 0
system("insmod /system/lib/modules/wk2xxx_spi.ko");
system("busybox udhcpc -i eth0");
system("timedatectl set-timezone Asia/Shanghai");
system("echo 63 > /sys/class/gpio/export");//reset key
system("echo in > /sys/class/gpio/gpio63/direction");
system("echo 113 > /sys/class/gpio/export");//pin 113 yellow
system("echo out > /sys/class/gpio/gpio113/direction");
#endif
uart_open(&uartRecvData,"/dev/ttyS0");//DT
uart_init(&uartRecvData,115200,8,1,'N',0);
uart_open(&uartRecvBack,"/dev/ttyS1");//HT
uart_init(&uartRecvBack,115200,8,1,'N',0);
uart_open(&uartSend,"/dev/ttyS5");//GT U12 ttyS0,U14 ttyS4,U21 ttysWK0 U13 ttysWK1 U15 ttysWK2 U22 ttysWK3 U20 ttyS1
uart_init(&uartSend,115200,8,1,'N',0);
#if 0
uart_open(&uartSend,"/dev/ttyS0");//DT
uart_init(&uartSend,115200,8,1,'N',0);
uart_open(&uartRecvData,"/dev/ttyS1");//HT
uart_init(&uartRecvData,115200,8,1,'N',0);
uart_open(&uartRecvBack,"/dev/ttyS5");//GT U12 ttyS0,U14 ttyS4,U21 ttysWK0 U13 ttysWK1 U15 ttysWK2 U22 ttysWK3 U20 ttyS1
uart_init(&uartRecvBack,115200,8,1,'N',0);
#endif
#if 0
struct dma_config cfg = {
.buf = malloc(256),
.len = 256
};
// 填充测试数据
memset(cfg.buf, 0x55, 256);
// 启动DMA传输
ioctl(uartSend.uart_fd, DMA_START_TX, &cfg);
#endif
//doCommand_help(0, NULL);
#if 1
enableWatchDog();
ret = pthread_create(&pt_watchdog,NULL,thread_feed_watchdog,NULL);
if(ret!=0){
LOG_I("pthread_create watchdog fail\n");
}else{
LOG_I("pthread_create watchdog success\n");
pthread_detach(pt_watchdog);
}
#endif
#if 0
ret = pthread_create(&pt_reboot,NULL,thread_reboot,NULL);
if(ret!=0){
LOG_I("pthread_create reboot fail\n");
}else{
LOG_I("pthread_create reboot success\n");
pthread_detach(pt_reboot);
}
#endif
ret = pthread_create(&pt_uart_recv_ack,NULL,thread_uart_recv_ack,NULL);
if(ret!=0){
LOG_I("pthread_create uart_recv_ack fail\n");
}else{
pthread_detach(pt_uart_recv_ack);
LOG_I("pthread_create uart_recv_ack success\n");
}
ret = pthread_create(&pt_uart_recv_data,NULL,thread_uart_recv_data,NULL);
if(ret!=0){
LOG_I("pthread_create uart_recv_data fail\n");
}else{
pthread_detach(pt_uart_recv_data);
LOG_I("pthread_create uart_recv_data success\n");
}
ret = pthread_create(&pt_uart_recv_back,NULL,thread_uart_recv_back,NULL);
if(ret!=0){
LOG_I("pthread_create uart_recv_back fail\n");
}else{
pthread_detach(pt_uart_recv_back);
LOG_I("pthread_create uart_recv_back success\n");
}
ret = pthread_create(&pt_mqtt_recv,NULL,thread_mqtt_recv,NULL);
if(ret!=0){
LOG_I("pthread_create mqtt_recv fail\n");
}else{
pthread_detach(pt_mqtt_recv);
LOG_I("pthread_create mqtt_recv success\n");
}
ret = pthread_create(&pt_tagsearch,NULL,thread_tag_search_send,NULL);
if(ret!=0){
LOG_I("pthread_create tag search send fail\n");
}else{
LOG_I("pthread_create tag search success\n");
pthread_detach(pt_tagsearch);
}
ret = pthread_create(&pt_removeduplicatetag,NULL,thread_remove_duplicate_tag,NULL);
if(ret!=0){
LOG_I("pthread_create remove duplicate tag send fail\n");
}else{
LOG_I("pthread_create remove duplicate tag success\n");
pthread_detach(pt_removeduplicatetag);
}
#if 0
ret = pthread_create(&pt_vm_heartbeat, NULL, thread_vm_heartbeat, stationsn);
if(ret!=0){
LOG_I("pthread_create vm heartbeat fail\n");
}else{
LOG_I("pthread_create vm heartbeat success\n");
pthread_detach(pt_vm_heartbeat);
}
#endif
#if 1
ret = pthread_create(&pt_removelog,NULL,thread_removelog,NULL);
if(ret!=0){
LOG_I("pthread_create removelog fail\n");
}else{
LOG_I("pthread_create removelog success\n");
pthread_detach(pt_removelog);
}
#endif
// 创建超时检测线程
ret = pthread_create(&timeout_thread, NULL, thread_timeout_check, NULL);
if(ret!=0){
LOG_I("pthread_create timeout_check fail\n");
}else{
LOG_I("pthread_create timeout_check success\n");
pthread_detach(timeout_thread);
}
// 新增3015合并点亮线程
pthread_t pt_3015_merge;
ret = pthread_create(&pt_3015_merge, NULL, thread_3015_lighton_merge, NULL);
if (ret != 0) {
LOG_I("pthread_create 3015_merge fail\n");
} else {
pthread_detach(pt_3015_merge);
LOG_I("pthread_create 3015_merge success\n");
}
// 新增3022合包批量下发线程
pthread_t pt_label_batch_send;
ret = pthread_create(&pt_label_batch_send, NULL, thread_label_batch_send, NULL);
if (ret != 0) {
LOG_I("pthread_create label_batch_send fail\n");
} else {
pthread_detach(pt_label_batch_send);
LOG_I("pthread_create label_batch_send success\n");
}
#if 0
// 新增模拟3027任务线程
ret = pthread_create(&pt_simulate_3027, NULL, thread_simulate_3027_task, NULL);
if (ret != 0) {
LOG_I("pthread_create simulate_3027 fail\n");
} else {
pthread_detach(pt_simulate_3027);
LOG_I("pthread_create simulate_3027 success\n");
}
#endif
ret = pthread_create(&pt_ota,NULL,thread_ota,NULL);
if(ret!=0){
LOG_I("pthread_create ota fail\n");
}else{
LOG_I("pthread_create ota success\n");
pthread_detach(pt_ota);
}
ret = pthread_create(&pt_doota,NULL,thread_do_ota,NULL);
if(ret!=0){
LOG_I("pthread_create doota fail\n");
}else{
LOG_I("pthread_create doota success\n");
pthread_detach(pt_doota);
}
#if 1
ret = pthread_create(&pt_readqr,NULL,thread_readqr,NULL);
if(ret!=0){
LOG_I("pthread_create readqr fail\n");
}else{
LOG_I("pthread_create readqr success\n");
pthread_detach(pt_readqr);
}
#endif
// 字符串清理函数,去除末尾的空白字符
void trim_whitespace(char *str) {
if (str == NULL) return;
int len = strlen(str);
while (len > 0 && (str[len-1] == '\n' || str[len-1] == '\r' ||
str[len-1] == ' ' || str[len-1] == '\t')) {
str[--len] = '\0';
}
}
readresult=file_to_buffer("savedDevSn",&len);
#if 0
if(readresult==NULL){
// savedDevSn文件不存在尝试从Redis获取SN
LOG_I("savedDevSn file not found, trying to get SN from Redis...\n");
// 初始化Redis SN客户端
if (init_redis_sn_client() == 0) {
LOG_I("Redis SN client initialized successfully\n");
// 尝试从Redis获取设备SN和MAC地址
char redis_sn[32] = {0};
char redis_mac[32] = {0};
if (get_device_sn_and_mac_from_redis(redis_sn, sizeof(redis_sn), redis_mac, sizeof(redis_mac)) == 0) {
// 成功获取到SN和MAC保存SN到文件
LOG_I("Got device SN: %s, MAC: %s from Redis\n", redis_sn, redis_mac);
buffer_to_file("savedDevSn", redis_sn, strlen(redis_sn), "wb");
// 保存MAC地址到文件供getDevRawPassword使用
buffer_to_file("savedDevMac", redis_mac, strlen(redis_mac), "wb");
LOG_I("Device MAC saved to file: %s\n", redis_mac);
strncpy(stationsn, redis_sn, sizeof(stationsn) - 1);
stationsn[sizeof(stationsn) - 1] = '\0';
readresult = redis_sn; // 设置readresult避免进入while循环
len = strlen(redis_sn);
} else {
LOG_I("Failed to get SN from Redis, waiting for manual scan...\n");
}
// 清理Redis客户端资源
cleanup_redis_sn_client();
} else {
LOG_I("Redis SN client initialization failed, waiting for manual scan...\n");
}
}
#endif
// 如果Redis获取失败或savedDevSn文件存在按原逻辑处理
while(readresult==NULL){
readresult=file_to_buffer("savedDevSn",&len);
sleep(5);
LOG_I("please scan sn\n");
//TODO输出日志到180.163.74.83网页
}
strncpy(stationsn,readresult,len);
trim_whitespace(stationsn); // 清理空白字符
readresult=NULL;
LOG_I("saved stationsn:%s\n",stationsn);
#if 1
readresult=file_to_buffer("/userdata/mqttRawPassword",&len);
if(readresult!=NULL){
strncpy(mqttRawPassword,readresult,len);
trim_whitespace(mqttRawPassword); // 清理空白字符
readresult=NULL;
LOG_I("saved mqttRawPassword:%s\n",mqttRawPassword);
}else{
if((ping("8.8.8.8") == 0)||(ping("8.8.4.4") == 0)){
getDevRawPassword(stationsn);
}else{
LOG_I("getDevRawPassword net not ready\n");
sleep(3);
}
}
#endif
readresult=file_to_buffer("/userdata/LightEnable",&len);
if(readresult!=NULL){
if(strcmp(readresult,"enable")==0){
isLightEnable=true;
}else{
isLightEnable=false;
}
readresult=NULL;
}
#if 1
while(1){
if((ping("8.8.8.8") == 0)||(ping("8.8.4.4") == 0)){
LOG_I("net ok\n");
while(!timeNew()){
//LOG_I("sleep\n");
getTimeCount++;
if(getTimeCount==100){
break;
}
sleep(1);
}
saveStartUpTime();
ret = pthread_create(&pt_mqtt,NULL,thread_mqtt,NULL);
if(ret!=0){
LOG_I("pthread_create mqtt fail\n");
}else{
pthread_detach(pt_mqtt);
LOG_I("pthread_create mqtt success\n");
}
break;
}else{
DEBUG_TX("net not ready\n");
sleep(3);
}
}
#endif
#if 1
while(1)
{
// 先检查标准输入是否可用
if (feof(stdin) || ferror(stdin)) {
//LOG_I("stdin error or EOF, sleeping for 1 second\n");
sleep(1);
continue;
}
memset(command_buffer, 0, sizeof(command_buffer));
if (fgets(command_buffer, sizeof(command_buffer), stdin) == NULL) {
usleep(100000);
continue;
}
command_buffer[strcspn(command_buffer, "\n")] = 0;
if (strlen(command_buffer) == 0) {
continue;
}
if(execute_command(command_buffer, (command_t *)&__start_command, (&__stop_command - &__start_command)/2) < 0)
{
LOG_I("unsupport command!\r\n");
}
}
#endif
return 0;
}
// 超时检测线程
void *thread_timeout_check(void *arg) {
prctl(PR_SET_NAME, "timeout_check");
while(1) {
if(last_2323_time != 0 && waiting_for_4646) { // 只有在等待0x4646时才检查超时
time_t current_time;
time(&current_time);
if(difftime(current_time, last_2323_time) >= 10.0) { // 超过10秒
LOG_I("thread_timeout_check: Timeout after receiving 0x2323, no 0x4646 received, setting isSendComEnd to 1\n");
isSendComEnd = 1;
last_2323_time = 0; // 重置时间
waiting_for_4646 = false; // 重置等待状态
isLightEnable = 1; // 重置点亮使能标志
isLightOn = false; // 重置点亮状态
isLightOnByRule = false; // 重置规则点亮状态
isLabelUp = false; // 重置标签更新状态
}
}
usleep(100*1000); // 每100ms检查一次
}
return NULL;
}
// 合并点亮线程
void *thread_3015_lighton_merge(void *arg) {
int total_all = 0;
while (1) {
//pthread_mutex_lock(&lightsn_buffer_mutex);
if (is_3015_collecting) {
time_t now = time(NULL);
if ((now - first_3015_time >= 3) || (lightsn_buffer_count >= MAX_LIGHTSN_BUFFER)) {
int total = lightsn_buffer_count;
total_all += total;
int batch_size = 10;
int sent = 0;
while (sent < total) {
int this_batch = (total - sent > batch_size) ? batch_size : (total - sent);
DEBUG_TX("-------total:%d, sent:%d, this batch: %d------\n", total, sent, this_batch);
if (isLightEnable && this_batch > 0) {
isLightOn = true;
isLightOnByRule = false;
isLabelUp = false;
uint32_t tags[10] = {0};
uint8_t tag_leds[10] = {0};
for (int i = 0; i < this_batch; i++) {
DEBUG_TX("sn[%d]=%s\n", sent + i + 1, lightsn_buffer[sent + i]);
// 1. SN转MACHEX字符串转uint32_t
if (strlen(lightsn_buffer[sent + i]) == 8) {
tags[i] = (uint32_t)strtoul(lightsn_buffer[sent + i], NULL, 16);
} else {
DEBUG_TX("[WARN] tag[%d] sn格式非法: %s, 跳过", sent + i, lightsn_buffer[sent + i]);
continue;
}
// 2. 颜色+闪光+声音合成LED控制字节协议格式
int flash = (strlen(flash_buffer[sent + i]) > 0) ? atoi(flash_buffer[sent + i]) : atoi(mqtt_parm.msg_flash); // "1"=闪光, "0"=常亮
int sound = (strlen(sound_buffer[sent + i]) > 0) ? atoi(sound_buffer[sent + i]) : atoi(mqtt_parm.msg_sound); // "1"=有声, "0"=无声
int changecolor = 0;
if(strcmp(color_buffer[sent + i],"1")==0){
changecolor=4;
}else if(strcmp(color_buffer[sent + i],"2")==0){
changecolor=6;
}else if(strcmp(color_buffer[sent + i],"3")==0){
changecolor=1;
}else if(strcmp(color_buffer[sent + i],"4")==0){
changecolor=2;
}else if(strcmp(color_buffer[sent + i],"5")==0){
changecolor=3;
}else if(strcmp(color_buffer[sent + i],"6")==0){
changecolor=7;
}else if(strcmp(color_buffer[sent + i],"7")==0){
changecolor=5;
}else if(strcmp(color_buffer[sent + i],"8")==0){
changecolor=0;
}
uint8_t led_val = 0;
if (flash) led_val |= 0x40; // Bit6
if (sound) led_val |= 0x10; // Bit4
led_val |= (changecolor & 0x0F); // 低4位为颜色
tag_leds[i] = led_val;
}
uint8_t changecolor=0;
if(strcmp(mqtt_parm.msg_color,"1")==0){
changecolor=4;
}else if(strcmp(mqtt_parm.msg_color,"2")==0){
changecolor=6;
}else if(strcmp(mqtt_parm.msg_color,"3")==0){
changecolor=1;
}else if(strcmp(mqtt_parm.msg_color,"4")==0){
changecolor=2;
}else if(strcmp(mqtt_parm.msg_color,"5")==0){
changecolor=3;
}else if(strcmp(mqtt_parm.msg_color,"6")==0){
changecolor=7;
}else if(strcmp(mqtt_parm.msg_color,"7")==0){
changecolor=5;
}else if(strcmp(mqtt_parm.msg_color,"8")==0){
changecolor=0;
}
jt_ledctrl_package_t led_ctrl={
.s.color=changecolor,
.s.sound=atoi(mqtt_parm.msg_sound),
.s.flash=atoi(mqtt_parm.msg_flash),
};
uart_data_send_head_lightband(&uartSend, 5, this_batch);
usleep(50000);
uart_data_send_lightband(&uartSend, led_ctrl.ch, atoi(mqtt_parm.msg_flash), atoi(mqtt_parm.msg_lightDuration), tags, tag_leds, this_batch);
usleep(150000);
uart_data_send_head_lightband(&uartSend, 5, this_batch);
usleep(50000);
uart_data_send_lightband(&uartSend, led_ctrl.ch, atoi(mqtt_parm.msg_flash), atoi(mqtt_parm.msg_lightDuration), tags, tag_leds, this_batch);
}
sent += this_batch;
if (sent < total) {
sleep(3);
}
DEBUG_TX("total_all: %d\n", total_all);
}
// 不要立即清空buffer等待isLightOn处理完成
is_3015_collecting = false;
first_3015_time = 0;
isLightOn = false;
}
}
//pthread_mutex_unlock(&lightsn_buffer_mutex);
usleep(100*1000);
}
return NULL;
}
// 3022合包批量下发线程
void *thread_label_batch_send(void *arg) {
while (1) {
if (isLightOnByRule == false && isLightOn == false) {
time_t now = time(NULL);
if (label_buf_count > 0 && (label_buf_count >= 10 || (now - label_buf_first_time) >= 60)) {
uart_data_send_head_lableup(&uartSend, 5, label_buf_count);
usleep(10000);
uart_data_send_lable(&uartSend, tags_buf, lable1_buf, lable2_buf, lable3_buf, label_buf_count);
label_buf_count = 0;
label_buf_first_time = 0;
isLabelUp = false;
}
}
usleep(1000 * 1000); // 每秒检查一次
}
return NULL;
}
void light_battery_report(uint32_t tagCode, uint16_t batteryV) {
const char *url = "http://180.163.74.83:8428/api/v1/import/prometheus";
char post_data[256];
CURL *curl = curl_easy_init();
if (!curl) {
DEBUG_TX("curl init failed\n");
return;
}
time_t now = time(NULL);
// Prometheus exposition format: light_battery{tag="xxxxxx"} value timestamp
snprintf(post_data, sizeof(post_data),
"light_battery{tag=\"%08X\"} %d\n", tagCode, batteryV);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
DEBUG_TX("send light_battery_report failed: %s\n", curl_easy_strerror(res));
} else {
DEBUG_TX("light_battery_report sent: %s", post_data);
}
curl_easy_cleanup(curl);
}
// 模拟3027任务发送线程
void *thread_simulate_3027_task(void *arg) {
prctl(PR_SET_NAME, "sim_3027");
// 等待系统初始化完成
sleep(10);
while (1) {
// 构造3027任务的JSON消息
char simulate_payload[1024];
snprintf(simulate_payload, sizeof(simulate_payload),
"{"
"\"deviceId\": \"TJ251679787196\","
"\"messageId\": \"1933039995430551552\","
"\"msg\": \"{\\\"data\\\":{\\\"color\\\":\\\"7\\\",\\\"flash\\\":\\\"0\\\",\\\"flashInterval\\\":\\\"4\\\",\\\"lightDuration\\\":\\\"30\\\",\\\"sound\\\":\\\"0\\\"},\\\"msgType\\\":\\\"3027\\\"}\","
"\"timestamp\": 2147483647"
"}");
// 将模拟的3027任务放入消息队列
PutDataIntoMQueue(simulate_payload);
LOG_I("Simulated 3027 task sent: %s\n", simulate_payload);
// 等待2分钟 (120秒)
sleep(120);
}
return NULL;
}