wangzhibo
2026-09-11 659c470eba542383987aad227b7f918100f131fa
xiaozhi-esp32-2.2.6/main/protocols/websocket_protocol.cc
@@ -8,6 +8,7 @@
#include <cJSON.h>
#include <esp_log.h>
#include <arpa/inet.h>
#include <freertos/task.h>
#include "assets/lang_config.h"
#define TAG "WS"
@@ -71,8 +72,14 @@
    return true;
}
bool WebsocketProtocol::IsAudioChannelConnected() const {
    return websocket_ != nullptr && websocket_->IsConnected() && !error_occurred_;
}
bool WebsocketProtocol::IsAudioChannelOpened() const {
    return websocket_ != nullptr && websocket_->IsConnected() && !error_occurred_ && !IsTimeout();
    // Local MP3 can idle the websocket for minutes. Treat a live socket as open
    // so detect/TTS reuse it instead of tearing it down and handshake-timing-out.
    return IsAudioChannelConnected();
}
void WebsocketProtocol::CloseAudioChannel(bool send_goodbye) {
@@ -81,6 +88,18 @@
}
bool WebsocketProtocol::OpenAudioChannel() {
    Board::GetInstance().SetPowerSaveLevel(PowerSaveLevel::PERFORMANCE);
    if (IsAudioChannelConnected()) {
        MarkIncomingActivity();
        ESP_LOGI(TAG, "Reuse existing websocket channel");
        return true;
    }
    // MODEM 从 MAX_MODEM 切回 NONE 不是瞬时完成的。立刻握手会
    // WebSocket handshake timeout,开机欢迎词和复读结束后回 chat 都会失败。
    vTaskDelay(pdMS_TO_TICKS(400));
    Settings settings("websocket", false);
    std::string url = settings.GetString("url");
    std::string token = settings.GetString("token");
@@ -186,7 +205,7 @@
    }
    // Wait for server hello
    EventBits_t bits = xEventGroupWaitBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000));
    EventBits_t bits = xEventGroupWaitBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(20000));
    if (!(bits & WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT)) {
        ESP_LOGE(TAG, "Failed to receive server hello");
        SetError(Lang::Strings::SERVER_TIMEOUT);