diff --git a/main/application.cc b/main/application.cc index c21da702..a94653b1 100644 --- a/main/application.cc +++ b/main/application.cc @@ -51,69 +51,88 @@ void Application::CheckNewVersion() { // Check if there is a new firmware version available ota_.SetPostData(board.GetJson()); + const int MAX_RETRY = 10; + int retry_count = 0; + while (true) { - if (ota_.CheckVersion()) { - if (ota_.HasNewVersion()) { - Alert("OTA 升级", "正在升级系统", "happy", std::string_view(p3_upgrade_start, p3_upgrade_end - p3_upgrade_start)); - // Wait for the chat state to be idle - do { - vTaskDelay(pdMS_TO_TICKS(3000)); - } while (GetDeviceState() != kDeviceStateIdle); - - // Use main task to do the upgrade, not cancelable - Schedule([this, &board, display]() { - SetDeviceState(kDeviceStateUpgrading); - - display->SetIcon(FONT_AWESOME_DOWNLOAD); - display->SetChatMessage("system", "新版本 " + ota_.GetFirmwareVersion()); - - board.SetPowerSaveMode(false); -#if CONFIG_USE_AUDIO_PROCESSING - wake_word_detect_.StopDetection(); -#endif - // 预先关闭音频输出,避免升级过程有音频操作 - auto codec = board.GetAudioCodec(); - codec->EnableInput(false); - codec->EnableOutput(false); - { - std::lock_guard lock(mutex_); - audio_decode_queue_.clear(); - } - background_task_->WaitForCompletion(); - delete background_task_; - background_task_ = nullptr; - vTaskDelay(pdMS_TO_TICKS(1000)); - - ota_.StartUpgrade([display](int progress, size_t speed) { - char buffer[64]; - snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024); - display->SetChatMessage("system", buffer); - }); - - // If upgrade success, the device will reboot and never reach here - display->SetStatus("更新失败"); - ESP_LOGI(TAG, "Firmware upgrade failed..."); - vTaskDelay(pdMS_TO_TICKS(3000)); - Reboot(); - }); - } else { - ota_.MarkCurrentVersionValid(); - display->ShowNotification("版本 " + ota_.GetCurrentVersion()); - - // Check if the activation code is valid - if (ota_.HasActivationCode()) { - SetDeviceState(kDeviceStateActivating); - ShowActivationCode(); - } else { - SetDeviceState(kDeviceStateIdle); - display->SetChatMessage("system", ""); - return; - } + if (!ota_.CheckVersion()) { + retry_count++; + if (retry_count >= MAX_RETRY) { + ESP_LOGE(TAG, "版本检查失败次数过多,退出检查"); + return; } + ESP_LOGW(TAG, "版本检查失败,%d秒后重试 (%d/%d)", 60, retry_count, MAX_RETRY); + vTaskDelay(pdMS_TO_TICKS(60000)); + continue; + } + retry_count = 0; + + if (ota_.HasNewVersion()) { + Alert("OTA 升级", "正在升级系统", "happy", std::string_view(p3_upgrade_start, p3_upgrade_end - p3_upgrade_start)); + // Wait for the chat state to be idle + do { + vTaskDelay(pdMS_TO_TICKS(3000)); + } while (GetDeviceState() != kDeviceStateIdle); + + // Use main task to do the upgrade, not cancelable + Schedule([this, display]() { + SetDeviceState(kDeviceStateUpgrading); + + display->SetIcon(FONT_AWESOME_DOWNLOAD); + display->SetChatMessage("system", "新版本 " + ota_.GetFirmwareVersion()); + + auto& board = Board::GetInstance(); + board.SetPowerSaveMode(false); +#if CONFIG_USE_AUDIO_PROCESSING + wake_word_detect_.StopDetection(); +#endif + // 预先关闭音频输出,避免升级过程有音频操作 + auto codec = board.GetAudioCodec(); + codec->EnableInput(false); + codec->EnableOutput(false); + { + std::lock_guard lock(mutex_); + audio_decode_queue_.clear(); + } + background_task_->WaitForCompletion(); + delete background_task_; + background_task_ = nullptr; + vTaskDelay(pdMS_TO_TICKS(1000)); + + ota_.StartUpgrade([display](int progress, size_t speed) { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "%d%% %zuKB/s", progress, speed / 1024); + display->SetChatMessage("system", buffer); + }); + + // If upgrade success, the device will reboot and never reach here + display->SetStatus("更新失败"); + ESP_LOGI(TAG, "Firmware upgrade failed..."); + vTaskDelay(pdMS_TO_TICKS(3000)); + Reboot(); + }); + + return; } - // Check again in 60 seconds - vTaskDelay(pdMS_TO_TICKS(60000)); + // No new version, mark the current version as valid + ota_.MarkCurrentVersionValid(); + display->ShowNotification("版本 " + ota_.GetCurrentVersion()); + + if (ota_.HasActivationCode()) { + // Activation code is valid + SetDeviceState(kDeviceStateActivating); + ShowActivationCode(); + // Check again in 60 seconds + vTaskDelay(pdMS_TO_TICKS(60000)); + continue; + } + + SetDeviceState(kDeviceStateIdle); + display->SetChatMessage("system", ""); + + // Exit the loop if upgrade or idle + break; } } @@ -199,7 +218,7 @@ void Application::ToggleChatState() { if (device_state_ == kDeviceStateIdle) { SetDeviceState(kDeviceStateConnecting); if (!protocol_->OpenAudioChannel()) { - Alert("ERROR", "无法建立音频通道"); + Alert("ERROR", "无法建立音频通道", "sad"); SetDeviceState(kDeviceStateIdle); return; } @@ -233,7 +252,7 @@ void Application::StartListening() { SetDeviceState(kDeviceStateConnecting); if (!protocol_->OpenAudioChannel()) { SetDeviceState(kDeviceStateIdle); - Alert("ERROR", "无法建立音频通道"); + Alert("ERROR", "无法建立音频通道", "sad"); return; } } @@ -314,7 +333,7 @@ void Application::Start() { protocol_ = std::make_unique(); #endif protocol_->OnNetworkError([this](const std::string& message) { - Alert("ERROR", message); + Alert("ERROR", message, "sad"); }); protocol_->OnIncomingAudio([this](std::vector&& data) { std::lock_guard lock(mutex_); @@ -401,6 +420,7 @@ void Application::Start() { } } }); + protocol_->Start(); // Check for new firmware version or get the MQTT broker address ota_.SetCheckVersionUrl(CONFIG_OTA_VERSION_URL); diff --git a/main/protocols/mqtt_protocol.cc b/main/protocols/mqtt_protocol.cc index 1f8f78c0..669be3d2 100644 --- a/main/protocols/mqtt_protocol.cc +++ b/main/protocols/mqtt_protocol.cc @@ -13,8 +13,6 @@ MqttProtocol::MqttProtocol() { event_group_handle_ = xEventGroupCreate(); - - StartMqttClient(); } MqttProtocol::~MqttProtocol() { @@ -28,6 +26,10 @@ MqttProtocol::~MqttProtocol() { vEventGroupDelete(event_group_handle_); } +void MqttProtocol::Start() { + StartMqttClient(); +} + bool MqttProtocol::StartMqttClient() { if (mqtt_ != nullptr) { ESP_LOGW(TAG, "Mqtt client already started"); @@ -98,7 +100,12 @@ void MqttProtocol::SendText(const std::string& text) { if (publish_topic_.empty()) { return; } - mqtt_->Publish(publish_topic_, text); + if (!mqtt_->Publish(publish_topic_, text)) { + ESP_LOGE(TAG, "Failed to publish message"); + if (on_network_error_ != nullptr) { + on_network_error_("发送失败,请检查网络"); + } + } } void MqttProtocol::SendAudio(const std::vector& data) { diff --git a/main/protocols/mqtt_protocol.h b/main/protocols/mqtt_protocol.h index 7fd46cd1..5f3938e9 100644 --- a/main/protocols/mqtt_protocol.h +++ b/main/protocols/mqtt_protocol.h @@ -25,6 +25,7 @@ public: MqttProtocol(); ~MqttProtocol(); + void Start() override; void SendAudio(const std::vector& data) override; bool OpenAudioChannel() override; void CloseAudioChannel() override; diff --git a/main/protocols/protocol.h b/main/protocols/protocol.h index faa8a94d..5328368d 100644 --- a/main/protocols/protocol.h +++ b/main/protocols/protocol.h @@ -40,6 +40,7 @@ public: void OnAudioChannelClosed(std::function callback); void OnNetworkError(std::function callback); + virtual void Start() = 0; virtual bool OpenAudioChannel() = 0; virtual void CloseAudioChannel() = 0; virtual bool IsAudioChannelOpened() const = 0; diff --git a/main/protocols/websocket_protocol.cc b/main/protocols/websocket_protocol.cc index 1c2e6895..4964dbc0 100644 --- a/main/protocols/websocket_protocol.cc +++ b/main/protocols/websocket_protocol.cc @@ -21,6 +21,9 @@ WebsocketProtocol::~WebsocketProtocol() { vEventGroupDelete(event_group_handle_); } +void WebsocketProtocol::Start() { +} + void WebsocketProtocol::SendAudio(const std::vector& data) { if (websocket_ == nullptr) { return; diff --git a/main/protocols/websocket_protocol.h b/main/protocols/websocket_protocol.h index 5629e8af..0d4c2bb9 100644 --- a/main/protocols/websocket_protocol.h +++ b/main/protocols/websocket_protocol.h @@ -15,6 +15,7 @@ public: WebsocketProtocol(); ~WebsocketProtocol(); + void Start() override; void SendAudio(const std::vector& data) override; bool OpenAudioChannel() override; void CloseAudioChannel() override; diff --git a/sdkconfig.defaults b/sdkconfig.defaults index fc581e2a..0a512fb1 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -17,6 +17,7 @@ ESP_TASK_WDT_TIMEOUT_S=10 CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 CONFIG_MBEDTLS_DYNAMIC_BUFFER=y CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=n CONFIG_ESP_WIFI_IRAM_OPT=n