修复了WS连接稳定性问题
This commit is contained in:
+145
-6
@@ -119,6 +119,8 @@
|
||||
static const char *TAG = "cp_mm_session";
|
||||
|
||||
static bool s_started;
|
||||
static bool s_starting;
|
||||
static bool s_stopping;
|
||||
|
||||
static control_plane_multimodal_auth_info_t s_auth;
|
||||
static char s_task_id[40];
|
||||
@@ -167,6 +169,7 @@ static StaticSemaphore_t s_state_mutex_buf;
|
||||
typedef enum {
|
||||
LOCAL_RESPONDING_EVENT_STARTED = 0,
|
||||
LOCAL_RESPONDING_EVENT_ENDED,
|
||||
LOCAL_RESPONDING_EVENT_QUIT,
|
||||
} local_responding_event_type_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -418,6 +421,8 @@ static const char *transport_loss_reason_name(control_plane_transport_loss_reaso
|
||||
return "listening_timeout";
|
||||
case CONTROL_PLANE_TRANSPORT_LOSS_NO_RESPONSE_TIMEOUT:
|
||||
return "no_response_timeout";
|
||||
case CONTROL_PLANE_TRANSPORT_LOSS_PROTOCOL_ERROR:
|
||||
return "protocol_error";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@@ -444,6 +449,8 @@ void control_plane_multimodal_mark_transport_unavailable(
|
||||
|
||||
if (lock_state()) {
|
||||
s_started = false;
|
||||
s_starting = false;
|
||||
s_stopping = false;
|
||||
s_transport_available = false;
|
||||
memset(&s_auth, 0, sizeof(s_auth));
|
||||
reset_session_state_locked();
|
||||
@@ -451,6 +458,19 @@ void control_plane_multimodal_mark_transport_unavailable(
|
||||
}
|
||||
|
||||
control_plane_multimodal_stop_uplink();
|
||||
|
||||
bool close_transport = reason == CONTROL_PLANE_TRANSPORT_LOSS_PROTOCOL_ERROR ||
|
||||
reason == CONTROL_PLANE_TRANSPORT_LOSS_SEND_TEXT_FAILURE ||
|
||||
reason == CONTROL_PLANE_TRANSPORT_LOSS_LISTENING_TIMEOUT ||
|
||||
reason == CONTROL_PLANE_TRANSPORT_LOSS_NO_RESPONSE_TIMEOUT;
|
||||
if (close_transport) {
|
||||
esp_err_t stop_err = domain_runtime_multimodal_transport_stop(0);
|
||||
if (stop_err != ESP_OK) {
|
||||
ESP_LOGW(TAG,
|
||||
"Async transport stop after unavailable ended with %s",
|
||||
esp_err_to_name(stop_err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_session_state(void)
|
||||
@@ -523,7 +543,19 @@ static void local_responding_event_worker(void *arg)
|
||||
idle_ticks = 1;
|
||||
}
|
||||
if (xQueueReceive(s_local_responding_event_queue, &msg, idle_ticks) != pdTRUE) {
|
||||
s_local_responding_event_task = NULL;
|
||||
if (lock_state()) {
|
||||
s_local_responding_event_task = NULL;
|
||||
unlock_state();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.type == LOCAL_RESPONDING_EVENT_QUIT) {
|
||||
if (lock_state()) {
|
||||
s_local_responding_event_task = NULL;
|
||||
unlock_state();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
@@ -594,6 +626,50 @@ static esp_err_t ensure_local_responding_event_worker(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void stop_local_responding_event_worker(void)
|
||||
{
|
||||
QueueHandle_t queue = NULL;
|
||||
TaskHandle_t task = NULL;
|
||||
if (lock_state()) {
|
||||
queue = s_local_responding_event_queue;
|
||||
task = s_local_responding_event_task;
|
||||
s_local_responding_started_send_pending = false;
|
||||
s_local_responding_ended_send_pending = false;
|
||||
unlock_state();
|
||||
}
|
||||
|
||||
if (queue != NULL && task != NULL) {
|
||||
local_responding_event_msg_t quit = {
|
||||
.type = LOCAL_RESPONDING_EVENT_QUIT,
|
||||
};
|
||||
(void)xQueueSend(queue, &quit, 0);
|
||||
TickType_t start_tick = xTaskGetTickCount();
|
||||
TickType_t wait_ticks = pdMS_TO_TICKS(300);
|
||||
if (wait_ticks == 0) {
|
||||
wait_ticks = 1;
|
||||
}
|
||||
while ((xTaskGetTickCount() - start_tick) < wait_ticks) {
|
||||
bool running = false;
|
||||
if (lock_state()) {
|
||||
running = s_local_responding_event_task != NULL;
|
||||
unlock_state();
|
||||
}
|
||||
if (!running) {
|
||||
break;
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
}
|
||||
|
||||
if (lock_state()) {
|
||||
s_local_responding_event_task = NULL;
|
||||
if (s_local_responding_event_queue != NULL) {
|
||||
xQueueReset(s_local_responding_event_queue);
|
||||
}
|
||||
unlock_state();
|
||||
}
|
||||
}
|
||||
|
||||
static void queue_local_responding_event(local_responding_event_type_t type)
|
||||
{
|
||||
char task_id[sizeof(s_task_id)] = {0};
|
||||
@@ -1198,7 +1274,12 @@ static void process_text_json(const char *json_text)
|
||||
request_id,
|
||||
dialog_id[0] ? dialog_id : "-");
|
||||
|
||||
if (cJSON_IsString(failed_task_id) &&
|
||||
bool protocol_error = strcmp(error_code, "InvalidParameter") == 0 ||
|
||||
strcmp(error_name, "InvalidParameter") == 0 ||
|
||||
strstr(error_message, "Invalid action") != NULL;
|
||||
|
||||
if (!protocol_error &&
|
||||
cJSON_IsString(failed_task_id) &&
|
||||
failed_task_id->valuestring != NULL &&
|
||||
failed_task_id->valuestring[0] != '\0') {
|
||||
bool matches_active_task = false;
|
||||
@@ -1218,7 +1299,13 @@ static void process_text_json(const char *json_text)
|
||||
}
|
||||
|
||||
stop_local_downstream_playback();
|
||||
reset_session_state_if_task_matches(task_id);
|
||||
if (protocol_error) {
|
||||
control_plane_multimodal_mark_transport_unavailable(
|
||||
CONTROL_PLANE_TRANSPORT_LOSS_PROTOCOL_ERROR,
|
||||
__func__);
|
||||
} else {
|
||||
reset_session_state_if_task_matches(task_id);
|
||||
}
|
||||
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_TASK_FAILED);
|
||||
} else if (strcmp(event->valuestring, "task-started") == 0) {
|
||||
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_TASK_STARTED);
|
||||
@@ -1378,8 +1465,10 @@ static void process_text_json(const char *json_text)
|
||||
cJSON *error_message = cJSON_GetObjectItemCaseSensitive(output, "error_message");
|
||||
cJSON *llm_request_id = cJSON_GetObjectItemCaseSensitive(output, "llm_request_id");
|
||||
char dialog_id[sizeof(s_dialog_id)] = {0};
|
||||
char task_id[sizeof(s_task_id)] = {0};
|
||||
if (lock_state()) {
|
||||
s_remote_responding = false;
|
||||
strlcpy(task_id, s_task_id, sizeof(task_id));
|
||||
strlcpy(dialog_id, s_dialog_id, sizeof(dialog_id));
|
||||
unlock_state();
|
||||
}
|
||||
@@ -1390,6 +1479,11 @@ static void process_text_json(const char *json_text)
|
||||
cJSON_IsString(error_message) && error_message->valuestring ? error_message->valuestring : "unknown",
|
||||
cJSON_IsString(llm_request_id) && llm_request_id->valuestring ? llm_request_id->valuestring : "-",
|
||||
dialog_id[0] ? dialog_id : "-");
|
||||
control_plane_multimodal_stop_uplink();
|
||||
stop_local_downstream_playback();
|
||||
control_plane_multimodal_mark_transport_unavailable(
|
||||
CONTROL_PLANE_TRANSPORT_LOSS_PROTOCOL_ERROR,
|
||||
__func__);
|
||||
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_OUTPUT_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -1409,6 +1503,9 @@ static void transport_event_bridge(const domain_multimodal_transport_event_t *ev
|
||||
switch (event->type) {
|
||||
case DOMAIN_MULTIMODAL_TRANSPORT_EVENT_CONNECTED:
|
||||
if (lock_state()) {
|
||||
s_started = true;
|
||||
s_starting = false;
|
||||
s_stopping = false;
|
||||
s_transport_available = true;
|
||||
s_last_heartbeat_tick = xTaskGetTickCount();
|
||||
s_last_downstream_tick = s_last_heartbeat_tick;
|
||||
@@ -1538,17 +1635,29 @@ esp_err_t control_plane_multimodal_start(void)
|
||||
#endif
|
||||
|
||||
if (lock_state()) {
|
||||
bool already_started = s_started;
|
||||
unlock_state();
|
||||
bool already_started = s_started || s_auth.token[0] != '\0';
|
||||
bool starting = s_starting;
|
||||
bool stopping = s_stopping;
|
||||
if (already_started) {
|
||||
unlock_state();
|
||||
return ESP_OK;
|
||||
}
|
||||
if (starting || stopping) {
|
||||
unlock_state();
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_starting = true;
|
||||
unlock_state();
|
||||
}
|
||||
|
||||
control_plane_multimodal_auth_info_t auth = {0};
|
||||
esp_err_t err = control_plane_multimodal_auth_fetch(&auth);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Auth fetch failed: %s", esp_err_to_name(err));
|
||||
if (lock_state()) {
|
||||
s_starting = false;
|
||||
unlock_state();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1557,6 +1666,10 @@ esp_err_t control_plane_multimodal_start(void)
|
||||
NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Register downstream playback callback failed: %s", esp_err_to_name(err));
|
||||
if (lock_state()) {
|
||||
s_starting = false;
|
||||
unlock_state();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1564,12 +1677,15 @@ esp_err_t control_plane_multimodal_start(void)
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Transport start failed: %s", esp_err_to_name(err));
|
||||
(void)domain_runtime_multimodal_audio_register_downstream_playback_callback(NULL, NULL);
|
||||
if (lock_state()) {
|
||||
s_starting = false;
|
||||
unlock_state();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
if (lock_state()) {
|
||||
s_auth = auth;
|
||||
s_started = true;
|
||||
unlock_state();
|
||||
}
|
||||
return ESP_OK;
|
||||
@@ -1577,7 +1693,22 @@ esp_err_t control_plane_multimodal_start(void)
|
||||
|
||||
void control_plane_multimodal_stop(void)
|
||||
{
|
||||
bool already_stopping = false;
|
||||
if (lock_state()) {
|
||||
already_stopping = s_stopping;
|
||||
if (!s_stopping) {
|
||||
s_stopping = true;
|
||||
}
|
||||
s_starting = false;
|
||||
unlock_state();
|
||||
}
|
||||
if (already_stopping) {
|
||||
ESP_LOGI(TAG, "Multimodal stop already in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
control_plane_multimodal_stop_uplink();
|
||||
stop_local_responding_event_worker();
|
||||
(void)control_plane_multimodal_register_downstream_audio_callback(NULL, NULL);
|
||||
(void)control_plane_multimodal_register_event_callback(NULL, NULL);
|
||||
(void)domain_runtime_multimodal_audio_register_downstream_playback_callback(NULL, NULL);
|
||||
@@ -1589,6 +1720,9 @@ void control_plane_multimodal_stop(void)
|
||||
|
||||
if (lock_state()) {
|
||||
s_started = false;
|
||||
s_starting = false;
|
||||
s_stopping = false;
|
||||
s_transport_available = false;
|
||||
memset(&s_auth, 0, sizeof(s_auth));
|
||||
reset_session_state_locked();
|
||||
unlock_state();
|
||||
@@ -2123,6 +2257,8 @@ esp_err_t control_plane_multimodal_get_runtime_state(control_plane_multimodal_ru
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
out_state->connected = transport_available_locked();
|
||||
out_state->starting = s_starting;
|
||||
out_state->stopping = s_stopping;
|
||||
out_state->has_active_task = s_task_id[0] != '\0';
|
||||
out_state->server_listening = s_server_listening;
|
||||
out_state->remote_responding = s_remote_responding;
|
||||
@@ -2227,6 +2363,9 @@ esp_err_t control_plane_multimodal_start_uplink(void)
|
||||
|
||||
void control_plane_multimodal_stop_uplink(void)
|
||||
{
|
||||
if (!domain_runtime_multimodal_audio_is_uplink_running()) {
|
||||
return;
|
||||
}
|
||||
esp_err_t err = domain_runtime_multimodal_audio_stop_uplink(CONTROL_PLANE_UPLINK_READY_WAIT_MS);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Mic uplink stop ended with %s", esp_err_to_name(err));
|
||||
|
||||
Reference in New Issue
Block a user