雷鸟:聚合平台ai接入,ui显示有问题 2353/1 2353/head 2354/target/1
authorcheng <chengyf@zhihuishixun.com>
Sun, 21 Sep 2025 08:03:35 +0000 (16:03 +0800)
committercheng <chengyf@zhihuishixun.com>
Sun, 21 Sep 2025 08:03:35 +0000 (16:03 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdDialogueView.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdPresenter.cpp
code/sdk/zhihui/ai_old/websocket_server_example.cpp
code/sdk/zhihui/ai_old/websocket_server_manager.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api.c

index 3b30d56..4cfa4c4 100644 (file)
@@ -151,6 +151,9 @@ namespace OHOS
         // 对话状态相关函数
         int GetConversationStatus();
 
+        bool Get_is_all_services_ready();
+        void init_all_callback(void);
+
     private:
         ThunderBirdModel();
         virtual ~ThunderBirdModel();
@@ -194,6 +197,8 @@ namespace OHOS
         int m_networkType;             // 网络类型
         bool m_hasNetwork;             // 网络连接标志位
         bool m_networkStatusChanged;   // 网络状态变化标志位
+
+        bool is_all_services_ready = false;
     };
 }
 
index 3a66221..309773e 100644 (file)
@@ -179,7 +179,7 @@ namespace OHOS
             }
             if(ThunderBirdModel::GetInstance()->IsTextEmpty() == true)
             {
-                UpdateDialogueText("保镖小姐 , 你来啦");
+                UpdateDialogueText("等待网络连接");
             }
             else
             {
@@ -235,6 +235,7 @@ namespace OHOS
     }
     void ThunderBirdDialogueView::UpdateDialogueText(const char *text)
     {
+        if(!TextLabel || !TextLabel_Y) return;
         TextLabel->SetText(text); 
         TextLabel_Y->SetText(text); 
     }
index 72bf980..149cfe1 100644 (file)
  #include "custom_runtime.h"
  #include "ln_api.h"
  #include "kv_store.h"
+
+ #define JUHEPINGTAI 1
+ #if JUHEPINGTAI
+ #include "websocket_server_manager.h"
+ #endif
  namespace OHOS
  {
      enum OTA_STATUS
          
          // 添加文本内容
          m_currentTimeStr = textId;
-         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SetTextStr: added text, current length: %zu", m_currentTimeStr.length());
+         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SetTextStr: added text, current length: %zu", m_currentTimeStr.length());
      }
      
      void ThunderBirdModel::ClearTextStr()
                 // 获取一下OTA 是否有最新版本
                 ota_update_boot();
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Network connected, calling HTTP service");
+                #if JUHEPINGTAI
+                uapi_init_all_websocket_servers();
+                uapi_start_all_websocket_servers(); // 连接服务器
+                #endif
             } else {
                 // 网络断开,记录状态变化日志
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Network disconnected");
             SetNetworkStatusChanged(false);
         }
         
+        #if JUHEPINGTAI
+        if(is_all_services_ready == false)
+        {
+            if (are_all_services_ready())//如果返回的是true就可以开始对话了
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Network disconnected");
+                init_all_callback();
+                is_all_services_ready = true;
+            }   
+        }
+        #endif
+        
         // 更新设备状态
         UpdateDeviceStatus();
         
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "StatusCallback: status=%d", static_cast<int>(m_currentStatus));
     }
     
+
+    bool ThunderBirdModel::Get_is_all_services_ready()
+    {
+        return is_all_services_ready;
+    }
     // ==================== 状态管理相关函数实现 ====================
     
     /**
         m_networkStatusChanged = changed;
     }
 
+
+    void ws_register_chat_filter_cb(char *result)
+    {
+    }
+    void ws_register_ai_question_cb(char *buf)
+    {
+    }
+
+    void ws_register_ai_answer_cb(char *buf, uint8_t type)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ws_register_ai_answer_cb:%s\n", buf ? buf : "<null>");
+        if (buf && buf[0] != '\0') {
+            // 先写入文本,再置对话标志,避免UI读到标志已置但文本尚未更新
+            ThunderBirdModel::GetInstance()->SetTextStr(buf);
+            set_start_conversation_flag(START_CONVERSATION_FLAG_START);
+        } else {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ws_register_ai_answer_cb: empty buf, skip update");
+        }
+    }
+
+    void ThunderBirdModel::init_all_callback(void)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "init_all_callback\n");
+        // ws_register_chat_filter_callback(ws_register_chat_filter_cb);
+        // ws_register_ai_question_callback(ws_register_ai_question_cb);
+        ws_register_ai_answer_callback(ws_register_ai_answer_cb);
+    }
+
  }
  
\ No newline at end of file
index 1f427da..96c1949 100644 (file)
@@ -167,10 +167,22 @@ namespace OHOS
                 {
                     //判断是否为开始对话 如果是开始对话 则更新对话数据
                     if(ThunderBirdModel::GetInstance()->GetConversationStatus() == 1){
-                    //更新对话数据
-                    std::string dialogueText = ThunderBirdModel::GetInstance()->GetTextStr();  
-                    //只有一行 是拼接 还是直接覆盖?
-                    ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(dialogueText.c_str());
+                        //更新对话数据
+                        std::string dialogueText = ThunderBirdModel::GetInstance()->GetTextStr();  
+                        //只有一行 是拼接 还是直接覆盖?
+                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateDialogueText:%s\n",dialogueText.c_str());
+                        ThunderBirdDialogueView::GetInstance()->UpdateDialogueText(dialogueText.c_str());
+                    }
+                    else{
+                        //如果不是对话 需要判断 是否服务准备好
+                        if(ThunderBirdModel::GetInstance()->Get_is_all_services_ready() == false)
+                        { 
+                            ThunderBirdDialogueView::GetInstance()->UpdateDialogueText( "等待网络连接" );
+                        }
+                        else
+                        {
+                            ThunderBirdDialogueView::GetInstance()->UpdateDialogueText( "网络连接成功" );
+                        }
                     }
                 }
             }
@@ -305,16 +317,19 @@ namespace OHOS
      */
     void ThunderBirdPresenter::HandleDialogueFunction(int16_t currentView, int16_t currentSubView)
     {
+        bool flag = ThunderBirdModel::GetInstance()->Get_is_all_services_ready();
         if (currentView == THUNDERBIRD_DIALOGUEVIEW && 
-            currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING) {
+            currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING && flag == true) {
             // 停止录音并发送
-            ThunderBirdModel::GetInstance()->StopRecording();
+            // ThunderBirdModel::GetInstance()->StopRecording();
             ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING);
-            ThunderBirdModel::GetInstance()->SendRecording();
+            // ThunderBirdModel::GetInstance()->SendRecording();
+            uapi_stop_AI_asr();
         } else {
             // 开始录音
             ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
-            ThunderBirdModel::GetInstance()->StartRecording();
+            // ThunderBirdModel::GetInstance()->StartRecording();
+            uapi_start_AI_asr();
         }
     }
 
index 0cac1e7..00b709b 100644 (file)
@@ -35,7 +35,12 @@ static uint8_t asr_is_ready=0;
 
 tts_ready_status_t tts_is_ready = TTS_READY_NOT_SENT;
 
-/* 外部函数声明 */
+/* 可注册回调:通过管理器注册 */
+static void (*g_ai_question_cb)(char *buf) = NULL;
+static void (*g_ai_answer_cb)(char *buf, uint8_t type) = NULL;
+static void (*g_chat_filter_cb)(char *result) = NULL;
+
+/* 不再使用默认BLE回退,未注册时打印日志 */
 extern void ble_set_ai_Question_str(char *str);
 extern void ble_set_ai_Answer_str(char *str, uint8_t type);
 extern int send_msg_data_into_Ai_msg_queue(void *data, uint16_t len, uint16_t type);
@@ -176,7 +181,7 @@ void handle_asr_data(const ws_event_data_t *event_data)
                 if(data.is_end)
                 {
                     ai_chat_send_txt(0, data.result_text, g_chat_server->client,false);
-                    ble_set_ai_Question_str(data.result_text);
+                    if (g_ai_question_cb) g_ai_question_cb(data.result_text); else printf("[WS][ASR] ai_question 回调未注册,丢弃内容: %s\n", data.result_text);
                 }
 
                 break;
@@ -262,6 +267,11 @@ void handle_chat_data(const ws_event_data_t *event_data)
         // 解析Chat结果
         char buf[512]={0};
         chat_event_type_t ret=chat_result_analysis((char*)event_data->data, buf, 512);
+        if (g_chat_filter_cb) {
+            g_chat_filter_cb(buf);
+        } else {
+            printf("[WS][CHAT] chat_filter_result_chars 未注册,使用原始内容\n");
+        }
         
         // 根据事件类型进行处理
         switch (ret) {
@@ -278,13 +288,13 @@ void handle_chat_data(const ws_event_data_t *event_data)
                 
             case CHAT_EVENT_MIDDLE:
                 printf("Chat event: MIDDLE - Content: %s\n", buf);
-                ble_set_ai_Answer_str(buf, 2);
+                if (g_ai_answer_cb) g_ai_answer_cb(buf, 2); else printf("[WS][CHAT] ai_answer 回调未注册,丢弃内容: %s\n", buf);
                 uapi_tts_process_text(g_tts_server->client,buf,(tts_is_ready == TTS_READY_SUCCESS_READY));
                 break;
                 
             case CHAT_EVENT_END:
                 printf("Chat event: END - Final content: %s\n", buf);
-                ble_set_ai_Answer_str(buf, 2);
+                if (g_ai_answer_cb) g_ai_answer_cb(buf, 2); else printf("[WS][CHAT] ai_answer 回调未注册,丢弃内容: %s\n", buf);
 
                 uapi_tts_process_text(g_tts_server->client,buf,(tts_is_ready == TTS_READY_SUCCESS_READY));
                 uapi_cache_stop_command(g_tts_server->client,(tts_is_ready == TTS_READY_SUCCESS_READY));
@@ -307,6 +317,22 @@ void handle_chat_data(const ws_event_data_t *event_data)
     } 
 }
 
+/* 对外注册接口实现 */
+void ws_register_chat_filter_callback(chat_filter_result_chars_cb_t cb)
+{
+    g_chat_filter_cb = cb;
+}
+
+void ws_register_ai_question_callback(ai_question_cb_t cb)
+{
+    g_ai_question_cb = cb;
+}
+
+void ws_register_ai_answer_callback(ai_answer_cb_t cb)
+{
+    g_ai_answer_cb = cb;
+}
+
 
 /**
  * @brief 提取JSON内容(简化实现)
@@ -521,6 +547,8 @@ errcode_t start_all_websocket_servers(void)
     // ai_media_init();
     old_Start_AIVoice(AIVoiceDataCallback_,nullptr);
     
+    /* 不进行默认回退注册,未注册时仅打印错误日志 */
+
     printf("All WebSocket servers started successfully\n");
     return ERRCODE_SUCC;
 }
index 6c0c2d0..d16e8e1 100644 (file)
@@ -269,6 +269,18 @@ errcode_t ws_server_set_interrupt_flag(ws_server_type_t server_type, uint8_t int
  */
 uint8_t ws_server_get_interrupt_flag(ws_server_type_t server_type);
 
+/* ========================= AI 文本回调注册(新增) ========================= */
+/* 聊天结果过滤回调:可对结果字符串进行原地过滤/修改 */
+typedef void (*chat_filter_result_chars_cb_t)(char *result);
+/* BLE 问题/答案上报回调 */
+typedef void (*ai_question_cb_t)(char *buf);
+typedef void (*ai_answer_cb_t)(char *buf, uint8_t type);
+
+/* 注册接口(线程安全由调用方保证)*/
+void ws_register_chat_filter_callback(chat_filter_result_chars_cb_t cb);
+void ws_register_ai_question_callback(ai_question_cb_t cb);
+void ws_register_ai_answer_callback(ai_answer_cb_t cb);
+
 
 #ifdef __cplusplus
 }
index 9e90539..707256e 100644 (file)
@@ -743,6 +743,7 @@ static uint32_t ln_download_mp3_file_advanced(const char *audio_url, const char
         {
             if (client_data.contentBlockLen > 0)
             {
+                printf("download mp3 file advanced: contentBlockLen=%d\n", client_data.contentBlockLen);
                 #if TEST_MP3_DOWNLOAD
                 /* 一边下载到文件,一边推送到播放器队列,尝试边下边播 */
                 size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
@@ -760,8 +761,18 @@ static uint32_t ln_download_mp3_file_advanced(const char *audio_url, const char
 
                 /* 非阻塞入队,队列满则忽略该块 */
                 //播放下载的音频
-                (void)ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
-
+                int ret = ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
+                if (ret != 0)
+                {
+                    printf("download mp3 file advanced: write failed, ret=%d\n", ret);
+                    // 写失败重新写
+                    LOS_Msleep(100);
+                    ret = ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
+                    if (ret != 0)
+                    {
+                        printf("download mp3 file advanced: write failed, ret=%d\n", ret);
+                    }
+                }
             }
             else
             {
@@ -1124,7 +1135,20 @@ static void ln_http_server_send_task(void const *arg)
         if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN)
         {
             printf("LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN:获取雷鸟设备Token\n");
-            uapi_ln_get_device_token();
+            uint32_t ret = ln_get_device_token_http(uapi_ln_get_device_id(), uapi_ln_get_device_iccid(), uapi_ln_get_device_model(), uapi_ln_get_device_version());
+            if (ret == ERRCODE_SUCC) 
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_HTTP_SERVER_SEND_TASK] 获取雷鸟设备Token成功\n");
+                ret = ln_ws_start(ln_ws_process_message);
+                if (ret != 0)
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_HTTP_SERVER_SEND_TASK] 启动WebSocket失败: %d\n", ret);
+                }
+            } 
+            else 
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[LN_HTTP_SERVER_SEND_TASK] 获取雷鸟设备Token失败\n");
+            }
         }
         else if (mail.cmd == LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM)
         {
@@ -1251,21 +1275,18 @@ static void ln_http_server_recv_task(void const *arg)
             //推送给ui
             if(mail.data)
             {
-                push_text_to_ui(mail.data);
             }
         } else if (mail.cmd == LN_HTTP_RECV_STORY_CHOOSE) {
             tag = "STORY_CHOOSE";
             //推送给ui
             if(mail.data)
             {
-                push_text_to_ui(mail.data);
             }
         } else if (mail.cmd == LN_HTTP_RECV_STORY_RANDOM) {
             tag = "STORY_RANDOM";
             //推送给ui
             if(mail.data)
             {
-                push_text_to_ui(mail.data);
             }
         } else if (mail.cmd == LN_HTTP_RECV_STORY_EXIT) {
             tag = "STORY_EXIT";
@@ -1460,14 +1481,14 @@ errcode_t uapi_ln_http_server_init(void)
         /* 不中断HTTP服务,按需可返回失败 */
     }
 
-    /* 创建WebSocket自动启动任务:每3秒检测一次网络并启动WS */
-    ln_ws_autostart_taskcfg.create_queue_handle = NULL;
-    ln_ws_autostart_taskcfg.attr.name = "ln_ws_autostart_task";
-    ln_ws_autostart_taskcfg.attr.priority = osPriorityNormal;
-    ln_ws_autostart_taskcfg.attr.stack_size = 0x500;
-    ln_ws_autostart_taskcfg.func = ln_ws_autostart_task;
-    ln_ws_autostart_taskcfg.use_mem = USE_EXTEND_MEM;
-    (void)uapi_create_osThread_custom(&ln_ws_autostart_taskcfg);
+    // /* 创建WebSocket自动启动任务:每3秒检测一次网络并启动WS */
+    // ln_ws_autostart_taskcfg.create_queue_handle = NULL;
+    // ln_ws_autostart_taskcfg.attr.name = "ln_ws_autostart_task";
+    // ln_ws_autostart_taskcfg.attr.priority = osPriorityNormal;
+    // ln_ws_autostart_taskcfg.attr.stack_size = 0x1000;
+    // ln_ws_autostart_taskcfg.func = ln_ws_autostart_task;
+    // ln_ws_autostart_taskcfg.use_mem = USE_EXTEND_MEM;
+    // (void)uapi_create_osThread_custom(&ln_ws_autostart_taskcfg);
 
     return ERRCODE_SUCC;
 }