{
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);
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)
{
{(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"},
#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命令枚举 */
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);
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)
{
(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);
}
/*
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;
}
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");
}
// 连接管理部分
+ 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");
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);
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;
+ }
}
/*
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;
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);
}
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;
return "连接中";
case WS_STATE_CONNECTED:
return "连接成功";
+ case WS_STATE_SLEEP:
+ return "休眠状态";
default:
return "未知状态";
}
}
}
+/* ============================ 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;
+}
+
+