优化通知ui哄睡开始接口,区分是小程序发起的还是意图识别的
authorluozheng <1732036298@qq.com>
Tue, 30 Sep 2025 06:13:20 +0000 (14:13 +0800)
committerluozheng <1732036298@qq.com>
Tue, 30 Sep 2025 06:13:20 +0000 (14:13 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/uiservice/src/ui_service.cpp
code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_story_random.c
code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.cpp
code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h

index 3022283..f8353cc 100644 (file)
@@ -196,7 +196,7 @@ namespace OHOS
         bool SwitchExpressionVideo(const char* videoPath);
         
         // 哄睡模式处理函数
-        void HandleSleepModeStart(const char* theme);
+        void HandleSleepModeStart(const char* theme, int is_intention_result);
         void HandleSleepModeEnd();
         void HandleBindAndUnbind(int is_bind);
         // 减低视频帧率
index e49d60a..462f049 100644 (file)
          return true; // 异步调用,返回 true 表示调用已提交
      }
 
-    void ThunderBirdModel::HandleSleepModeStart(const char* theme)
+    void ThunderBirdModel::HandleSleepModeStart(const char* theme, int is_intention_result)
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleSleepModeStart");
         if (ThunderBirdMainView::GetInstance()) {
index 2d3ef9f..d20e286 100644 (file)
@@ -439,11 +439,14 @@ void HandTaskCharacterConfigNotify(Request *request)
 void HandSleepModeStartNotify(Request *request)
 {
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandSleepModeStartNotify msg_id = %d", request->msgId);
-    std::string theme(static_cast<char*>(request->data), request->len);
+    std::string value(static_cast<char*>(request->data), request->len);
+    std::string theme = value.substr(0, value.find('|'));
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandSleepModeStartNotify storyTheme = %s", theme.c_str());
+    int is_intention_result = std::stoi(value.substr(value.find('|') + 1));
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandSleepModeStartNotify is_intention_result = %d", is_intention_result);
     //跳转到哄睡模式
     GraphicService::GetInstance()->PostGraphicEvent(
-        std::bind(&OHOS::ThunderBirdModel::HandleSleepModeStart,OHOS::ThunderBirdModel::GetInstance(),theme.c_str()));
+        std::bind(&OHOS::ThunderBirdModel::HandleSleepModeStart,OHOS::ThunderBirdModel::GetInstance(),theme.c_str(), is_intention_result));
 }
 // 哄睡模式结束通知
 void HandSleepModeEndNotify(Request *request)
@@ -552,14 +555,6 @@ void HandBindAndUnbindNotify(Request *request)
         std::bind(&OHOS::ThunderBirdModel::HandleBindAndUnbind,OHOS::ThunderBirdModel::GetInstance(), is_bind));
 }
 
-// 屏保下载成功通知
-void HandScreenImageDownloadSuccessNotify(Request *request)
-{
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandScreenImageDownloadSuccessNotify msg_id = %d", request->msgId);
-    GraphicService::GetInstance()->PostGraphicEvent(
-        std::bind(&OHOS::ThunderBirdModel::HandleScreenImageDownloadSuccess,OHOS::ThunderBirdModel::GetInstance()));
-}
-
 // 更新文本内容通知
 void HandTextUpdateNotify(Request *request)
 {
@@ -583,8 +578,11 @@ void HandDownloadSuccessNotify(Request *request)
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandDownloadSuccessNotify msg_id = %d", request->msgId);
     int type = *(int *)request->data;
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_UI_SERVICE, "HandDownloadSuccessNotify type = %d", type);
-    // GraphicService::GetInstance()->PostGraphicEvent(
-    //     std::bind(&OHOS::ThunderBirdModel::HandleDownloadSuccess,OHOS::ThunderBirdModel::GetInstance(), type));
+    if(type == 0) //屏保切换
+    {
+        GraphicService::GetInstance()->PostGraphicEvent(
+            std::bind(&OHOS::ThunderBirdModel::HandleScreenImageDownloadSuccess,OHOS::ThunderBirdModel::GetInstance()));
+    }
 }
 /* -------------------------------------------------------------------------- */
 #ifdef __cplusplus
index bc34f3a..16deb0e 100644 (file)
@@ -713,6 +713,33 @@ static uint32_t ln_ws_start_at(uint8_t *para, uint32_t paraLen, char *strCommonC
     return ERRCODE_SUCC;
 }
 
+//AT^LN_WS_START_WITH_CALLBACK=tick_time
+static uint32_t ln_ws_start_with_callback_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    printf("[LN][WS_START_WITH_CALLBACK]\n");
+    uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
+    uint32_t argc = 0;
+    (void)ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (argc < 1)
+    {
+        printf("Usage: AT^LN_WS_START_WITH_CALLBACK=<tick_time>\n");
+        return ERRCODE_FAIL;
+    }
+    if (atoi((char*)argv[0]) < 1000 || atoi((char*)argv[0]) > 10000)
+    {
+        printf("Usage: AT^LN_WS_START_WITH_CALLBACK=<tick_time> (tick_time >= 1000ms && tick_time <= 10000ms)\n");
+        return ERRCODE_FAIL;
+    }
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN][WS_START_WITH_CALLBACK] tick_time: %dms\n", atoi((char*)argv[0]));
+    int tick_time = atoi((char*)argv[0]);
+    int ret = ln_ws_start(ln_ws_process_message,tick_time);
+    if (ret != 0)
+    {
+        printf("[LN][WS_START_WITH_CALLBACK] failed: %d\n", ret);
+        return ERRCODE_FAIL;
+    }
+    return ERRCODE_SUCC;
+}
 /* AT^LN_WS_STOP */
 static uint32_t ln_ws_stop_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
 {
@@ -1893,6 +1920,7 @@ static const at_cmd_table_t g_ln_api_cmd[] = {
 
      /* -------------------------------- WebSocket -------------------------------- */
     {(char *)"AT^LN_WS_START", ln_ws_start_at, (char *)"启动WebSocket连接: AT^LN_WS_START"},
+    {(char *)"AT^LN_WS_START_WITH_CALLBACK", ln_ws_start_with_callback_at, (char *)"启动WebSocket连接带设置回调函数: AT^LN_WS_START_WITH_CALLBACK"},
     {(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"},
index 99c9ece..0264379 100644 (file)
@@ -235,6 +235,8 @@ char *uapi_ln_get_device_version(void)
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "g_device_version: %s", g_device_version);
     return g_device_version;
 }
+
+static int websocket_retry_connect_count = 0;
 /* 获取设备token: 优先读本地缓存,判断过期,否则刷新 */
 char *uapi_ln_get_device_token(void)
 {
@@ -293,6 +295,16 @@ char *uapi_ln_get_device_token(void)
     else
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[TOKEN] 网络离线,无法刷新 Token");
+        websocket_retry_connect_count++;
+        if (websocket_retry_connect_count >= 100)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[TOKEN] 网络离线,无法刷新 Token,重试次数超过10次,进入休眠");
+            ln_ws_enter_sleep();
+        }
+        else
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[TOKEN] 网络离线,无法刷新 Token,重试次数: %d", websocket_retry_connect_count);
+        }
     }
     return NULL;
 }
@@ -637,7 +649,10 @@ void ln_ws_process_message(const ws_data_msg_t *data_msg, ws_command_t type)
     }
     case WS_CMD_VOICE_CHAT_RESPONSE:
     {
-        push_text_to_ui(data_msg->text_content);
+        if (json_str)
+        {
+            ln_parse_voice_chat_response(json_str, (int)strlen(json_str));
+        }
         break;
     }
     case WS_CMD_CHOOSE_STORY_RESPONSE:
@@ -1170,10 +1185,10 @@ static void ln_http_server_send_task(void const *arg)
         {
             if (mail.data && mail.len == sizeof(ln_story_random_req_t))
             {
-                printf("LN_HTTP_SERVICE_CMD_STORY_RANDOM:随机故事\n");
-                ln_story_random_req_t req;
-                memcpy(&req, mail.data, sizeof(req));
-                ln_story_random_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.story_theme[0] ? req.story_theme : NULL);
+                // printf("LN_HTTP_SERVICE_CMD_STORY_RANDOM:随机故事\n");
+                // ln_story_random_req_t req;
+                // memcpy(&req, mail.data, sizeof(req));
+                // ln_story_random_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.story_theme[0] ? req.story_theme : NULL);
             }
         }
         else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY)
@@ -1336,12 +1351,6 @@ static void ln_init_required_dirs(void)
     }
 }
 
-// 初始化一些配置信息
-static void ln_load_init_config(void)
-{
-    ln_read_character_config();
-}
-
 // 雷鸟http服务初始化
 errcode_t uapi_ln_http_server_init(void)
 {
@@ -1363,7 +1372,6 @@ errcode_t uapi_ln_http_server_init(void)
     ln_ws_start(ln_ws_process_message,2000);
 
     ln_init_required_dirs();
-    ln_load_init_config();
 
     return ERRCODE_SUCC;
 }
\ No newline at end of file
index ef687da..b58b724 100644 (file)
@@ -50,7 +50,7 @@ void ln_read_character_config(void)
         return;
     }
     json_buf[n] = '\0';
-    ln_parse_character_config(json_buf, (int)n);
+    ln_parse_character_config_local(json_buf, (int)n);
     fclose(file);
     printf("[DEVICE_CHARACTER] read character config success\n");
 }
index 7533fb1..d2366ba 100644 (file)
@@ -201,6 +201,64 @@ uint32_t ln_story_random_http(const char *device_id,
     return ERRCODE_SUCC;
 }
 
+//解析语音聊天响应
+void ln_parse_voice_chat_response(const char *json_str, int json_len)
+{
+    printf("%s\n", json_str);
+    cJSON *root = cJSON_Parse(json_str);
+    if (!root)
+    {
+        printf("parse failed\n");
+        return;
+    }
+    cJSON *data = cJSON_GetObjectItem(root, "data");
+    if (!data)
+    {
+        printf("data is null\n");
+        cJSON_Delete(root);
+        return;
+    }
+    cJSON *textContent = cJSON_GetObjectItem(data, "textContent");
+    if (!textContent)
+    {
+        printf("textContent is null\n");
+        cJSON_Delete(root);
+        return;
+    }
+    printf("用户文本内容: %s\n", textContent->valuestring);
+    push_text_to_ui(textContent->valuestring);
+
+    cJSON *intention = cJSON_GetObjectItem(data, "intention");
+    if (!intention)
+    {
+        printf("intention is null\n");
+        cJSON_Delete(root);
+        return;
+    }
+    printf("用户意图识别结果: %s\n", intention->valuestring);
+    if(strcmp(intention->valuestring, "StartSleepMode") == 0)
+    {
+        printf("开始哄睡\n");
+        push_sleep_mode_start_notification(NULL, 1);//1意图识别结果,不是小程序直接发起
+        //通知websocket发送随机故事请求
+        ln_ws_send_random_story_request(NULL);
+    }
+    else if(strcmp(intention->valuestring, "EndSleepMode") == 0)
+    {
+        printf("结束哄睡\n");
+        push_sleep_mode_end_notification();
+    }
+    cJSON *npcEmotion = cJSON_GetObjectItem(data, "npcEmotion");
+    if (!npcEmotion)
+    {
+        printf("NPC情感状态 is null\n");
+        cJSON_Delete(root);
+        return;
+    }
+    printf("NPC情感状态: %s\n", npcEmotion->valuestring);
+    cJSON_Delete(root);
+}
+
 /* 解析哄睡模式开始:提取data.storyTheme并触发随机故事 */
 void ln_parse_sleep_mode_start(const char *json_str, int json_len)
 {
@@ -229,7 +287,7 @@ void ln_parse_sleep_mode_start(const char *json_str, int json_len)
     if(theme == NULL || theme[0] == '\0') {
         theme = "随机";
     }
-    push_sleep_mode_start_notification(theme);
+    push_sleep_mode_start_notification(theme, 0);//0小程序直接发起,不是意图识别结果
     //通知websocket发送随机故事请求
     ln_ws_send_random_story_request(theme);
     if (root) cJSON_Delete(root);
index 5a24c2e..a656a7c 100644 (file)
@@ -150,11 +150,12 @@ void push_character_config_change_notification(const char* characterId,
 
     SendMsgToUIService(HAND_CHARACTER_CONFIG_CHANGE_NOTIFY, 0, (void *)payload, (int32_t)strlen(payload));
 }
-//通知ui跳转哄睡界面
-void push_sleep_mode_start_notification(const char *storyTheme)
+//通知ui跳转哄睡界面:1是意图识别结果,0是其他结果
+void push_sleep_mode_start_notification(const char *storyTheme, int is_intention_result)
 {
-    /* 发送包含字符串结束符,避免接收端以%s打印读取越界产生乱码 */
-    SendMsgToUIService(HAND_SLEEP_MODE_START_NOTIFY, 0, (void *)storyTheme, (int32_t)(strlen(storyTheme) + 1));
+    char payload[256] = {0};
+    (void)snprintf(payload, sizeof(payload) - 1, "%s|%d", storyTheme, is_intention_result);
+    SendMsgToUIService(HAND_SLEEP_MODE_START_NOTIFY, 0, (void *)payload, (int32_t)strlen(payload));
 }
 //通知ui跳转哄睡界面结束
 void push_sleep_mode_end_notification(void)
index 2e422e0..1f9fb39 100644 (file)
@@ -69,8 +69,8 @@ void push_character_config_change_notification(
                                               const char *eyesColor,
                                               const char *hairStyle,
                                               int screenImageAsEmoji);
-//通知ui跳转哄睡界面
-void push_sleep_mode_start_notification(const char *storyTheme);
+//通知ui跳转哄睡界面,是否是意图识别结果
+void push_sleep_mode_start_notification(const char *storyTheme, int is_intention_result);
 //通知ui跳转哄睡界面结束
 void push_sleep_mode_end_notification(void);
 //通知ui下载表情