feat(control-plane): trigger cloud draw from SW2 button

This commit is contained in:
chenjintao
2026-08-10 13:53:34 +08:00
parent 07219e6aad
commit 42187ba21d
3 changed files with 60 additions and 7 deletions
@@ -104,6 +104,7 @@ esp_err_t control_plane_multimodal_send_speech_stop(void);
esp_err_t control_plane_multimodal_send_cancel_speech(void);
esp_err_t control_plane_multimodal_send_request_to_respond(
const control_plane_multimodal_respond_request_t *request);
esp_err_t control_plane_request_cloud_chouqian(void);
esp_err_t control_plane_multimodal_send_update_info(
const control_plane_multimodal_update_info_request_t *request);
esp_err_t control_plane_multimodal_send_local_responding_started(void);
@@ -56,6 +56,7 @@ static bool s_multimodal_watchdog_stop_requested;
static bool s_multimodal_watchdog_task_starting;
static bool s_model_command_dispatched;
static bool s_server_success_prompt_played;
static bool s_cloud_chouqian_pending;
static control_plane_model_command_callback_t s_model_command_cb;
static void *s_model_command_cb_user_data;
static portMUX_TYPE s_multimodal_runtime_lock = portMUX_INITIALIZER_UNLOCKED;
@@ -160,6 +161,22 @@ static void control_plane_set_model_command_dispatched(bool dispatched)
portEXIT_CRITICAL(&s_multimodal_runtime_lock);
}
static void control_plane_clear_cloud_chouqian_pending(const char *reason)
{
bool was_pending = false;
portENTER_CRITICAL(&s_multimodal_runtime_lock);
was_pending = s_cloud_chouqian_pending;
s_cloud_chouqian_pending = false;
portEXIT_CRITICAL(&s_multimodal_runtime_lock);
if (was_pending) {
ESP_LOGI(TAG,
"Cloud chouqian request completed: %s",
reason != NULL ? reason : "unknown");
}
}
static void control_plane_set_model_command_callback(control_plane_model_command_callback_t cb,
void *user_data)
{
@@ -226,6 +243,9 @@ static void control_plane_responding_text_bridge(const char *text,
value,
(unsigned int)value_index,
value_index_valid ? 1 : 0);
if (command_type == CONTROL_PLANE_MODEL_COMMAND_CHOUQIAN) {
ESP_LOGI(TAG, "Cloud chouqian result received: %s", value);
}
cb(command_type, value, value_index, value_index_valid, cb_user_data);
}
@@ -359,6 +379,32 @@ esp_err_t control_plane_multimodal_request_to_respond(
return control_plane_multimodal_send_request_to_respond(request);
}
esp_err_t control_plane_request_cloud_chouqian(void)
{
portENTER_CRITICAL(&s_multimodal_runtime_lock);
if (s_cloud_chouqian_pending) {
portEXIT_CRITICAL(&s_multimodal_runtime_lock);
return ESP_ERR_INVALID_STATE;
}
s_cloud_chouqian_pending = true;
s_model_command_dispatched = false;
portEXIT_CRITICAL(&s_multimodal_runtime_lock);
const control_plane_multimodal_respond_request_t request = {
.type = CONTROL_PLANE_MULTIMODAL_RESPOND_TYPE_PROMPT,
.text = "我要抽签",
.parameters_json = NULL,
};
esp_err_t err = control_plane_multimodal_send_request_to_respond(&request);
if (err != ESP_OK) {
control_plane_clear_cloud_chouqian_pending("request send failed");
return err;
}
ESP_LOGI(TAG, "Cloud chouqian prompt sent");
return ESP_OK;
}
esp_err_t control_plane_multimodal_update_info(
const control_plane_multimodal_update_info_request_t *request)
{
@@ -499,14 +545,17 @@ static void control_plane_multimodal_event_bridge(control_plane_multimodal_event
}
case CONTROL_PLANE_MULTIMODAL_EVENT_TRANSPORT_DISCONNECTED:
control_plane_clear_cloud_chouqian_pending("transport disconnected");
control_plane_multimodal_stop_uplink();
break;
case CONTROL_PLANE_MULTIMODAL_EVENT_TRANSPORT_ERROR:
control_plane_clear_cloud_chouqian_pending("transport error");
control_plane_multimodal_stop_uplink();
break;
case CONTROL_PLANE_MULTIMODAL_EVENT_TASK_FAILED:
control_plane_clear_cloud_chouqian_pending("task failed");
control_plane_request_server_error_expression(DOMAIN_EXPRESSION_TRIGGER_SERVER_TASK_FAILED);
control_plane_multimodal_stop_uplink();
break;
@@ -530,6 +579,7 @@ static void control_plane_multimodal_event_bridge(control_plane_multimodal_event
}
case CONTROL_PLANE_MULTIMODAL_EVENT_RESPONDING_ENDED:
control_plane_clear_cloud_chouqian_pending("response ended");
break;
case CONTROL_PLANE_MULTIMODAL_EVENT_SPEECH_STARTED:
@@ -537,6 +587,7 @@ static void control_plane_multimodal_event_bridge(control_plane_multimodal_event
break;
case CONTROL_PLANE_MULTIMODAL_EVENT_OUTPUT_ERROR:
control_plane_clear_cloud_chouqian_pending("output error");
control_plane_request_server_error_expression(DOMAIN_EXPRESSION_TRIGGER_SERVER_OUTPUT_ERROR);
break;
@@ -601,6 +652,7 @@ esp_err_t control_plane_start_multimodal_client(void)
void control_plane_stop_multimodal_client(void)
{
control_plane_clear_cloud_chouqian_pending("multimodal client stopped");
stop_watchdog_task();
control_plane_multimodal_stop();
}
@@ -129,13 +129,13 @@ static void control_plane_dispatch_key_event(const control_plane_key_event_t *ev
if (event->key_id == CONTROL_PLANE_KEY_ID_SW2) {
if (event->type == CONTROL_PLANE_KEY_EVENT_SHORT_PRESS) {
const domain_expression_request_t request = {
.id = DOMAIN_EXPRESSION_CHOUQIAN,
.trigger = DOMAIN_EXPRESSION_TRIGGER_SW2_SINGLE_CLICK,
};
esp_err_t expr_err = domain_runtime_request_expression(&request);
if (expr_err != ESP_OK && expr_err != ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "SW2 single-click chouqian expression failed: %s", esp_err_to_name(expr_err));
esp_err_t request_err = control_plane_request_cloud_chouqian();
if (request_err == ESP_ERR_INVALID_STATE) {
ESP_LOGI(TAG, "Cloud chouqian request skipped: multimodal session unavailable or request pending");
} else if (request_err != ESP_OK) {
ESP_LOGW(TAG,
"Cloud chouqian request failed: %s",
esp_err_to_name(request_err));
}
}
if (event->type == CONTROL_PLANE_KEY_EVENT_DOUBLE_CLICK) {