From: 胡传军 <1224667075@qq.com> Date: Sun, 26 Oct 2025 13:03:50 +0000 (+0000) Subject: Merge #2604 into sdk650pathc0423 from refs/changes/2604/head X-Git-Tag: V1.0.9_20251128_194606_LN~170^2 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=f6a264de73300ebd2488ddb1e645dd10eaa8411a;p=mirrors%2FFD230.git Merge #2604 into sdk650pathc0423 from refs/changes/2604/head Code review from 胡传军 * refs/changes/2604/head: (14 commits squashed) - 增加优化 EG810 雷鸟对话 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - 修改雷鸟 播放卡顿问题 - sos修改 - 合并 - 修改 cat1 python的tcp控制逻辑 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - 同步雷鸟修改 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - 增加cat1升级服务 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 - 增加vad 雷鸟对话,仅可自动结束 Signed-off-by: aliyun8003852482 <1224667075@qq.com> Reviewed-by: snickersun@163.com Merged-by: snickersun@163.com CR-link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2604 --- diff --git a/code/sdk/zhihui/4g/cat1Service/CMakeLists.txt b/code/sdk/zhihui/4g/cat1Service/CMakeLists.txt index 62ff46318..691a92a79 100644 --- a/code/sdk/zhihui/4g/cat1Service/CMakeLists.txt +++ b/code/sdk/zhihui/4g/cat1Service/CMakeLists.txt @@ -9,6 +9,20 @@ set(COMPONENT_NAME "cat1Service") set(PUBLIC_HEADER ) +if( (BOARD_FD230 IN_LIST DEFINES )) + set(DEVICE_PATH fd230) +elseif( BOARD_W9 IN_LIST DEFINES ) + set(DEVICE_PATH w9) +elseif( BOARD_FD272 IN_LIST DEFINES ) + set(DEVICE_PATH fd272) +elseif( BOARD_N9 IN_LIST DEFINES ) + set(DEVICE_PATH n9) +elseif( BOARD_LEINIAO IN_LIST DEFINES ) + set(DEVICE_PATH fd230) +else() + message(FATAL_ERROR "Unknown device type: please define BOARD_FD230, BOARD_W9, BOARD_FD272, BOARD_N9, or BOARD_LEINIAO") +endif() + set(PRIVATE_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/Service ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/include @@ -17,6 +31,9 @@ ${ROOT_DIR}/open_source/openharmony/third_party/lwip/lwip_adapter/liteos/src/inc # ${ROOT_DIR}/open_source/openharmony/base/iothardware/peripheral/interfaces/inner_api # ${ROOT_DIR}/open_source/openharmony/base/security/huks/frameworks/huks_standard/main/crypto_engine/mbedtls/include # ${ROOT_DIR}/open_source/openharmony/base/security/huks/frameworks/huks_standard/main/common/include +${ROOT_DIR}/zhihui/services/ble_service/blemoder +${ROOT_DIR}/zhihui/services/ble_service/bleservice +${ROOT_DIR}/application/wearable/${DEVICE_PATH}/service/broadcast/include ) # 源文件列表 diff --git a/code/sdk/zhihui/4g/cat1Service/Service/cat1_server.c b/code/sdk/zhihui/4g/cat1Service/Service/cat1_server.c index 532200d9e..25328b69a 100644 --- a/code/sdk/zhihui/4g/cat1Service/Service/cat1_server.c +++ b/code/sdk/zhihui/4g/cat1Service/Service/cat1_server.c @@ -18,6 +18,7 @@ #include // #include #include "lwip/inet.h" +#include "cat1_tcpServer.h" /* Define htons function if not available */ #ifndef htons @@ -104,6 +105,12 @@ enum UDP_COMMAND_HEAD { UDP_MSG_SEND_VOLTE_SWITCH = 0x1A,//VOLTE开关 + UDP_MSG_SEND_OTA= 0x1B,//OTA 升级 + + UDP_MSG_SEND_AI_ID= 0x1C,//ai设备id获取 + + UDP_MSG_TCP_OTA_INIT= 0x1D,//TCP ota升级 + UDP_MSG_WATCH_REPLY_ACK = 0xAC,// // UDP_MSG_WATCH_REPLY_HANGUP = 0x21,// }; @@ -292,7 +299,7 @@ static uint8_t PY_SRV_VER_CURRENT = 0; #define PY_SRV_VER_5 "PY_SRV_V5" #define PY_SRV_VER_6 "PY_SRV_V6" -static uint8_t g_py_ver = 4; +uint8_t g_py_ver = 4; static osTimerId_t g_timer_time_answer = NULL; @@ -1198,6 +1205,13 @@ static void time_sync_func(void) #endif if (cat1_api_need_update_signal()) cat1_getsignal(); + + #ifdef SUPPORT_CHINA_MOBILE_AI_REGULATION + char device_id[128]={0}; + get_cmai_dev_id(device_id); + if(strlen(device_id)<=10) + cat1_get_DEV_ID(); + #endif } void restart_time_sync(void) @@ -1259,6 +1273,20 @@ void send_dtmf_number_toCat1(char ch)//发送dtfm udp_send_msg_toCat1(UDP_MSG_SEND_DTMF_NUMBER,&ch); } +void cat1_get_DEV_ID(void) +{ + cat1_print_dbg("UDP_CMD_get_DEV_ID\n"); + udp_send_msg_toCat1(UDP_MSG_SEND_AI_ID,"0"); +} + +void cat1_start_tcp_ota_init(void) +{ + cat1_print_dbg("UDP_MSG_TCP_OTA_INIT\n"); + udp_send_msg_toCat1(UDP_MSG_TCP_OTA_INIT,"0"); +} + + + /** * @brief 发送指令给Cat1,输入 CMD_4G_T , cmd_buf 为指令所需参数. * @return 成功 ERRCODE_SUCC 或者其他失败ERRCODE . @@ -1510,6 +1538,9 @@ static int udp_packet_parse(char *rx_buffer, int len) index = cat1_handle_sms(msg_buffer); // uapi_save_runtime_log(RUNTIME_LOG_CAT1_UDP_MSG_SMS); break; + case UDP_MSG_SEND_AI_ID: + set_cmai_dev_id(msg_buffer); + break; default: cat1_print_err("error message: %s\n", rx_buffer); index = 1; @@ -1676,10 +1707,22 @@ errcode_t cat1_server_init(void) //第一次启动,要确保去除已经添加过的cat1 Vote restart_sleep_cat1_timer(); #endif + uint8_t need_ota=0; + FILE *fp= fopen(CAT1_PY_IS_NEED_UDP_PATH,"rb+"); + if(fp) + { + fread(&need_ota,sizeof(uint8_t),1,fp); + fclose(fp); + remove(CAT1_PY_IS_NEED_UDP_PATH); + if(need_ota>g_py_ver) + { + cat1_start_tcp_ota_init(); + cat1_tcp_server_init(); + } + + } - cat1_tcp_server_init(); - return ERRCODE_SUCC; } diff --git a/code/sdk/zhihui/4g/cat1Service/Service/cat1_tcpServer.c b/code/sdk/zhihui/4g/cat1Service/Service/cat1_tcpServer.c index f98f6087b..302cbaab4 100644 --- a/code/sdk/zhihui/4g/cat1Service/Service/cat1_tcpServer.c +++ b/code/sdk/zhihui/4g/cat1Service/Service/cat1_tcpServer.c @@ -40,9 +40,13 @@ static inline u16_t htons(u16_t n) #include "cat1_utils.h" #include "cat1_tcpServer.h" #include "cat1_runtime.h" +#include "bleInstruct.h" +#include "broadcast_feature.h" #ifdef __cplusplus + extern "C" { + #endif /* __cplusplus */ @@ -54,14 +58,15 @@ extern "C" { #include "cat1_server_hal.h" #include "cat1_ctl.h" #include "tcxo.h" -#include "cat1_utils.h" - - - +#include "custom_utils.h" #include "cmsis_os.h" +#include "broadcast_feature.h" static uint8_t g_skip_cat1_service_udp_transfer = 0; +uint8_t is_need_udp_updata=0; + + #define PEER_IP "172.16.1.2" #define PEER_PORT 5001 #define SERVER_IP "172.16.1.5" @@ -74,6 +79,15 @@ static uint8_t g_msg_format_type = 0; #else #define CAT1_PY_PATH "/system/cat1ota" //存放需要升级的py文件路径 #endif + + +#ifdef SINGLE_USER_PARTITION +#define CAT1_PY_UDP_PATH "/user/system/cat1otaudp" //存放需要升级的py文件路径 +#else +#define CAT1_PY_UDP_PATH "/system/cat1otaudp" //存放需要升级的py文件路径 +#endif + + #define CAT1_REPLYA_FILE_SIZE_FUN 1 //是否需要CAT1回复文件大小一致传输完单个文件是否与SIZE大小匹配比较 static osTimerId_t file_transfer_timer=NULL; static uint8_t timerOut_count = 0; @@ -116,6 +130,9 @@ struct tcp_msg_old_t { }; #pragma pack(pop) +#include "cmsis_os2.h" +extern osStatus_t osDelay(uint32_t ticks); +#define cat1_msleep(ms) osDelay(ms) /* osDelay(1) : 1ms */ static int g_listen_sock = 0; struct sockaddr_in filesourceAddr = {0}; @@ -164,7 +181,7 @@ static int pack_tlv_format(char *tx_buffer,uint8_t mode,uint8_t cmd, char *conte { int content_length = (int)strlen(content); - if(content_length > MAX_TCP_MSG_BUFFER_LEN || content == NULL) + if(content_length > MAX_TCP_MSG_BUFFER_LEN || content == NULL) { printf("content data error: content_length %d %s\r\n",content_length,content); return -1; @@ -193,7 +210,11 @@ static void udp_send_response(char *tx_buffer,uint8_t mode, uint8_t cmd, char *c // printf("msg_format_type %d \n",g_msg_format_type,len); int err = 0; if( len > 0 ) { + err = sendto(g_listen_sock, tx_buffer, len, 0, (struct sockaddr *)&filesourceAddr, sizeof(filesourceAddr)); + // err=send(g_listen_sock,tx_buffer,len,0); + cat1_msleep(10); + cat1_print_err("udp_send_response\n"); if (err < 0) { cat1_print_err("Error occured during sending: errno %d\n", errno); } @@ -209,6 +230,9 @@ void ble_tcp_send_msg_toCat1(uint8_t mode,uint8_t cmd,char *content) cat1_print_err("Error cat1 poweroff tcp skipp send data\n"); return ; } + printf("ble_tcp_send_msg_toCat1 1\r\n"); + + cat1_api_wakeup_cat1(1); // uart_port_register_irq(UART_BUS_0); osal_irq_enable(UART_1_IRQN); @@ -217,11 +241,15 @@ void ble_tcp_send_msg_toCat1(uint8_t mode,uint8_t cmd,char *content) cat1_print_err(" g_skip_cat1_service_udp_transfer \n"); return ; } - char station_tx_buffer[MAX_TCP_MSG_BUFFER_LEN] = {0}; + char *station_tx_buffer=(char*)malloc(MAX_TCP_MSG_BUFFER_LEN); if( filesourceAddr.sin_port != 0 ) { udp_send_response(station_tx_buffer,mode,cmd, content); + cat1_print_err("ble_tcp_send_msg_toCat1 2\n"); } + free(station_tx_buffer); + + cat1_api_wakeup_cat1(0); } @@ -306,10 +334,12 @@ void cat1_ota_send_data(uint8_t Code,char *fileName,uint32_t fileSize,char *data cJSON_AddNumberToObject(dataJSON,"Code",CAT1_TCP_START_SEND_FILE_DATA); cJSON_AddStringToObject(dataJSON,"data",(char *)data); // FE 头 0012c 文件长度 + data+crc json_format = cJSON_PrintUnformatted(dataJSON); - // printf("start cat1_ota_send_data json_format:%s %d\r\n",data,strlen(data)); + printf("start cat1_ota_send_data json_format:%s %d\r\n",data,strlen(data)); cJSON_Delete(dataJSON); printf("cat1_ota_send_data two:\r\n"); ble_tcp_send_msg_toCat1(FILE_TRANSFER_CMD,0,json_format); + // if(json_format) + printf("free json_format \r\n"); cJSON_free(json_format); break; // case CAT1_TCP_START_OTA_FAILE: //OTA失败 @@ -407,10 +437,12 @@ static void stop_cat1_ota(void){ //停止 CAT1 ota 清标识 } } if(fp != NULL){ //防止打开文件没有关闭 - printf("file is not close!\r\n"); + printf("file is not lwip_close!\r\n"); fclose(fp); fp = NULL; } + + cat1_api_wakeup_cat1(0); } static void cat1_file_Timer_CallBack(int data_tmp) @@ -486,16 +518,16 @@ void read_dir(void){ // 跳过'.'和'..'目录 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { printf("%s\n", entry->d_name); // 输出文件名 - // std::string filename= entry->d_name; - // //0 1 2 - // if(filename=="Cat1pyVersion.txt" - // || filename=="main.py" - // || filename=="main_init.py" - // || filename=="tcpService.py") - // { - // printf("屏蔽升级文件 %s\n",filename.c_str()); - // continue; - // } + // entry->d_name; + //0 1 2 + if(strcmp("Cat1pyVersion.txt",entry->d_name)==0 + || strcmp("main.py",entry->d_name)==0 + || strcmp("main_init.py",entry->d_name)==0 + || strcmp("tcpService.py",entry->d_name)==0 ) + { + printf("屏蔽升级文件 %s\n",entry->d_name); + continue; + } fileNameList[file_count] = (char *)malloc(DEFAULT_MAX_FILE_NAME_SIZE * sizeof(char)); if (fileNameList[file_count] == NULL) { @@ -530,6 +562,56 @@ void read_dir(void){ } } +void read_UDP_dir(void){ + + for (int i = 0; i < DEFAULT_MAX_FILE_COUNT; i++) { //释放内存 + if(fileNameList[i] != NULL){ + free(fileNameList[i]); + fileNameList[i] = NULL; + } + } + + file_count = 0; + + printf("fileNameList[file_count]\r\n"); + + for(int i=0;i<5;i++) + { + fileNameList[file_count] = (char *)malloc(DEFAULT_MAX_FILE_NAME_SIZE * sizeof(char)); + + if(i==0) + snprintf(fileNameList[file_count],DEFAULT_MAX_FILE_NAME_SIZE,"%s","telecom_dmp.py"); + else if (i==1) + snprintf(fileNameList[file_count],DEFAULT_MAX_FILE_NAME_SIZE,"%s","china_mobile_dmp.py"); + else if (i==2) + snprintf(fileNameList[file_count],DEFAULT_MAX_FILE_NAME_SIZE,"%s","cat1Service.py"); + else if (i==3) + snprintf(fileNameList[file_count],DEFAULT_MAX_FILE_NAME_SIZE,"%s","tcpserver.py"); + else + snprintf(fileNameList[file_count],DEFAULT_MAX_FILE_NAME_SIZE,"%s","main.py"); + + printf("fileNameList[file_count] %s\r\n",fileNameList[file_count]); + file_count+=1; + } + + send_dir_info(); + noreplayCount = 0; + uint32_t tick; + osStatus_t retTimer; + if(file_transfer_timer == NULL){ + file_transfer_timer = osTimerNew((osTimerFunc_t)cat1_file_Timer_CallBack, osTimerPeriodic, NULL, NULL); + tick = 1000;// osMs2Tick(1000); + retTimer = osTimerStart(file_transfer_timer, tick); + if (retTimer != osOK && file_transfer_timer != NULL) { + cat1_print_err("StartCallTimer osTimerStart failed, ret = %lx!!", retTimer); + osTimerDelete(file_transfer_timer); + file_transfer_timer = NULL; + } + } + +} + + void send_curfile_info_data(void) { cat1_ota_flag = CAT1_TCP_START_SEND_SINGLE_FILE_INFO; @@ -539,6 +621,9 @@ void send_curfile_info_data(void) if(strlen(fileNameList[curfilecount]) != 0 && filesize != 0){ char file_path[DEFAULT_MAX_FILE_NAME_SIZE]={0}; memset(file_path,0,DEFAULT_MAX_FILE_NAME_SIZE); + if(is_need_udp_updata) + sprintf_s(file_path,DEFAULT_MAX_FILE_NAME_SIZE,"%s/%s",CAT1_PY_UDP_PATH,fileNameList[curfilecount]); + else sprintf_s(file_path,DEFAULT_MAX_FILE_NAME_SIZE,"%s/%s",CAT1_PY_PATH,fileNameList[curfilecount]); if(fp != NULL){ fclose(fp); @@ -587,6 +672,10 @@ void read_file_info_data(void){ struct dirent *entry; char file_path[DEFAULT_MAX_FILE_NAME_SIZE]={0}; memset(file_path,0,DEFAULT_MAX_FILE_NAME_SIZE); + + if(is_need_udp_updata) + sprintf_s(file_path,DEFAULT_MAX_FILE_NAME_SIZE,"%s/%s",CAT1_PY_UDP_PATH,fileNameList[curfilecount]); + else sprintf_s(file_path,DEFAULT_MAX_FILE_NAME_SIZE,"%s/%s",CAT1_PY_PATH,fileNameList[curfilecount]); count+=1; @@ -682,6 +771,10 @@ void send_data_case(uint8_t mode){ switch (mode) { case READ_DIR_INFO: //读文件目录信息 + printf("READ_DIR_INFO\r\n"); + if(is_need_udp_updata) + read_UDP_dir(); + else read_dir(); break; case READ_FILE_DATA_INFO://收到CAT1回复开始发送文件信息 @@ -706,6 +799,12 @@ void send_data_case(uint8_t mode){ void start_cat1_ota(void){ stop_cat1_ota(); send_data_case(READ_DIR_INFO); //开始OTA 就开始升级py文件 + + uint8_t TRANSMIT_DATA=START_CAT1_OTA; + + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); + + cat1_api_wakeup_cat1(1); } void Cat1_OTA(uint8_t ota_state) { @@ -866,6 +965,9 @@ static int udp_packet_parse(char *rx_buffer, int len) { return 0; } + uint8_t shutdowflag = 1;//重启 + uint8_t TRANSMIT_DATA=OTA_UPDATA_FAIL; + switch (cmd) { case CAT1_REPLAY_CREAT_DIR_FAILE: //cat1:创建临时文件夹失败 @@ -875,6 +977,7 @@ static int udp_packet_parse(char *rx_buffer, int len) creat_file_err+=1; if(creat_file_err >= FAILE_COUNT){ //创建十次都出错不创建结束当前的升级 creat_file_err=0; + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); stop_cat1_ota(); break; } @@ -904,6 +1007,7 @@ static int udp_packet_parse(char *rx_buffer, int len) if(write_data_err >= FAILE_COUNT){ write_data_err = 0; stop_cat1_ota(); + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); break; } printf("CAT1_REPLAY_WRITE_FILE_ERROR! %d",cmd); @@ -916,6 +1020,8 @@ static int udp_packet_parse(char *rx_buffer, int len) data_crc_err+=1; if(data_crc_err >= FAILE_COUNT){ //连续十次CRC都出错就结束进程 data_crc_err = 0; + uint8_t TRANSMIT_DATA=OTA_UPDATA_FAIL; + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); stop_cat1_ota(); break; } @@ -937,16 +1043,22 @@ static int udp_packet_parse(char *rx_buffer, int len) if(creat_file_err >= FAILE_COUNT){ creat_file_err = 0; stop_cat1_ota(); + uint8_t TRANSMIT_DATA=OTA_UPDATA_FAIL; + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); break; } send_data_case(CREAT_FILE_FAILE); break; case CAT1_REPLAY_OTA_SUCC: //ota 成功失败与否 收到CAT1的回复就停止计时器 stop_cat1_ota(); + //成功直接重启 + CustomEventPublish(TOPIC_EVENT_SHUTDOWN_ANIMATIOR, &shutdowflag, sizeof(shutdowflag)); //添加GUI break; case CAT1_REPLAY_OTA_FALIE: + stop_cat1_ota(); + break; case CAT1_REPLAY_FILE_SIZE_OK: //文件大小发送和接收的一致 read_file_info_data(); @@ -956,6 +1068,7 @@ static int udp_packet_parse(char *rx_buffer, int len) if(file_size_err >= FAILE_COUNT){ file_size_err = 0; stop_cat1_ota(); + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); break; } send_curfile_info_data(); @@ -1006,9 +1119,67 @@ static int udp_socket_file_init() return listen_sock; } -#include "cmsis_os2.h" -extern osStatus_t osDelay(uint32_t ticks); -#define cat1_msleep(ms) osDelay(ms) /* osDelay(1) : 1ms */ + +static int tcp_socket_file_init() +{ + int addr_family; + int ip_protocol; + int opt = 1; + struct sockaddr_in destAddr; + char addr_str[128]; + + // destAddr.sin_addr.s_addr = htonl(INADDR_ANY); + destAddr.sin_addr.s_addr = inet_addr(SERVER_IP); + destAddr.sin_family = AF_INET; + destAddr.sin_port = htons(PORT); + addr_family = AF_INET; + ip_protocol = IPPROTO_IP; + inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); + + int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (listen_sock < 0) { + cat1_print_err("Unable to create socket: errno %d\n", errno); + return -1; + } + // setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + // setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + filesourceAddr.sin_addr.s_addr = inet_addr(PEER_IP); + filesourceAddr.sin_family = AF_INET; + filesourceAddr.sin_port = htons(PEER_PORT); + + return listen_sock; +} + + +void re_connect(void) +{ + // socklen_t addrLen = sizeof(filesourceAddr); + // lwip_close(g_listen_sock); + // // while (1) + // { + // int connret=connect(g_listen_sock, (struct sockaddr *)&filesourceAddr,addrLen); + // cat1_print_err("Unable to connect: errno %d\n", errno); + // if(connret=0) + // { + // cat1_print_err("connect succ\n"); + // // break; + // } + // else + // { + // cat1_msleep(1000); + // cat1_print_err("connecting...\n"); + // } + // } + remove(CAT1_PY_IS_NEED_UDP_PATH); + cat1_print_err("CAT1_PY_IS_NEED_UDP_PATH\n"); +} + +uint8_t errno_count=0; +static uint8_t IS_need_ota=1; +extern uint8_t g_py_ver; + + void cat1_server_file_task(void *pvParameters) { char rx_buffer[512]; @@ -1016,13 +1187,85 @@ void cat1_server_file_task(void *pvParameters) int index; socklen_t addrLen = sizeof(filesourceAddr); while (1) { - if( g_listen_sock > 0 ) close(g_listen_sock); - g_listen_sock = udp_socket_file_init(); - if( g_listen_sock < 0 ) { - cat1_print_err("socket init fail and retry\n"); - // vTaskDelay(1000/portTICK_RATE_MS); + if(errno_count>10) + { + //如果失败太多次将退出循环,避免浪费系统资源 + // return; + cat1_print_err("errno count %d\n",errno_count); + } + if( g_listen_sock > 0 ) + { + cat1_print_err("lwip_close(g_listen_sock)\n"); + lwip_close(g_listen_sock); + } + + if(is_need_udp_updata==0) + { + g_listen_sock = tcp_socket_file_init(); + if( g_listen_sock < 0 ) { + cat1_print_err("socket init fail and retry\n"); + // vTaskDelay(1000/portTICK_RATE_MS); + errno_count++; + cat1_msleep(1000); + continue; + } cat1_msleep(1000); - continue; + int connret=connect(g_listen_sock, (struct sockaddr *)&filesourceAddr,addrLen); + if(connret>=0) + { + cat1_print_err("connect succ\n"); + } + else + { + cat1_msleep(1000); + cat1_print_err("Unable to connect: errno %d\n", errno); + cat1_print_err("connecting...\n"); + errno_count++; + continue; + } + } + else + { + g_listen_sock = udp_socket_file_init(); + if( g_listen_sock < 0 ) { + cat1_print_err("socket init fail and retry\n"); + // vTaskDelay(1000/portTICK_RATE_MS); + cat1_msleep(1000); + errno_count++; + continue; + } + } + + errno_count=0; + + if(IS_need_ota) + { + IS_need_ota=0; + if(g_py_ver==16) + { + uint8_t TRANSMIT_DATA=IS_NEED_CAT1_OTA; + + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); + } + else if(g_py_ver==17) + { + Cat1_OTA(CAT1_TCP_START_OTA); + } + else if(g_py_ver==18) + { + uint8_t TRANSMIT_DATA=IS_NEED_CAT1_OTA; + + CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,&TRANSMIT_DATA,1); + } + else if (g_py_ver>=19 && (uapi_dev_runtime_get_cat1_networkstat()) ) + { + char * cat1_modemver = uapi_dev_runtime_get_cat1_modemver(); + + // star_http_ota_updata(cat1_modemver ,g_py_ver); + + + } + } while (1) { @@ -1066,6 +1309,8 @@ void cat1_server_file_task(void *pvParameters) #define CAT1_SERVICE_TASK_SIZE (0x800*5) #define CAT1_SERVICE_TASK_PRIO 5 + + errcode_t cat1_tcp_server_init(void) { cat1_print_info("cat1_tcp_server_init !\r\n"); @@ -1076,8 +1321,14 @@ errcode_t cat1_tcp_server_init(void) taskcfg.attr.stack_size = CAT1_SERVICE_TASK_SIZE; taskcfg.func = cat1_server_file_task; taskcfg.use_mem = USE_EXTEND_MEM; - - errcode_t ret=cat1_create_osThread_custom(&taskcfg); + + if(g_py_ver<=16) + { + is_need_udp_updata=1; + } + errcode_t ret=uapi_create_osThread_custom(&taskcfg); + + if(ret != ERRCODE_SUCC) { cat1_print_err("create cat1_service_file failed %d!\r\n",ret); @@ -1086,6 +1337,31 @@ errcode_t cat1_tcp_server_init(void) return ERRCODE_SUCC; } +char* xor_encrypt_decrypt(const char* message, const char* key) { + if (message == NULL || key == NULL) { + return NULL; + } + + size_t message_len = strlen(message); + size_t key_len = strlen(key); + + // 分配内存用于存储结果 + char* result = (char*)malloc(message_len + 1); + if (result == NULL) { + return NULL; // 内存分配失败 + } + + // 执行 XOR 操作 + for (size_t i = 0; i < message_len; ++i) { + result[i] = message[i] ^ key[i % key_len]; + } + result[message_len] = '\0'; // 确保字符串以 null 结尾 + + return result; +} + + + #ifdef __cplusplus } diff --git a/code/sdk/zhihui/4g/cat1Service/include/cat1_server.h b/code/sdk/zhihui/4g/cat1Service/include/cat1_server.h index 80e90942d..f3df815be 100644 --- a/code/sdk/zhihui/4g/cat1Service/include/cat1_server.h +++ b/code/sdk/zhihui/4g/cat1Service/include/cat1_server.h @@ -45,6 +45,7 @@ uint8_t get_call_hungup_flag(void); uint8_t set_call_hungup_flag(uint8_t data); void cat1_call_hungup_timer(void); +void cat1_start_tcp_ota_init(void); #ifdef __cplusplus } diff --git a/code/sdk/zhihui/4g/cat1Service/include/cat1_tcpServer.h b/code/sdk/zhihui/4g/cat1Service/include/cat1_tcpServer.h index 032268f0e..ef0e7e9fa 100644 --- a/code/sdk/zhihui/4g/cat1Service/include/cat1_tcpServer.h +++ b/code/sdk/zhihui/4g/cat1Service/include/cat1_tcpServer.h @@ -77,6 +77,14 @@ void cat1_ota_send_data(uint8_t Code,char *fileName,uint32_t fileSize,char *data void Cat1_OTA(uint8_t ota_state); //获取CAT1 OTA升级状态 返回 CAT1_TCP_STOP_OTA 不在升级状态 其他在升级状态中 uint8_t Get_Cat1_OTA_Flag(void); + +#ifdef SINGLE_USER_PARTITION +#define CAT1_PY_IS_NEED_UDP_PATH "/user/system/cat1otaudp/is_need_updata.txt" //存放需要升级的py文件路径 +#else +#define CAT1_PY_IS_NEED_UDP_PATH "/system/cat1otaudp/is_need_updata.txt" //存放需要升级的py文件路径 +#endif + + #ifdef __cplusplus #if __cplusplus } diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index 4b8dff687..242f0af52 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -381,6 +381,7 @@ typedef enum { WS_CMD_AUDIO_PLAYBACK_START, /* 音频播放开始 */ WS_CMD_AUDIO_PLAYBACK_END, /* 音频播放结束 */ WS_CMD_AUDIO_RECORDING_START, /* 开始录音上传 */ + WS_CMD_AUDIO_RECORDING_END, /* 结束录音上传 */ WS_CMD_SENTENCE_PLAYBACK_COMPLETE, /* 单句语音播放完成 */ WS_CMD_MAX /* 最大命令 */ } ws_command_t; diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c index bd1dfb94f..6e84e582a 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c @@ -152,6 +152,9 @@ static audio_chat_context_t g_audio_chat_ctx = {0}; // 音频聊天结束标志 static bool g_audio_chat_ending = false; +// 录音上传状态跟踪 +static bool g_recording_upload_started = false; + // 音频数据缓存结构 typedef struct { uint8_t *data; // 音频数据 @@ -176,6 +179,11 @@ static uint32_t g_audio_timeout_ticks = 1500; // 音频超时tick数(默认1.5 static uint32_t g_last_binary_data_tick = 0; // 最后一次接收二进制数据的tick static uint32_t g_audio_playback_start_tick = 0; // 音频播放开始时间tick +// VAD冷却时间相关变量 +static uint32_t g_vad_cooldown_start_tick = 0; // VAD冷却开始时间tick +static bool g_vad_cooldown_active = false; // VAD冷却是否激活 +static uint32_t g_vad_cooldown_duration_ms = 3000; // VAD冷却持续时间(毫秒) + // 音频时长记录循环数组 #define AUDIO_DURATION_BUFFER_SIZE 50 @@ -197,6 +205,8 @@ static void set_chat_id_matched(void); static bool is_chat_id_matched(void); static bool is_active_chat_response(const char *chat_id, const char *response_id); static void ln_ws_audio_write_callback(uint32_t size); +static bool ln_ws_is_vad_cooldown_active(void); +static void ln_ws_start_vad_cooldown(void); @@ -667,6 +677,9 @@ int ln_ws_start_audio_chat(ln_audio_chat_command_t command_type) // 重置对话ID匹配标志 reset_chat_id_match(); + // 重置录音上传状态 + g_recording_upload_started = false; + const char *command_name = (command_type == LN_AUDIO_CHAT_VOICE_CHAT_REQUEST) ? "VoiceChatRequest" : "ChooseStoryRequest"; @@ -690,6 +703,12 @@ int ln_ws_end_audio_chat(void) } LN_WS_DEBUG("Ending audio chat: %s, total messages: %u\n", g_audio_chat_ctx.chat_id, g_audio_chat_ctx.message_counter); + + // 安全检查:如果录音上传状态异常,记录警告 + if (!g_recording_upload_started) { + LN_WS_WARN("Recording upload was not started, but ending audio chat\n"); + } + // 设置结束标志,等待下次AIVoiceDataCallback_ln调用时发送结束消息 g_audio_chat_ending = true; @@ -706,6 +725,12 @@ static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* use { (void)userData; + // 状态一致性检查:如果音频聊天未激活但录音上传状态为true,重置状态 + if (!g_audio_chat_ctx.is_active && g_recording_upload_started) { + LN_WS_WARN("Audio chat not active but recording upload started, resetting state\n"); + g_recording_upload_started = false; + } + // MEDIA_INFO_LOG("Received audio data: size=%u bytes", size); // ========== VAD 处理已移到 ln_ws_send_audio_data (录音接口层) ========== @@ -719,8 +744,8 @@ static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* use if (ret != ERRCODE_SUCC) { /* 静默失败,避免过多日志 */ } else { - LN_WS_DEBUG("VAD: Sent %u bytes (format=%d, is_last=%d)\n", - size, format, false); + // LN_WS_DEBUG("VAD: Sent %u bytes (format=%d, is_last=%d)\n", + // size, format, false); } } @@ -729,6 +754,10 @@ static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* use LN_WS_INFO("VAD: Audio recording ended\n"); } } + else + { + LN_WS_INFO("VAD: Audio g_vad_server_enabled g_vad_server_initialized vad_server_is_running\n"); + } #endif @@ -737,18 +766,45 @@ static void AIVoiceDataCallback_ln(const uint8_t* data, uint32_t size, void* use { if (g_audio_chat_ending) { LN_WS_DEBUG("Sending audio chat end message\n"); + + // 触发结束录音上传事件 + // 增加多重判断确保不会重复触发: + // 1. 录音上传状态已开始 + // 2. 音频聊天上下文激活 + // 3. 回调函数已注册 + if (g_recording_upload_started && g_ws_message_callback != NULL) { + LN_WS_INFO("Triggering WS_CMD_AUDIO_RECORDING_END event\n"); + g_ws_message_callback(NULL, WS_CMD_AUDIO_RECORDING_END); + g_recording_upload_started = false; + } + // 发送结束消息 ln_ws_send_audio_data(data, size, true); + // AI_SendAudioDataToQueue(data, size); // 重置聊天上下文和结束标志 g_audio_chat_ctx.is_active = false; g_audio_chat_ending = false; } else { + // 触发开始录音上传事件(仅在第一次发送时触发) + // 增加多重判断确保不会重复触发: + // 1. 录音上传状态未开始 + // 2. 音频聊天上下文激活 + // 3. 有有效的音频数据 + // 4. 回调函数已注册 + if (!g_recording_upload_started && g_ws_message_callback != NULL) { + LN_WS_INFO("Triggering WS_CMD_AUDIO_RECORDING_START event\n"); + g_ws_message_callback(NULL, WS_CMD_AUDIO_RECORDING_START); + g_recording_upload_started = true; + } + // 使用新的音频发送接口 ln_ws_send_audio_data(data, size, false); + // AI_SendAudioDataToQueue(data, size); } } + LOS_Msleep(10); } // "audioBase64": @@ -972,6 +1028,38 @@ int ln_ws_start(ws_message_callback_t_ln callback, uint32_t audio_timeout_ticks) return 0; } +void vad_status_callback_ln_ws(int status) +{ + LN_WS_INFO("Audio vad_status_callback_ln_ws %d\n",status); + if(g_audio_playback_active) + { + // ln_ws_start_vad_cooldown(); + LN_WS_INFO("g_audio_playback_active %d\n",g_audio_playback_active); + return; + } + + // if(status==1) + // { + // // 检查是否在VAD冷却时间内 + // if(ln_ws_is_vad_cooldown_active()) + // { + // LN_WS_INFO("VAD cooldown active, ignoring start request\n"); + // return; + // } + + // ln_ws_start_audio_chat(LN_AUDIO_CHAT_VOICE_CHAT_REQUEST); + // } + // else + if (status==2) + { + ln_ws_end_audio_chat(); + // 开始VAD冷却计时 + ln_ws_start_vad_cooldown(); + } + + +} + void ln_ws_audio_init(void) { // 检查是否已经初始化 @@ -1007,9 +1095,11 @@ void ln_ws_audio_init(void) #if ENABLE_VAD_SERVER // 如果 VAD 服务器已启用,则初始化 VAD 服务器 + ln_ws_enable_vad_server(); + if (g_vad_server_enabled && !g_vad_server_initialized) { LN_WS_INFO("Initializing VAD server...\n"); - errcode_t ret = vad_server_init(NULL); // 使用 NULL 回调,也可以传入自定义回调 + errcode_t ret = vad_server_init(vad_status_callback_ln_ws); // 使用 NULL 回调,也可以传入自定义回调 if (ret == ERRCODE_SUCC) { g_vad_server_initialized = true; LN_WS_INFO("VAD server initialized successfully\n"); @@ -1081,7 +1171,7 @@ int ln_ws_enable_vad_server(void) // 如果音频已经初始化,立即初始化 VAD 服务器 if (g_audio_initialized && !g_vad_server_initialized) { - errcode_t ret = vad_server_init(NULL); + errcode_t ret = vad_server_init(vad_status_callback_ln_ws); if (ret == ERRCODE_SUCC) { g_vad_server_initialized = true; LN_WS_INFO("VAD server initialized successfully\n"); @@ -2852,3 +2942,35 @@ static bool check_playback_completion_by_timeout(void) return false; // 播放未完成 } + +// ===== VAD冷却时间管理函数 ===== + +// 检查VAD冷却时间是否激活 +static bool ln_ws_is_vad_cooldown_active(void) +{ + if (!g_vad_cooldown_active) { + return false; + } + + uint32_t current_tick = osKernelGetTickCount(); + uint32_t elapsed_ms = current_tick - g_vad_cooldown_start_tick; + + // 如果冷却时间已过,重置冷却状态 + if (elapsed_ms >= g_vad_cooldown_duration_ms) { + g_vad_cooldown_active = false; + LN_WS_INFO("VAD cooldown period ended, elapsed: %u ms\n", elapsed_ms); + return false; + } + + LN_WS_DEBUG("VAD cooldown active, remaining: %u ms\n", + g_vad_cooldown_duration_ms - elapsed_ms); + return true; +} + +// 开始VAD冷却计时 +static void ln_ws_start_vad_cooldown(void) +{ + g_vad_cooldown_start_tick = osKernelGetTickCount(); + g_vad_cooldown_active = true; + LN_WS_INFO("VAD cooldown started, duration: %u ms\n", g_vad_cooldown_duration_ms); +}