From 121ecfe0977ac3a480994f5c90942a2e0d853b07 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Sat, 17 Jan 2026 12:10:52 +0800 Subject: [PATCH] =?utf8?q?=E9=80=80=E5=87=BA=E5=AF=B9=E8=AF=9D=E6=97=B6?= =?utf8?q?=E4=BF=9D=E8=AF=81=E8=B5=84=E6=BA=90=E9=94=80=E6=AF=81=E5=90=8E?= =?utf8?q?=E9=87=8D=E8=BF=9Ewebsocket=E3=80=82=E5=87=8F=E5=B0=91=E6=AD=BB?= =?utf8?q?=E6=9C=BA=E9=A3=8E=E9=99=A9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../zhihui/leiniao/imsl_ln/ln_api_websocket.c | 83 +++++++++++++++---- 1 file changed, 68 insertions(+), 15 deletions(-) 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 1a98f6f38..e9e9071bd 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_websocket.c @@ -1851,6 +1851,9 @@ int ln_ws_send_voice_chat_interrupt(const char *reason) return -1; } + // 检查是否是退出对话场景 + bool is_exit_dialogue = (strcmp(reason, "退出对话") == 0); + // 检查是否需要在1秒内有数据时触发重连 bool need_reconnect = ln_ws_check_binary_data_interrupt(); @@ -1899,24 +1902,64 @@ int ln_ws_send_voice_chat_interrupt(const char *reason) LN_WS_DEBUG("Sending VoiceChatInterrupt: %s\n", json_string); // 发送消息 + int ret = uapi_ws_send_text(json_string); + if (ret == 0) { + LN_WS_DEBUG("VoiceChatInterrupt sent successfully\n"); + } // 清理资源 - int ret=0; - if (need_reconnect || (g_audio_chat_ctx.finish_state == LN_CHAT_SENT_END_NO_REPLY)) - { - ret = uapi_ws_send_text(json_string); - if (ret == 0) { - LN_WS_DEBUG("VoiceChatInterrupt sent successfully\n"); - } - // 如果检测到频繁数据接收,直接重连 - LN_WS_INFO("Triggering reconnection due to frequent binary data reception\n"); - if (ln_ws_reconnect() != 0) { - LN_WS_ERROR("Failed to reconnect after frequent data reception\n"); + // 如果需要重连 + if (need_reconnect || (g_audio_chat_ctx.finish_state == LN_CHAT_SENT_END_NO_REPLY)) { + if (is_exit_dialogue) { + // 只有退出对话场景,才等待资源清理完成后再重连 + // 资源清理(AUDIO_DEINIT)通过消息队列异步执行,需要等待清理完成 + LN_WS_INFO("Exit dialogue mode, waiting for resource cleanup before reconnection\n"); + + // 轮询检查资源清理完成标志,最多等待500ms + const uint32_t max_wait_ms = 500; + const uint32_t check_interval_ms = 20; // 每20ms检查一次 + uint32_t waited_ms = 0; + bool cleanup_complete = false; + + while (waited_ms < max_wait_ms) { + // 检查音频是否已反初始化(资源清理完成的标志) + if (!ln_ws_is_audio_initialized()) { + cleanup_complete = true; + LN_WS_INFO("Resource cleanup completed after %u ms\n", waited_ms); + break; + } + LOS_Msleep(check_interval_ms); + waited_ms += check_interval_ms; + } + + if (!cleanup_complete) { + LN_WS_WARN("Resource cleanup timeout after %u ms, proceeding with reconnection anyway\n", max_wait_ms); + } + + // 再次检查连接状态,确保在等待期间连接状态未改变 + if (g_ws_connected == WS_STATE_CONNECTED) { + LN_WS_INFO("Triggering reconnection after exit dialogue (resource cleanup %s)\n", + cleanup_complete ? "completed" : "timeout"); + if (ln_ws_reconnect() != 0) { + LN_WS_ERROR("Failed to reconnect after exit dialogue\n"); + } + } else { + LN_WS_WARN("Connection state changed during wait, skip reconnection: %d\n", g_ws_connected); + } + } else { + // 非退出对话场景(如二进制数据间隔检查触发的重连),直接重连 + // WebSocket重连是网络层操作,与音频资源无关 + if (g_ws_connected == WS_STATE_CONNECTED) { + LN_WS_INFO("Triggering reconnection %s\n", + need_reconnect ? "due to binary data interrupt" : "due to chat finish state"); + if (ln_ws_reconnect() != 0) { + LN_WS_ERROR("Failed to reconnect\n"); + } + } else { + LN_WS_WARN("Connection state changed, skip reconnection: %d\n", g_ws_connected); + } } } - else { - LN_WS_INFO("no to send VoiceChatInterrupt\n"); - } cJSON_free(json_string); cJSON_Delete(json); @@ -2409,6 +2452,16 @@ static int ln_ws_parse_data_message(const char *json_str, ws_data_msg_t *data_ms if (data_msg->command == WS_CMD_RANDOM_STORY_RESPONSE) { cJSON *data_obj = cJSON_GetObjectItem(root, "data"); if (data_obj && cJSON_IsObject(data_obj)) { + // 根据协议,先检查errorCode字段(在data对象中,不在data.data中) + cJSON *error_code = cJSON_GetObjectItem(data_obj, "errorCode"); + if (error_code && !cJSON_IsNull(error_code)) { + // 如果errorCode不为null,表示发生了错误 + // 根据协议,错误响应中会包含data字段,其中包含错误信息和音频URL + LN_WS_WARN("RandomStoryResponse error: errorCode=%s\n", + cJSON_IsString(error_code) ? error_code->valuestring : "unknown"); + // 错误响应中仍然会包含data字段,继续解析以便播放错误音频 + } + // 解析finished字段(先解析到data_msg,但不更新全局上下文) cJSON *finished = cJSON_GetObjectItem(data_obj, "finished"); if (finished && cJSON_IsBool(finished)) { @@ -2437,7 +2490,7 @@ static int ln_ws_parse_data_message(const char *json_str, ws_data_msg_t *data_ms } } - // 解析data.data字段 + // 解析data.data字段(根据协议,即使有错误,data字段也可能存在,包含错误信息和音频URL) cJSON *data_data = cJSON_GetObjectItem(data_obj, "data"); if (data_data && cJSON_IsObject(data_data)) { // 解析storyTheme字段,存储到text_content中 -- 2.17.1