fix(multimodal): protect voice startup from background uploads

This commit is contained in:
chenjintao
2026-08-14 18:23:46 +08:00
parent 451d989e78
commit 609fe978f1
4 changed files with 85 additions and 6 deletions
@@ -233,6 +233,19 @@ static void local_wake_service_ready_prompt(void)
runtime.request_to_speak_pending ? 1 : 0,
runtime.client_speech_active ? 1 : 0,
runtime.ptt_release_required ? 1 : 0);
bool incomplete_task_start = runtime.connected &&
runtime.has_active_task &&
!runtime.server_listening &&
!runtime.remote_responding &&
!runtime.request_to_speak_pending &&
!runtime.client_speech_active;
if (incomplete_task_start) {
esp_err_t stop_err = control_plane_multimodal_send_stop(
"LocalWakeListeningTimeout");
ESP_LOGW(TAG,
"Local wake timed-out task cleanup: result=%s",
esp_err_to_name(stop_err));
}
control_plane_set_ptt_active(false);
return;
}
@@ -148,6 +148,7 @@ static bool s_remote_responding_ended;
static bool s_request_to_speak_pending;
static bool s_client_speech_active;
static bool s_ptt_release_required;
static bool s_response_pending;
static bool s_local_responding_started;
static bool s_local_responding_ended_sent;
static bool s_downstream_playback_completed;
@@ -437,6 +438,7 @@ static void reset_session_state_locked(void)
s_request_to_speak_pending = false;
s_client_speech_active = false;
s_ptt_release_required = false;
s_response_pending = false;
s_local_responding_started = false;
s_local_responding_ended_sent = false;
s_downstream_playback_completed = false;
@@ -1307,6 +1309,8 @@ static void process_text_json(const char *json_text)
cJSON *header = cJSON_GetObjectItemCaseSensitive(root, "header");
cJSON *event = header ? cJSON_GetObjectItemCaseSensitive(header, "event") : NULL;
cJSON *message_task_id = header ?
cJSON_GetObjectItemCaseSensitive(header, "task_id") : NULL;
cJSON *payload = cJSON_GetObjectItemCaseSensitive(root, "payload");
cJSON *output = payload ? cJSON_GetObjectItemCaseSensitive(payload, "output") : NULL;
cJSON *output_event = output ? cJSON_GetObjectItemCaseSensitive(output, "event") : NULL;
@@ -1390,23 +1394,42 @@ static void process_text_json(const char *json_text)
}
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_TASK_FAILED);
} else if (strcmp(event->valuestring, "task-started") == 0) {
ESP_LOGI(TAG, "Cloud task started");
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_TASK_STARTED);
}
}
if (cJSON_IsString(output_event) && output_event->valuestring != NULL) {
if (strcmp(output_event->valuestring, "Started") == 0) {
ESP_LOGI(TAG, "Cloud task started (output event)");
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_TASK_STARTED);
} else if (strcmp(output_event->valuestring, "DialogStateChanged") == 0 &&
cJSON_IsString(state) && state->valuestring != NULL) {
if (strcmp(state->valuestring, "Listening") == 0) {
bool accepted = false;
if (lock_state()) {
s_server_listening = true;
s_remote_responding = false;
s_remote_responding_ended = false;
s_request_to_speak_pending = false;
accepted = s_task_id[0] != '\0' &&
(!cJSON_IsString(message_task_id) ||
message_task_id->valuestring == NULL ||
strcmp(s_task_id, message_task_id->valuestring) == 0);
if (accepted) {
s_server_listening = true;
s_remote_responding = false;
s_remote_responding_ended = false;
s_request_to_speak_pending = false;
}
unlock_state();
}
if (!accepted) {
ESP_LOGW(TAG,
"Ignore stale Listening event for task_id=%s",
cJSON_IsString(message_task_id) &&
message_task_id->valuestring != NULL ?
message_task_id->valuestring : "-");
cJSON_Delete(root);
return;
}
ESP_LOGI(TAG, "Cloud dialog entered Listening");
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_SERVER_LISTENING);
} else {
if (lock_state()) {
@@ -1424,6 +1447,7 @@ static void process_text_json(const char *json_text)
s_request_to_speak_pending = false;
s_client_speech_active = false;
s_ptt_release_required = false;
s_response_pending = false;
s_drop_downstream_audio = false;
unlock_state();
}
@@ -1431,6 +1455,7 @@ static void process_text_json(const char *json_text)
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_SERVER_LISTENING);
} else if (strcmp(output_event->valuestring, "RespondingStarted") == 0) {
if (lock_state()) {
s_response_pending = false;
s_remote_responding = true;
s_remote_responding_ended = false;
s_local_responding_ended_sent = false;
@@ -1517,6 +1542,7 @@ static void process_text_json(const char *json_text)
s_request_to_speak_pending = false;
s_client_speech_active = false;
s_ptt_release_required = false;
s_response_pending = false;
s_local_responding_started = false;
s_downstream_playback_completed = false;
s_drop_downstream_audio = false;
@@ -1530,6 +1556,7 @@ static void process_text_json(const char *json_text)
notify_event(CONTROL_PLANE_MULTIMODAL_EVENT_SERVER_NOT_LISTENING);
} else if (strcmp(output_event->valuestring, "SpeechStarted") == 0) {
if (lock_state()) {
s_response_pending = false;
s_last_asr_text_len = 0;
unlock_state();
}
@@ -1553,6 +1580,7 @@ static void process_text_json(const char *json_text)
control_plane_multimodal_stop_uplink();
if (lock_state()) {
s_ptt_release_required = s_client_speech_active;
s_response_pending = true;
unlock_state();
}
ESP_LOGI(TAG, "ASR ended");
@@ -2026,6 +2054,7 @@ esp_err_t control_plane_multimodal_send_start(void)
s_request_to_speak_pending = false;
s_client_speech_active = false;
s_ptt_release_required = false;
s_response_pending = false;
unlock_state();
cJSON *root = cJSON_CreateObject();
@@ -2276,6 +2305,7 @@ esp_err_t control_plane_multimodal_send_speech_start(void)
if (err == ESP_OK && lock_state()) {
s_client_speech_active = true;
s_ptt_release_required = false;
s_response_pending = false;
s_request_to_speak_pending = false;
unlock_state();
}
@@ -2305,6 +2335,9 @@ esp_err_t control_plane_multimodal_send_speech_stop(void)
if (lock_state()) {
s_client_speech_active = false;
s_ptt_release_required = false;
if (err == ESP_OK && has_active_task) {
s_response_pending = true;
}
s_request_to_speak_pending = false;
unlock_state();
}
@@ -2339,6 +2372,7 @@ esp_err_t control_plane_multimodal_send_cancel_speech(void)
if (err == ESP_OK && lock_state()) {
s_client_speech_active = false;
s_ptt_release_required = false;
s_response_pending = false;
s_request_to_speak_pending = false;
unlock_state();
}
@@ -2520,6 +2554,7 @@ esp_err_t control_plane_multimodal_get_runtime_state(control_plane_multimodal_ru
out_state->request_to_speak_pending = s_request_to_speak_pending;
out_state->client_speech_active = s_client_speech_active;
out_state->ptt_release_required = s_ptt_release_required;
out_state->response_pending = s_response_pending;
out_state->local_responding_started = s_local_responding_started;
out_state->received_downstream_audio = s_received_downstream_audio;
out_state->last_heartbeat_ms = tick_to_ms(s_last_heartbeat_tick);