From f9d0439a4d5ec2ddaa43d6b06bfe93336f512d9f Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=83=A1=E4=BC=A0=E5=86=9B?= <1224667075@qq.com> Date: Sat, 20 Sep 2025 12:42:39 +0000 Subject: [PATCH] Merge #2332 into sdk650pathc0423 from refs/changes/2332/head MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Code review from 胡传军 * refs/changes/2332/head: (3 commits squashed) - 修改ws 的stop调用 - 增加ln ws休眠接口 - Merge branch 'sdk650pathc0423' of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423 Signed-off-by: aliyun8003852482 <1224667075@qq.com> Merged-by: 罗正 <1732036298@qq.com> CR-link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2332 --- .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 66 +++++- code/sdk/zhihui/leiniao/imsl_ln/ln_api.h | 9 + .../zhihui/leiniao/imsl_ln/ln_api_websocket.c | 194 +++++++++++++++++- 3 files changed, 259 insertions(+), 10 deletions(-) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index aaed755b6..bff370a6d 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -650,7 +650,7 @@ static uint32_t ln_ws_stop_at(uint8_t *para, uint32_t paraLen, char *strCommonCm { VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd); printf("[LN][WS_STOP]\n"); - int ret = ln_ws_stop(); + int ret = ln_ws_stop_async(); if (ret != 0) { printf("[LN][WS_STOP] failed: %d\n", ret); @@ -681,6 +681,66 @@ static uint32_t ln_ws_send_text_at(uint8_t *para, uint32_t paraLen, char *strCom printf("[LN][WS_SEND] ok: %s\n", text); return ERRCODE_SUCC; } + +/* AT^LN_WS_FORCE_RECONNECT */ +static uint32_t ln_ws_force_reconnect_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); + VAD_UNUSED(paraLen); + VAD_UNUSED(strCommonCmd); + printf("[LN][WS_FORCE_RECONNECT]\n"); + int ret = ln_ws_force_reconnect(); + if (ret != 0) + { + printf("[LN][WS_FORCE_RECONNECT] failed: %d\n", ret); + return ERRCODE_FAIL; + } + return ERRCODE_SUCC; +} + +/* AT^LN_WS_CLOSE_STATUS */ +static uint32_t ln_ws_close_status_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); + VAD_UNUSED(paraLen); + VAD_UNUSED(strCommonCmd); + printf("[LN][WS_CLOSE_STATUS]\n"); + ln_ws_print_status_info(); + return ERRCODE_SUCC; +} + +/* AT^LN_WS_SLEEP */ +static uint32_t ln_ws_sleep_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); + VAD_UNUSED(paraLen); + VAD_UNUSED(strCommonCmd); + printf("[LN][WS_SLEEP]\n"); + int ret = ln_ws_enter_sleep(); + if (ret != 0) + { + printf("[LN][WS_SLEEP] failed: %d\n", ret); + return ERRCODE_FAIL; + } + return ERRCODE_SUCC; +} + +/* AT^LN_WS_WAKEUP */ +static uint32_t ln_ws_wakeup_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); + VAD_UNUSED(paraLen); + VAD_UNUSED(strCommonCmd); + printf("[LN][WS_WAKEUP]\n"); + int ret = ln_ws_exit_sleep(); + if (ret != 0) + { + printf("[LN][WS_WAKEUP] failed: %d\n", ret); + return ERRCODE_FAIL; + } + return ERRCODE_SUCC; +} + /* 音频播放: AT^LN_STORY_PLAY_NEXT */ static uint32_t ln_audio_play_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) { @@ -868,6 +928,10 @@ static const at_cmd_table_t g_ln_api_cmd[] = { {(char *)"AT^LN_WS_START", ln_ws_start_at, (char *)"启动WebSocket连接: AT^LN_WS_START"}, {(char *)"AT^LN_WS_STOP", ln_ws_stop_at, (char *)"停止WebSocket连接: AT^LN_WS_STOP"}, {(char *)"AT^LN_WS_SEND", ln_ws_send_text_at, (char *)"发送WS文本: AT^LN_WS_SEND=hello"}, + {(char *)"AT^LN_WS_FORCE_RECONNECT", ln_ws_force_reconnect_at, (char *)"强制重连WebSocket: AT^LN_WS_FORCE_RECONNECT"}, + {(char *)"AT^LN_WS_SLEEP", ln_ws_sleep_at, (char *)"进入休眠状态: AT^LN_WS_SLEEP"}, + {(char *)"AT^LN_WS_WAKEUP", ln_ws_wakeup_at, (char *)"退出休眠状态: AT^LN_WS_WAKEUP"}, + {(char *)"AT^LN_WS_CLOSE_STATUS", ln_ws_close_status_at, (char *)"查询WebSocket关闭状态: AT^LN_WS_CLOSE_STATUS"}, /* 音频播放 */ {(char *)"AT^LN_STORY_PLAY_AT", ln_audio_play_at, (char *)"播放音频: AT^LN_STORY_PLAY_AT"}, diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index f76634bba..990ffd7bd 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -360,6 +360,15 @@ int ln_ws_start(ws_message_callback_t callback); int ln_ws_send_text(const char *text); int ln_ws_stop(void); int ln_ws_stop_async(void); +int ln_ws_force_reconnect(void); +int ln_ws_enter_sleep(void); +int ln_ws_exit_sleep(void); + +/* WebSocket状态查询接口 */ +int ln_ws_get_connection_state(void); +const char* ln_ws_get_connection_state_string(void); +int ln_ws_get_close_status_public(void); +void ln_ws_print_status_info(void); /* 回调函数注册接口 */ void ln_ws_register_message_callback(ws_message_callback_t callback); 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 555a11158..86251d1df 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c @@ -25,6 +25,14 @@ #define WS_STATE_DISCONNECTED 0 // 未连接 #define WS_STATE_CONNECTING 1 // 连接中 #define WS_STATE_CONNECTED 2 // 连接成功 +#define WS_STATE_SLEEP 3 // 休眠状态 + +/* WebSocket关闭状态枚举 */ +typedef enum { + WS_CLOSE_NOT_EXECUTED = 0, // 未执行 + WS_CLOSE_STARTING = 1, // 开始执行 + WS_CLOSE_SUCCESS = 2 // 执行成功 +} ws_close_status_t; /* WebSocket命令枚举 */ @@ -44,6 +52,7 @@ static volatile int g_ws_running = 0; static volatile unsigned int g_ws_reconnect_count = 0; /* 断线后递增,用于URL reconnect参数 */ static osMessageQueueId_t g_ws_msg_queue = NULL; static ws_message_callback_t g_ws_message_callback = NULL; /* 消息处理回调函数 */ +static volatile ws_close_status_t g_ws_close_status = WS_CLOSE_NOT_EXECUTED; /* WebSocket关闭状态标志位 */ static void ln_ws_build_url(char *out, size_t out_size); int ln_ws_send_ping(void); @@ -53,7 +62,10 @@ static int ln_ws_queue_data_message(const ws_data_msg_t *data_msg); static void ln_ws_free_data_message(ws_data_msg_t *data_msg); static void ln_ws_default_message_handler(const ws_data_msg_t *data_msg, ws_command_t type); static void ln_ws_process_message_with_callback(const ws_data_msg_t *data_msg); - +static int ln_ws_close_with_status(int client_fd); +static ws_close_status_t ln_ws_get_close_status(void); +static void ln_ws_reset_close_status(void); +const char* ln_ws_get_connection_state_string(void); /* 队列创建函数 */ void ln_ws_queue_init(void) { @@ -72,7 +84,8 @@ static void ln_ws_on_open(int client) (void)client; printf("WebSocketClientConstructor ln_ws_on_open\r\n"); g_ws_connected = WS_STATE_CONNECTED; - printf("[LN][WS] 连接状态: 连接成功\n"); + ln_ws_reset_close_status(); // 连接成功时重置关闭状态 + printf("[LN][WS] 连接状态: 连接成功, 关闭状态已重置为 NOT_EXECUTED (%d)\n", g_ws_close_status); } /* @@ -124,12 +137,17 @@ static void ln_ws_on_error(int client, struct WebSocketErrorResult error) static void ln_ws_on_close(int client) { (void)client; - printf("WebSocketClientConstructor [LN][WS] ln_ws_on_close"); + printf("WebSocketClientConstructor [LN][WS] ln_ws_on_close %d\r\n",client); + + // 在断开回调触发时,将关闭状态设置为成功 + g_ws_close_status = WS_CLOSE_SUCCESS; + printf("[LN][WS] WebSocket close callback triggered, status set to SUCCESS (%d)\n", g_ws_close_status); + g_ws_connected = WS_STATE_DISCONNECTED; printf("[LN][WS] 连接状态: 未连接\n"); if(g_ws_client_fd>=0) { - WebSocketClientClose(g_ws_client_fd); + // 这里不再调用 ln_ws_close_with_status,因为回调已经触发说明关闭成功 g_ws_client_fd=-1; } @@ -171,8 +189,9 @@ static void ln_ws_main_thread(void *arg) case WS_MSG_TYPE_FORCE_RECONNECT: printf("[LN][WS] Force reconnect requested\n"); if (g_ws_client_fd >= 0) { - WebSocketClientClose(g_ws_client_fd); - g_ws_client_fd = -1; + printf("[LN][WS] WebSocketClientClose\n"); + ln_ws_close_with_status(g_ws_client_fd); + printf("[LN][WS] WebSocketClientClose end\n"); } g_ws_connected = WS_STATE_DISCONNECTED; printf("[LN][WS] 连接状态: 未连接(强制重连)\n"); @@ -209,6 +228,13 @@ static void ln_ws_main_thread(void *arg) } // 连接管理部分 + if (g_ws_connected == WS_STATE_SLEEP) { + // 休眠状态:暂停所有操作,只打印状态信息 + printf("[LN][WS] Sleep mode: pausing all operations\n"); + usleep(1000 * 1000); // 休眠1秒 + continue; + } + if (g_ws_connected == WS_STATE_DISCONNECTED) { if (g_ws_client_fd < 0) { printf("[LN][WS] 开始创建WebSocket客户端...\n"); @@ -244,7 +270,7 @@ static void ln_ws_main_thread(void *arg) printf("[LN][WS] connect failed: %d\n", ret); g_ws_connected = WS_STATE_DISCONNECTED; printf("[LN][WS] 连接状态: 未连接(连接失败)\n"); - (void)WebSocketClientClose(g_ws_client_fd); + (void)ln_ws_close_with_status(g_ws_client_fd); g_ws_client_fd = -1; /* 指数退避*/ unsigned int delay = 1u << (g_ws_reconnect_count > 5 ? 5 : g_ws_reconnect_count); @@ -270,10 +296,35 @@ static void ln_ws_main_thread(void *arg) heartbeat_counter = 0; // 重置计数器 } } + else + { + printf("ln ws_state %s\r\n",ln_ws_get_connection_state_string()); + } /* 1秒间隔 */ usleep(1000 * 1000); } + + + if (g_ws_client_fd >= 0) { + ln_ws_close_with_status(g_ws_client_fd); + } + g_ws_connected = WS_STATE_DISCONNECTED; + + // 删除消息队列 + if (g_ws_msg_queue != NULL) { + + ws_msg_info_t msg; + while (osMessageQueueGet(g_ws_msg_queue, &msg, NULL, 0) == osOK) { + if(msg.data.raw_json) + { + free(msg.data.raw_json); + } + + } + osMessageQueueDelete(g_ws_msg_queue); + g_ws_msg_queue = NULL; + } } /* @@ -411,7 +462,7 @@ int ln_ws_force_reconnect(void) ws_msg_info_t msg; msg.msg_type = WS_MSG_TYPE_FORCE_RECONNECT; msg.data_len = 0; - // msg.data = NULL; + msg.data.raw_json = NULL; osStatus_t ret = osMessageQueuePut(g_ws_msg_queue, &msg, 0, 0); return (ret == osOK) ? 0 : -1; @@ -425,6 +476,7 @@ int ln_ws_stop_async(void) ws_msg_info_t msg; msg.msg_type = WS_MSG_TYPE_STOP; msg.data_len = 0; + msg.data.raw_json = NULL; // msg.data = NULL; osStatus_t ret = osMessageQueuePut(g_ws_msg_queue, &msg, 0, 0); @@ -441,7 +493,7 @@ int ln_ws_stop(void) } int ret = 0; if (g_ws_client_fd >= 0) { - ret = WebSocketClientClose(g_ws_client_fd); + ret = ln_ws_close_with_status(g_ws_client_fd); g_ws_client_fd = -1; } g_ws_connected = WS_STATE_DISCONNECTED; @@ -471,6 +523,8 @@ const char* ln_ws_get_connection_state_string(void) return "连接中"; case WS_STATE_CONNECTED: return "连接成功"; + case WS_STATE_SLEEP: + return "休眠状态"; default: return "未知状态"; } @@ -723,4 +777,126 @@ static void ln_ws_process_message_with_callback(const ws_data_msg_t *data_msg) } } +/* ============================ WebSocket关闭状态管理 ============================ */ + +/** + * @brief 带状态跟踪的WebSocket关闭函数 + * @param client_fd WebSocket客户端文件描述符 + * @return WebSocketClientClose的返回值 + */ +static int ln_ws_close_with_status(int client_fd) +{ + if (client_fd < 0) { + printf("[LN][WS] Invalid client_fd for close operation\n"); + return -1; + } + + // 设置状态为开始执行 + g_ws_close_status = WS_CLOSE_STARTING; + printf("[LN][WS] WebSocketClientClose starting, fd=%d, status=%d\n", client_fd, g_ws_close_status); + + // 执行关闭操作 + int ret = WebSocketClientClose(client_fd); + + // 注意:成功状态由 ln_ws_on_close 回调函数设置,这里只处理失败情况 + if (ret != 0) { + g_ws_close_status = WS_CLOSE_NOT_EXECUTED; + printf("[LN][WS] WebSocketClientClose failed, fd=%d, ret=%d, status=%d\n", client_fd, ret, g_ws_close_status); + } else { + printf("[LN][WS] WebSocketClientClose call returned success, waiting for close callback\n"); + } + + return ret; +} + +/** + * @brief 获取当前WebSocket关闭状态 + * @return 当前关闭状态 + */ +static ws_close_status_t ln_ws_get_close_status(void) +{ + return g_ws_close_status; +} + +/** + * @brief 重置WebSocket关闭状态 + */ +static void ln_ws_reset_close_status(void) +{ + g_ws_close_status = WS_CLOSE_NOT_EXECUTED; + printf("[LN][WS] WebSocket close status reset to NOT_EXECUTED (%d)\n", g_ws_close_status); +} + +/* ============================ 公共接口函数 ============================ */ + +/** + * @brief 获取WebSocket关闭状态(公共接口) + * @return 当前关闭状态 + */ +int ln_ws_get_close_status_public(void) +{ + return (int)ln_ws_get_close_status(); +} + +/** + * @brief 打印WebSocket状态信息(调试用) + */ +void ln_ws_print_status_info(void) +{ + printf("[LN][WS] === WebSocket Status Info ===\n"); + printf("[LN][WS] Connection State: %s (%d)\n", ln_ws_get_connection_state_string(), g_ws_connected); + printf("[LN][WS] Close Status: %d (0=NOT_EXECUTED, 1=STARTING, 2=SUCCESS)\n", g_ws_close_status); + printf("[LN][WS] Client FD: %d\n", g_ws_client_fd); + printf("[LN][WS] Running: %d\n", g_ws_running); + printf("[LN][WS] Reconnect Count: %u\n", g_ws_reconnect_count); + printf("[LN][WS] ===============================\n"); +} + +/** + * @brief 进入休眠状态(公共接口) + * @return 0成功,-1失败 + */ +int ln_ws_enter_sleep(void) +{ + printf("[LN][WS] Entering sleep mode\n"); + + if (!g_ws_running) { + printf("[LN][WS] WebSocket service not running, cannot enter sleep\n"); + return -1; + } + + // 如果当前有连接,先断开 + if (g_ws_client_fd >= 0) { + printf("[LN][WS] Disconnecting before entering sleep mode\n"); + ln_ws_close_with_status(g_ws_client_fd); + } + + // 设置状态为休眠 + g_ws_connected = WS_STATE_SLEEP; + printf("[LN][WS] Sleep mode activated, all operations paused\n"); + + return 0; +} + +/** + * @brief 退出休眠状态(公共接口) + * @return 0成功,-1失败 + */ +int ln_ws_exit_sleep(void) +{ + printf("[LN][WS] Exiting sleep mode\n"); + + if (g_ws_connected != WS_STATE_SLEEP) { + printf("[LN][WS] Not in sleep mode, current state: %s\n", ln_ws_get_connection_state_string()); + return -1; + } + + // 设置状态为断开,让主线程重新开始连接 + g_ws_connected = WS_STATE_DISCONNECTED; + printf("[LN][WS] Sleep mode deactivated, resuming normal operations\n"); + + return 0; +} + + -- 2.17.1