From 815918c99d05684ad76fd62264b8e1cf7a24cba4 Mon Sep 17 00:00:00 2001 From: chenjintao Date: Mon, 21 Sep 2026 16:33:19 +0800 Subject: [PATCH] fix: ensure OTA prompt plays before upgrade --- .../threadx/interface/custom_app/mp3_player.c | 24 ++++---- .../threadx/interface/custom_app/mqtt.c | 27 ++++++-- .../interface/custom_app/ws_talkingq.c | 61 +++++++++++++++++-- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/ql-application/threadx/interface/custom_app/mp3_player.c b/ql-application/threadx/interface/custom_app/mp3_player.c index be5046a..d11092a 100644 --- a/ql-application/threadx/interface/custom_app/mp3_player.c +++ b/ql-application/threadx/interface/custom_app/mp3_player.c @@ -280,10 +280,11 @@ u32 local_mp3_data_fetch(const char *uri, uint8_t *buffer, u32 length) size_t url_mp3_data_fetch(const char *uri, uint8_t *buffer, size_t length) { - int resp_status = -1; - uint32_t nw = length; - uint32_t page_pos = 0; - int error_cnt = 0; + int resp_status = -1; + uint32_t nw = length; + uint32_t page_pos = 0; + uint32_t content_length = 0; + int error_cnt = 0; //printf("fd_fetch start\n"); session = webclient_session_create(1024); @@ -306,11 +307,12 @@ size_t url_mp3_data_fetch(const char *uri, uint8_t *buffer, size_t length) goto __exit; } - if (session->content_length == 0) - { - printf("Request file size is 0!"); - goto __exit; - } + if (session->content_length == 0) + { + printf("Request file size is 0!"); + goto __exit; + } + content_length = session->content_length; printf("start read\n"); if(total_length < session->content_length) @@ -325,7 +327,7 @@ size_t url_mp3_data_fetch(const char *uri, uint8_t *buffer, size_t length) page_pos = 0; do { - if(vad_audio_is_recording()) { + if(vad_audio_is_recording() || tts_playing_ret()==2) { break; } @@ -361,7 +363,7 @@ __exit: session = NULL; } - if(total_lengthcontent_length){ + if(total_length 0) { + ql_rtos_task_sleep_ms(OTA_PROMPT_POLL_MS); + if (hal_os_up_time_ms() - prompt_start_time > OTA_PROMPT_PLAY_TIMEOUT_MS) { + RLOGE("OTA prompt playback timeout, counter=%d", + xiaoice_get_play_counter()); + break; + } + } + if (xiaoice_get_play_counter() == 0) { + printf("OTA prompt playback completed\r\n"); + } + } /* Product requirement: keep deleting the configured audio files before OTA. */ app_file_check_del(); diff --git a/ql-application/threadx/interface/custom_app/ws_talkingq.c b/ql-application/threadx/interface/custom_app/ws_talkingq.c index 47abe9c..65c1d41 100644 --- a/ql-application/threadx/interface/custom_app/ws_talkingq.c +++ b/ql-application/threadx/interface/custom_app/ws_talkingq.c @@ -49,7 +49,7 @@ static int16 *ppbuff=mp3_buff; static int onmessage_status = -1; volatile int tts_playing = 0; unsigned char wss_connect_start = 0; -static int player_mq_couter = 0; +static volatile int player_mq_couter = 0; static unsigned char audio_in_task_cancel = 0; static unsigned char xiaoice_wss_connect_status = 0; @@ -105,6 +105,11 @@ static librws_app_t app = &_app; static ql_sem_t ws_connect_sem = NULL; extern int fota_start; +#define OTA_AUDIO_STOP_TIMEOUT_MS 3000 +#define OTA_AUDIO_STOP_POLL_MS 20 + +void xiaoice_clear_player_mq(void); + static int tts_play_status = 0;//1播放中 2播放完成 @@ -234,8 +239,13 @@ void add_file_to_play_player_queue(char *path, int type) //如果录音后 超过10s 还没有收到信息 提示本轮对话结束 -static void onmessage_text(rws_socket socket, const char *text, const unsigned int len) -{ +static void onmessage_text(rws_socket socket, const char *text, const unsigned int len) +{ + if (fota_start == 1) { + printf("ignore websocket audio during OTA\r\n"); + return; + } + // printf("message(txt), %d(byte): %s ", len, text); char url_buff[128]={0x00}; @@ -820,6 +830,49 @@ int app_play_tips_file(int index) return 0; } +int app_play_ota_tips_file(void) +{ + char filename_buff[64] = {0}; + uint32_t timeout; + + /* OTA owns the audio path from this point on. Stop the active conversation + * before queuing the prompt, otherwise recording/TTS rejects or masks it. */ + if (vad_audio_is_recording()) { + vad_audio_stop_record(); + } + + if (get_xiaoice_connected_status() == 2) { + talkingq_ws_disconnect(); + } + + tts_playing = 2; + xiaoice_clear_player_mq(); + + timeout = hal_os_up_time_ms(); + while (player_mq_couter > 0) { + ql_rtos_task_sleep_ms(OTA_AUDIO_STOP_POLL_MS); + if (hal_os_up_time_ms() - timeout > OTA_AUDIO_STOP_TIMEOUT_MS) { + printf("OTA wait previous audio timeout, counter:%d\r\n", + player_mq_couter); + return -3; + } + } + + tts_play_status = 0; + tts_playing = 0; + + /* Normal prompts are blocked while fota_start is set. Queue the dedicated + * OTA prompt directly after the old conversation has fully stopped. */ + snprintf(filename_buff, sizeof(filename_buff), "U:/%s", mp3_file[3]); + printf("xiaoice_play_index:3\n"); + if (ql_access(filename_buff, 0) != 0) { + return -2; + } + + add_file_to_play_player_queue(filename_buff, 0); + return player_mq_couter > 0 ? 0 : -1; +} + void app_player_thread(void *arvg) { ice_work_item *player_item=NULL; @@ -1044,12 +1097,12 @@ void xiaoice_clear_player_mq(void) free(player_item->data); player_item->data = NULL; } + if(player_mq_couter>0) player_mq_couter--; free(player_item); player_item = NULL; } } - player_mq_couter=0; } void xiaoice_close_all_audio(void)