Merge #2332 into sdk650pathc0423 from refs/changes/2332/head
author胡传军 <1224667075@qq.com>
Sat, 20 Sep 2025 12:42:39 +0000 (12:42 +0000)
committer罗正 <1732036298@qq.com>
Sat, 20 Sep 2025 12:42:39 +0000 (12:42 +0000)
Code review from 胡传军

* refs/changes/2332/head: (3 commits squashed)

  - 修改ws 的stop调用

  - 增加ln ws休眠接口

  - Merge branch &#39;sdk650pathc0423&#39; of https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230 into sdk650pathc0423

Signed-off-by: aliyun8003852482 <1224667075@qq.com>
Merged-by: 罗正 <1732036298@qq.com>
link: https://codeup.aliyun.com/64191456b9581d62e8f81ac0/FD230/change/2332
code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c

index aaed755..bff370a 100644 (file)
@@ -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"},
index f76634b..990ffd7 100644 (file)
@@ -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);
index 555a111..86251d1 100644 (file)
 #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;
+}
+
+