雷鸟增加 AT^LN_WS_LOG_LEVEL 指令动态控制日志等级
author孙春阳 <snickersun@163.com>
Sun, 28 Dec 2025 09:03:55 +0000 (17:03 +0800)
committer孙春阳 <snickersun@163.com>
Sun, 28 Dec 2025 09:03:55 +0000 (17:03 +0800)
雷鸟websocket 没有token或deviceid 就不访问网络

code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c
code/sdk/zhihui/websocket/os_ws/haisi_websocket.c
code/sdk/zhihui/websocket/os_ws/haisi_websocket.h

index 1665de9..09ecff6 100644 (file)
@@ -1912,6 +1912,24 @@ static uint32_t ln_bt_disconnect_at(uint8_t *para, uint32_t paraLen, char *strCo
     ln_bt_disconnect();
     return ERRCODE_SUCC;
 }
+static uint32_t ln_ws_set_log_level_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    LN_UNUSED(strCommonCmd);
+    LN_UNUSED(para);
+    LN_UNUSED(paraLen);
+    printf("[LN][WS_LOG_LEVEL] Setting WebSocket log level: %s\n", para);
+    return ERRCODE_SUCC;
+    uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
+    uint32_t argc = 0;
+    if (ConvertCmdToParam(para, paraLen, argv, &argc) != LN_SUCCESS || argc < 1) {
+        printf("ERROR: Failed to parse log level\n");
+        return ERRCODE_FAIL;
+    }
+    uint8_t log_level = (uint8_t)atoi((char*)argv[0]);
+    ln_ws_set_log_level(log_level);
+    printf("[LN][WS_LOG_LEVEL] Set WebSocket log level to: %d\n", log_level);
+    return ERRCODE_SUCC;
+}
 
 static const at_cmd_table_t g_ln_api_cmd[] = {
     /* ---------------------------------- 雷鸟API --------------------------------- */
@@ -2011,6 +2029,9 @@ static const at_cmd_table_t g_ln_api_cmd[] = {
     {(char *)"AT^LN_BT_UNPAIR", ln_bt_unpair_at, (char *)"解绑指定蓝牙设备: AT^LN_BT_UNPAIR=AA:BB:CC:DD:EE:FF"},
     {(char *)"AT^LN_BT_CONNECT", ln_bt_connect_at, (char *)"连接蓝牙设备: AT^LN_BT_CONNECT=AA:BB:CC:DD:EE:FF"},
     {(char *)"AT^LN_BT_DISCONNECT", ln_bt_disconnect_at, (char *)"断开蓝牙设备: AT^LN_BT_DISCONNECT=AA:BB:CC:DD:EE:FF"},
+
+    //WebSocket日志等级设置
+    {(char *)"AT^LN_WS_LOG_LEVEL", ln_ws_set_log_level_at, (char *)"设置WebSocket日志等级: AT^LN_WS_LOG_LEVEL=0-3"},
 };
 
 
index 857b92f..925c6e3 100644 (file)
@@ -43,6 +43,10 @@ typedef enum {
 // 当前日志等级(可通过配置修改)
 static ln_ws_log_level_t g_log_level =  LN_WS_LOG_INFO;
 
+void ln_ws_set_log_level(uint8_t level)
+{
+    g_log_level = (ln_ws_log_level_t)level;
+}
 // 打印函数
 // 日志等级字符串数组
 static const char *g_log_level_str[] = {
@@ -331,7 +335,7 @@ static void ln_ws_event_callback(ws_event_type_t event_type)
 }
 
 /* URL构建回调函数 */
-static void ln_ws_url_callback(char *url, size_t url_size, char *header_buf, size_t header_size)
+static int ln_ws_url_callback(char *url, size_t url_size, char *header_buf, size_t header_size)
 {
 #if LN_ENV_PRODUCTION
 const char *base = "ws://ambybox-o.api.leiniao.com/ambybox-device-api/v1/websocket"; 
@@ -340,8 +344,17 @@ const char *base = "ws://ambybox-o.api.leiniao.com/ambybox-device-api/v1/websock
 #endif
     const char *device_id = uapi_ln_get_device_id();
     const char *token = uapi_ln_get_device_token();
-    if (!device_id) device_id = "";
-    if (!token) token = "";
+    
+    // 检查 token 和 device_id 是否有效
+    if (!token || strlen(token) == 0) {
+        LN_WS_ERROR("ln_ws_url_callback: token is null or empty\n");
+        return -1;
+    }
+    if (!device_id || strlen(device_id) == 0) {
+        LN_WS_ERROR("ln_ws_url_callback: device_id is null or empty\n");
+        return -1;
+    }
+    
     extern volatile int g_ws_is_reconnecting ; /* 是否正在重连的标志位 */
     
     /* 仅使用 deviceToken 也可通过;额外带上 deviceId 与 reconnect 便于后端管理 */
@@ -360,6 +373,8 @@ const char *base = "ws://ambybox-o.api.leiniao.com/ambybox-device-api/v1/websock
     // 110.42.224.129 8910
     //  snprintf(url, url_size, "%s","ws://110.42.224.129:8910");
             //  base, token, device_id, g_ws_reconnect_count);
+    
+    return 0;
 }
 
 /* 心跳处理回调函数 */
index 90dc8c5..c42d946 100644 (file)
@@ -110,8 +110,7 @@ static volatile int g_ws_is_sending = 0;  /* 发送状态标志:0=空闲,1=
 static volatile int g_ws_is_suspended = 0;  /* suspend状态标志:0=未suspend,1=已suspend */
 static volatile int g_ws_wake_keep = 0;  /* 保持唤醒状态标志:0=允许低功耗,1=保持唤醒 */
 
-static void uapi_ws_build_url(char *out, size_t out_size);
-static void uapi_ws_default_url_handler(char *url, size_t url_size, char *header_buf, size_t header_size);
+// static void uapi_ws_build_url(char *out, size_t out_size);
 int uapi_ws_send_ping(void);
 static int uapi_ws_close_with_status(int client_fd);
 static ws_close_status_t uapi_ws_get_close_status(void);
@@ -478,7 +477,7 @@ int last_connection_state = WS_STATE_DISCONNECTED;  // 记录上次连接状态
         
         if (g_ws_connected == WS_STATE_DISCONNECTED) {
             if (g_ws_client_fd >= 0) {
-            {
+            
                 if(g_ws_close_status== WS_CLOSE_NOT_EXECUTED){
                     HAISI_WS_DEBUG("WebSocketClientClose WS_CLOSE_NOT_EXECUTED\n");
                     uapi_ws_close_with_status(g_ws_client_fd);
@@ -486,7 +485,28 @@ int last_connection_state = WS_STATE_DISCONNECTED;  // 记录上次连接状态
                     g_ws_client_fd=-1;
                     HAISI_WS_DEBUG("WebSocketClientClose WS_CLOSE_NOT_EXECUTED end\n");
                 }
+            
             }
+            char url[512] = {0};
+            char header_buf[512] = {0};
+            
+            // 使用回调函数处理URL和Header(必须在创建WebSocket客户端之前检查)
+            if (g_ws_callbacks.url_callback != NULL) {
+                int url_callback_ret = g_ws_callbacks.url_callback(url, sizeof(url), header_buf, sizeof(header_buf));
+                if (url_callback_ret != 0) {
+                    // URL回调失败,设置状态为断开,重置超时计时器,确保不创建socket
+                    HAISI_WS_ERROR("URL callback failed: %d, will not create WebSocket client\n", url_callback_ret);
+                    g_ws_connected = WS_STATE_DISCONNECTED;
+                    uapi_ws_reset_connect_timer();
+                    // 如果已有客户端fd,先关闭它
+                    if (g_ws_client_fd >= 0) {
+                        uapi_ws_close_with_status(g_ws_client_fd);
+                        g_ws_client_fd = -1;
+                    }
+                    // 延迟一段时间后重试,避免频繁检查
+                    usleep(2000 * 1000); // 延迟2秒
+                    continue;
+                }
             }
 
             if (g_ws_client_fd < 0) {
@@ -513,14 +533,7 @@ int last_connection_state = WS_STATE_DISCONNECTED;  // 记录上次连接状态
                 }
             }
 
-            char url[512] = {0};
-            char header_buf[512] = {0};
-            
-            // 使用回调函数处理URL和Header
-            if (g_ws_callbacks.url_callback != NULL) {
-                g_ws_callbacks.url_callback(url, sizeof(url), header_buf, sizeof(header_buf));
-            }
-
+ 
             HAISI_WS_INFO("尝试连接WebSocket: %s\n", url);
             HAISI_WS_DEBUG("使用Header: %s\n", header_buf);
              int ret=0;
index bd7bdb5..358d3ea 100644 (file)
@@ -30,7 +30,7 @@ typedef void (*ws_binary_message_callback_t)(const uint8_t *raw_data, uint32_t t
 typedef void (*ws_incomplete_message_callback_t)(const char *raw_data, size_t length, bool isBinary);
 
 /* URL构建回调函数类型 */
-typedef void (*ws_url_callback_t)(char *url, size_t url_size, char *header_buf, size_t header_size);
+typedef int (*ws_url_callback_t)(char *url, size_t url_size, char *header_buf, size_t header_size);  // 返回0表示成功,-1表示失败
 
 /* 心跳处理回调函数类型 */
 typedef int (*ws_heartbeat_callback_t)(void);  // 返回1表示需要发送心跳,返回0表示不需要