AI语音优化:
authorluozheng <1732036298@qq.com>
Wed, 16 Oct 2024 10:40:12 +0000 (18:40 +0800)
committerluozheng <1732036298@qq.com>
Wed, 16 Oct 2024 10:40:12 +0000 (18:40 +0800)
1.添加AI查询的定时器与AI思考中定时器分离
2.删除AIModel中无用代码

code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp
code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AivoiceChatContentListAdapter.cpp

index 0ea1520..e3e25d4 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com
  * @Date: 2024-06-20 15:14:43
  * @LastEditors: luozheng 1732036298@qq.com
- * @LastEditTime: 2024-10-15 19:03:35
+ * @LastEditTime: 2024-10-16 18:26:13
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/include/AiVoiceModel.h
  */
 #ifndef AI_VOICE_MODEL_H
@@ -42,7 +42,6 @@ namespace OHOS
         bool ChangeToAIVoiceConnectTimeoutView();
         void FunctionKeyOnClickToChangeAIModel(void);
         // 初始化和状态管理
-        bool CreateIfNotExists();
         void StatusResume(void);
 
         bool IsExistOpenAIAPIKeys();
@@ -81,8 +80,6 @@ namespace OHOS
 
         // 文件检查和AI状态管理
         void CheckFileAndSendAIIsReady();
-        bool GetEntryTimeoutFlag(void);
-        void SetEntryTimeoutFlag(bool flag);
 
         // AI录音路径管理
         std::string GetAIAudioPath(void);
@@ -102,6 +99,8 @@ namespace OHOS
         void start_listening_timer(uint32_t interval = 1000);
         void stop_listening_timer(void);
 
+        void start_ai_isready_timer(uint32_t interval = 1000);
+        void stop_ai_isready_timer(void);
 
         void SetSelectAiModel(int index);
         int GetSelectAiModel(void);
@@ -125,7 +124,6 @@ namespace OHOS
 #endif
         std::string userQuestionStr;                                         // 用户提出的问题
         std::string aiAnswerStr;                                             // AI回答的问题
-        bool entryTimeoutFlag{false};                                        // 进入超时界面标志
         uint8_t ChatContentListCount{0};                                     // 列表数量
         static const uint16_t MaxChatContentListCount = 2;                   // 对话列表最大数量
         ChatContentItem chatTtems[MaxChatContentListCount] = {0, "", false}; // 对话项数组
index 1ef125c..b3bcdc6 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com
  * @Date: 2024-06-20 15:14:50
  * @LastEditors: luozheng 1732036298@qq.com
- * @LastEditTime: 2024-10-16 10:46:11
+ * @LastEditTime: 2024-10-16 18:36:51
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp
  */
 #include "aivoice/include/AiVoiceModel.h"
@@ -84,11 +84,11 @@ namespace OHOS
     /*跳转到AI聆听界面界面*/
     bool AiVoiceModel::ChangeToAIVoiceListeningView(bool value)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::ChangeToReturnResultTextView");
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::ChangeToAIVoiceListeningView");
         AiVoicePresenter *Aipresenter_ = AiVoicePresenter::GetInstance();
         if (Aipresenter_ == nullptr)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::ChangeToReturnResultTextView fail!!");
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::ChangeToAIVoiceListeningView fail!!");
             return false;
         }
         Aipresenter_->ChangeToAIVoiceListeningView(value);
@@ -123,33 +123,6 @@ namespace OHOS
         return;
     }
 
-    /*如果文件不存在就创建*/
-    bool AiVoiceModel::CreateIfNotExists()
-    {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::CreateIfNotExists");
-        const std::string filePath = "/user/userdata/AiRecording/AIAudio.pcm";
-        // Check if file exists
-        FILE *file = fopen(filePath.c_str(), "r");
-        if (file != nullptr)
-        {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File already exists: %s", filePath.c_str());
-            fclose(file);
-            return false;
-        }
-
-        // File does not exist, create it
-        file = fopen(filePath.c_str(), "w");
-        if (file == nullptr)
-        {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create file: %s", filePath.c_str());
-            return false;
-        }
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File created: %s", filePath.c_str());
-        fclose(file);
-
-        return true;
-    }
-
     /*获取API Keys是否可用*/
     bool AiVoiceModel::IsExistOpenAIAPIKeys()
     {
@@ -184,26 +157,13 @@ namespace OHOS
         return false;
     }
 
-    // 获取与AI模型的连接状态
-    bool AiVoiceModel::GetAiVoiceConnectStatus(void)
-    {
-        return AiVoiceConnectStatus;
-    }
-
-    // 设置与AI模型的连接状态
-    void AiVoiceModel::SetAiVoiceConnectStatus(bool state)
-    {
-        AiVoiceConnectStatus = state;
-    }
-
     /*查询用户选择的AI模型是否已经连接*/
     void AiVoiceModel::QuerySelectedAiModelIsConnect()
     {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::QuerySelectedAiModelIsConnect");
         auto it = selectAiModelToTextId.find(GetSelectAiModel());
         if (it != selectAiModelToTextId.end())
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SelectAiModel = %d", it->second.second);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[QuerySelectedAiModelIsConnect] SelectAiModel = %d", it->second.second);
             inquire_AI_is_ready(it->second.second);
         }
     }
@@ -478,10 +438,6 @@ namespace OHOS
         /* -------------------------------------------------------------------------- */
         userQuestionStr += str;
         /* -------------------------------------------------------------------------- */
-        // if (!UpdateUserQuestionStr())
-        // {
-        //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateUserQuestionStr fail!!");
-        // }
         SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0);
     }
 
@@ -496,18 +452,7 @@ namespace OHOS
     /*设置Ai回答的字符串*/
     void AiVoiceModel::SetAiAnswerStrStr(std::string str)
     {
-        // if (!entryTextViewState)
-        // {
-        //     SendMsgToUIService(UI_AI_RESPONSE_USERDATA, 0, nullptr, 0);
-        //     entryTextViewState = true; //进入返回结果界面的标志  避免重复发消息
-        // }
-        /* -------------------------------------------------------------------------- */
         aiAnswerStr += str;
-        /* -------------------------------------------------------------------------- */
-        // if (!UpdateAiAnswerStr())
-        // {
-        //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateAiAnswerStr fail!!");
-        // }
         SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
     }
 
@@ -523,9 +468,9 @@ namespace OHOS
             SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)errnote.c_str(), errnote.length());
             return;
         }
-        else if(AiVoiceModel::AI_RESPONSE_END) //如果是AI 回应结束
+        else if (AiVoiceModel::AI_RESPONSE_END) // 如果是AI 回应结束
         {
-            if(errnote.empty()) //如果没有回应数据
+            if (errnote.empty()) // 如果没有回应数据
             {
                 WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::GetErrnote is empty!!");
                 AiVoiceModel::GetInstance().SetErrnote("response data is empty");
@@ -548,7 +493,6 @@ namespace OHOS
     /*获取AI音频路径*/
     std::string AiVoiceModel::GetAIAudioPath(void)
     {
-        // CreateIfNotExists();
         return AIAIAudioPath;
     }
 
@@ -643,16 +587,6 @@ namespace OHOS
         }
     }
 
-    bool AiVoiceModel::GetEntryTimeoutFlag(void)
-    {
-        return entryTimeoutFlag;
-    }
-
-    void AiVoiceModel::SetEntryTimeoutFlag(bool flag)
-    {
-        entryTimeoutFlag = flag;
-    }
-
     void AiVoiceModel::StatusResume(void)
     {
         Time = THIRTY_TIME;
@@ -667,8 +601,6 @@ namespace OHOS
         }
         ChatContentListCount = 0;
         entryTextViewState = false;
-        entryTimeoutFlag = false;
-        AIVoice_StopTimer();
         ClearQuestionAndAiAnswerStr();
         StopListenAndRecordingUserQuestion();
     }
@@ -677,54 +609,30 @@ namespace OHOS
     /*定时器到期时的处理*/
     static void AIVoice_TimerCallbackProc(int data)
     {
-        if (!AiVoiceModel::GetInstance().GetAiVoiceConnectStatus()) // 查询AI模型是否可用的定时器
+        // 等待AI思考完成的定时器
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AIVoice_TimerCallbackProc,Time = %d", Time);
+        if (Time == 30) // 等待一秒,确保录音停止,发送录音准备就绪指令
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AIVoice_TimerCallbackProc,AiModelConnectTimeout = %d", AiModelConnectTimeout);
-            AiModelConnectTimeout--;
-            if (AiModelConnectTimeout < 0) // 模型连接失败有5秒超时
-            {
-                AiVoiceModel::GetInstance().AIVoice_StopTimer();
-                AiVoiceView *view_ = AiVoiceView::GetInstance();
-                AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance();
-                if (view_ != nullptr && p_AiVoicePresenter != nullptr)
-                {
-                    if ((view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr) &&
-                        (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible()))
-                    {
-                        p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
-                    }
-                }
-            }
+            AiVoiceModel::GetInstance().CheckFileAndSendAIIsReady();
         }
-        else // 等待AI思考完成的定时器
+        if (Time < 0) // 如果思考时间超时30s,进入连接超时界面
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AIVoice_TimerCallbackProc,Time = %d", Time);
-            Time -= 1;
-            if (Time == 30) //等待一秒,确保录音停止,发送录音准备就绪指令
-            {
-                AiVoiceModel::GetInstance().CheckFileAndSendAIIsReady();
-                // AiVoiceModel::GetInstance().AIVoice_StopTimer();
-                // return;
-            }
-            if (Time < 0) // 如果思考时间超时30s,进入连接超时界面
+            AiVoiceModel::GetInstance().AIVoice_StopTimer();
+            AiVoiceModel::GetInstance().SetErrnote("The connection timed out. Please restart the conversation");
+            std::string str = AiVoiceModel::GetInstance().GetErrnote();
+            SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
+        }
+        else
+        {
+            // 4g中途断连待扩展
+
+            // 蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等
+            if (get_ble_connect() == false)
             {
-                AiVoiceModel::GetInstance().AIVoice_StopTimer();
-                AiVoiceModel::GetInstance().SetErrnote("The connection timed out. Please restart the conversation");
+                AiVoiceModel::GetInstance().SetErrnote("ble is disconnected");
                 std::string str = AiVoiceModel::GetInstance().GetErrnote();
                 SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
             }
-            else
-            {
-                //4g中途断连待扩展
-                
-                //蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等
-                if(get_ble_connect() == false)
-                {
-                    AiVoiceModel::GetInstance().SetErrnote("ble is disconnected");
-                    std::string str = AiVoiceModel::GetInstance().GetErrnote();
-                    SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
-                }
-            }
         }
         return;
     }
@@ -734,6 +642,7 @@ namespace OHOS
      */
     static void AIVoice_TimerCallback(int data)
     {
+        Time -= 1;
         GraphicService::GetInstance()->PostGraphicEvent(std::bind(AIVoice_TimerCallbackProc, data));
     }
 
@@ -802,7 +711,7 @@ namespace OHOS
 
     // 声明定时器变量
     static osTimerId_t g_screen60s_timer = nullptr;
-    static uint16_t SCREEN_60S_TIME = 60;
+    static uint16_t SCREEN_60S_TIME = 60; // 60s
 
     static void ai_start_screen60s_timer_callbackProc(int data)
     {
@@ -890,9 +799,9 @@ namespace OHOS
         LISTENING_TIMEOUT--;
         if (LISTENING_TIMEOUT <= 0)
         {
-            AiVoiceModel::GetInstance().StopListenAndRecordingUserQuestion(); //停止聆听用户问题
-            AiVoiceModel::GetInstance().stop_listening_timer(); //停止聆听定时器
-            if (AiVoiceView::GetInstance() && AivoiceListeningView::GetInstance() )
+            AiVoiceModel::GetInstance().StopListenAndRecordingUserQuestion(); // 停止聆听用户问题
+            AiVoiceModel::GetInstance().stop_listening_timer();               // 停止聆听定时器
+            if (AiVoiceView::GetInstance() && AivoiceListeningView::GetInstance())
             {
                 AiVoiceView::GetInstance()->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 切换到思考中界面
                 AiVoiceModel::GetInstance().AIVoice_StartTimer();
@@ -906,6 +815,7 @@ namespace OHOS
                 AivoiceListeningView::GetInstance()->GetShowtimeoutLabel()->Invalidate();
             }
         }
+        return;
     }
     static void AIListeningCallback(int data)
     {
@@ -945,7 +855,7 @@ namespace OHOS
             return;
         }
     }
-    
+
     // 停止一个AI录音的定时器
     void AiVoiceModel::stop_listening_timer(void)
     {
@@ -964,6 +874,88 @@ namespace OHOS
             LISTENING_TIMEOUT = 15;
         }
     }
+
+    static osTimerId_t g_ai_is_ready_Handle = nullptr; // 处理查询AI是否就绪定时器
+    static uint8_t AI_IS_READY_TIMEOUT = 5; // 5s钟超时
+    static void AI_IS_READY_CallbackProc(int data)
+    {
+        if (AI_IS_READY_TIMEOUT <= 0) // 模型连接失败有5秒超时
+        {
+            AiVoiceModel::GetInstance().stop_ai_isready_timer();
+            AiVoiceView *view_ = AiVoiceView::GetInstance();
+            AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance();
+            if (view_ != nullptr && p_AiVoicePresenter != nullptr)
+            {
+                if ((view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr) &&
+                    (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible()))
+                {
+                    p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
+                }
+            }
+        }
+        return;
+    }
+    static void AI_IS_READY_Callback(int data)
+    {
+        AI_IS_READY_TIMEOUT--;
+        GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI_IS_READY_CallbackProc, data));
+    }
+
+    // 开启一个查询AI是否准备就绪的定时器
+    void AiVoiceModel::start_ai_isready_timer(uint32_t interval)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai_isready_timer");
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
+        if (g_ai_is_ready_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+            return;
+        }
+        /* --------------------------------- 2.创建定时器 -------------------------------- */
+        g_ai_is_ready_Handle = osTimerNew((osTimerFunc_t)AI_IS_READY_Callback, osTimerPeriodic, nullptr, nullptr);
+        // 检查定时器创建是否成功
+        if (g_ai_is_ready_Handle == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+            return;
+        }
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */
+        int tick = osMs2Tick(interval);
+        /* --------------------------------- 4.启动定时器 -------------------------------- */
+        osStatus_t ret = osTimerStart(g_ai_is_ready_Handle, tick);
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */
+        if (ret != osOK)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            if (g_ai_is_ready_Handle != nullptr)
+            {
+                ret = osTimerDelete(g_ai_is_ready_Handle);
+            }
+            g_ai_is_ready_Handle = nullptr;
+            return;
+        }
+        return;
+    }
+
+    // 停止一个查询AI是否准备就绪的定时器
+    void AiVoiceModel::stop_ai_isready_timer(void)
+    {
+        // 检查定时器是否存在
+        if (g_ai_is_ready_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::stop_ai_isready_timer");
+            osTimerStop(g_ai_is_ready_Handle);
+            // 删除定时器并置为 nullptr
+            osStatus_t ret = osTimerDelete(g_ai_is_ready_Handle);
+            if (ret != osOK)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            }
+            g_ai_is_ready_Handle = nullptr;
+            AI_IS_READY_TIMEOUT = 5;
+        }
+    }
+
     // 设置选择的ai模型
     void AiVoiceModel::SetSelectAiModel(int index)
     {
index f9428d0..6ae30d7 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com
  * @Date: 2024-06-20 15:11:17
  * @LastEditors: luozheng 1732036298@qq.com
- * @LastEditTime: 2024-10-16 15:13:54
+ * @LastEditTime: 2024-10-16 18:29:25
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoicePresenter.cpp
  */
 #include "AppViewIDs.h"
@@ -88,8 +88,10 @@ namespace OHOS
         Presenter<AiVoiceView>::OnStop();
         ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
         model->StatusResume();
+        model->AIVoice_StopTimer();
         model->ai_stop_screen60s_timer();
         model->stop_listening_timer();
+        model->stop_ai_isready_timer();
 
         uapi_ble_connect_param_update(50);
     }
@@ -116,8 +118,7 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeToAIVoiceListeningView");
         if (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr && view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible())
         {
-            model->AIVoice_StopTimer(); // 停止定时器
-            model->SetAiVoiceConnectStatus(val);
+            model->stop_ai_isready_timer();// 停止定时器
             if (val) /*如果查询的AI模型可用跳转到聆听中界面*/
             {
                 ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_LISTENING_VIEWID);
@@ -214,7 +215,7 @@ namespace OHOS
             }
             else if (showView == AIVOICE_AIMODE_CONNECTING)
             {
-                model->AIVoice_StartTimer(); /*开启一个查询AI模型是否连接成功定时器*/
+                model->start_ai_isready_timer();/*开启一个查询AI模型是否连接成功定时器*/
             }
             break;
 
@@ -230,8 +231,6 @@ namespace OHOS
             model->stop_listening_timer();
             if (showView == AIVOICE_THINKING_VIEWID) // 聆听中->思考中界面
             {
-                // osal_msleep(500);
-                // model->CheckFileAndSendAIIsReady();
                 model->AIVoice_StartTimer();
             }
             break;
@@ -323,12 +322,7 @@ namespace OHOS
             else if (appBluetoothConnectState) // 3.只有与APP蓝牙连接正常
             {
                 // 通过蓝牙连接APP调用大模型
-#ifdef DISABLE_AI_VALID_QUERY
-                ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_LISTENING_VIEWID);
-                model->SetAiVoiceConnectStatus(true);
-#else
                 ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING
-#endif
             }
             else // 4.两者连接都异常
             {
index 2fd95d1..3789381 100644 (file)
@@ -2,7 +2,7 @@
  * @Author: luozheng 1732036298@qq.com
  * @Date: 2024-03-28 14:27:05
  * @LastEditors: luozheng 1732036298@qq.com
- * @LastEditTime: 2024-10-05 10:20:15
+ * @LastEditTime: 2024-10-16 18:31:00
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/language/src/AivoiceChatContentListAdapter.cpp
  */
 #include "aivoice/include/AivoiceChatContentListAdapter.h"
@@ -116,6 +116,7 @@ namespace OHOS
             item = dynamic_cast<AivoiceChatContentListItemView *>(inView);
             item->ResetItemView(itemViewHeight, aiAnswerFlag);
         }
+        item->SetViewIndex(index);
         item->SetItemInfo(itemData);
         return item;
     }