feat(control-plane): show listening ui for ptt button
This commit is contained in:
@@ -161,6 +161,7 @@ void control_plane_stop_key_input_task(void);
|
|||||||
void control_plane_reset_wifi_provisioning_and_restart(void);
|
void control_plane_reset_wifi_provisioning_and_restart(void);
|
||||||
esp_err_t control_plane_schedule_websocket_wait_task(void);
|
esp_err_t control_plane_schedule_websocket_wait_task(void);
|
||||||
void control_plane_set_ptt_active(bool active);
|
void control_plane_set_ptt_active(bool active);
|
||||||
|
void control_plane_set_ptt_active_from_local_wake(void);
|
||||||
esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason);
|
esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason);
|
||||||
|
|
||||||
esp_err_t control_plane_remote_log_start(void);
|
esp_err_t control_plane_remote_log_start(void);
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ typedef struct {
|
|||||||
bool capture_owned;
|
bool capture_owned;
|
||||||
bool prompt_pending;
|
bool prompt_pending;
|
||||||
bool prompt_playing;
|
bool prompt_playing;
|
||||||
bool listening_ui_active;
|
|
||||||
TickType_t prompt_wait_started_tick;
|
TickType_t prompt_wait_started_tick;
|
||||||
uint32_t detection_generation;
|
uint32_t detection_generation;
|
||||||
} local_wake_state_t;
|
} local_wake_state_t;
|
||||||
@@ -88,21 +87,6 @@ static void local_wake_set_capture_owned(bool owned)
|
|||||||
portEXIT_CRITICAL(&s_local_wake_lock);
|
portEXIT_CRITICAL(&s_local_wake_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void local_wake_request_expression(domain_expression_id_t id)
|
|
||||||
{
|
|
||||||
const domain_expression_request_t request = {
|
|
||||||
.id = id,
|
|
||||||
.trigger = DOMAIN_EXPRESSION_TRIGGER_LOCAL_WAKE,
|
|
||||||
};
|
|
||||||
esp_err_t err = domain_runtime_request_expression(&request);
|
|
||||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
|
||||||
ESP_LOGW(TAG,
|
|
||||||
"Local wake expression request failed: id=%d err=%s",
|
|
||||||
(int)id,
|
|
||||||
esp_err_to_name(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool control_plane_local_wake_prompt_gate_active(void)
|
bool control_plane_local_wake_prompt_gate_active(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_TQ_LOCAL_WAKE_ENABLE && CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE
|
#if CONFIG_TQ_LOCAL_WAKE_ENABLE && CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE
|
||||||
@@ -315,7 +299,6 @@ static void local_wake_handle_detection(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s_local_wake.paused_for_foreground = true;
|
s_local_wake.paused_for_foreground = true;
|
||||||
s_local_wake.listening_ui_active = true;
|
|
||||||
s_local_wake.detection_generation = event->detection_generation;
|
s_local_wake.detection_generation = event->detection_generation;
|
||||||
#if CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE
|
#if CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_ENABLE
|
||||||
s_local_wake.prompt_pending = CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_FILE[0] != '\0';
|
s_local_wake.prompt_pending = CONFIG_TQ_LOCAL_WAKE_RESPONSE_PROMPT_FILE[0] != '\0';
|
||||||
@@ -324,7 +307,6 @@ static void local_wake_handle_detection(
|
|||||||
#endif
|
#endif
|
||||||
portEXIT_CRITICAL(&s_local_wake_lock);
|
portEXIT_CRITICAL(&s_local_wake_lock);
|
||||||
|
|
||||||
local_wake_request_expression(DOMAIN_EXPRESSION_LISTENING);
|
|
||||||
ESP_LOGI(TAG,
|
ESP_LOGI(TAG,
|
||||||
"Local wake foreground entered: generation=%u listening_ui=1 prompt_gate=%d ready_timeout_ms=%u",
|
"Local wake foreground entered: generation=%u listening_ui=1 prompt_gate=%d ready_timeout_ms=%u",
|
||||||
(unsigned)event->detection_generation,
|
(unsigned)event->detection_generation,
|
||||||
@@ -340,7 +322,7 @@ static void local_wake_handle_detection(
|
|||||||
(unsigned)event->confidence_x10000,
|
(unsigned)event->confidence_x10000,
|
||||||
(unsigned)event->detection_generation);
|
(unsigned)event->detection_generation);
|
||||||
|
|
||||||
control_plane_set_ptt_active(true);
|
control_plane_set_ptt_active_from_local_wake();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void local_wake_task(void *arg)
|
static void local_wake_task(void *arg)
|
||||||
@@ -437,7 +419,6 @@ esp_err_t control_plane_local_wake_start(void)
|
|||||||
s_local_wake.capture_owned = false;
|
s_local_wake.capture_owned = false;
|
||||||
s_local_wake.prompt_pending = false;
|
s_local_wake.prompt_pending = false;
|
||||||
s_local_wake.prompt_playing = false;
|
s_local_wake.prompt_playing = false;
|
||||||
s_local_wake.listening_ui_active = false;
|
|
||||||
s_local_wake.prompt_wait_started_tick = 0U;
|
s_local_wake.prompt_wait_started_tick = 0U;
|
||||||
s_local_wake.detection_generation = 0U;
|
s_local_wake.detection_generation = 0U;
|
||||||
s_local_wake.started = true;
|
s_local_wake.started = true;
|
||||||
@@ -532,19 +513,13 @@ void control_plane_local_wake_pause_for_foreground(void)
|
|||||||
void control_plane_local_wake_resume_after_foreground(void)
|
void control_plane_local_wake_resume_after_foreground(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_TQ_LOCAL_WAKE_ENABLE
|
#if CONFIG_TQ_LOCAL_WAKE_ENABLE
|
||||||
bool restore_idle_ui = false;
|
|
||||||
portENTER_CRITICAL(&s_local_wake_lock);
|
portENTER_CRITICAL(&s_local_wake_lock);
|
||||||
s_local_wake.paused_for_foreground = false;
|
s_local_wake.paused_for_foreground = false;
|
||||||
s_local_wake.prompt_pending = false;
|
s_local_wake.prompt_pending = false;
|
||||||
s_local_wake.prompt_playing = false;
|
s_local_wake.prompt_playing = false;
|
||||||
s_local_wake.prompt_wait_started_tick = 0U;
|
s_local_wake.prompt_wait_started_tick = 0U;
|
||||||
restore_idle_ui = s_local_wake.listening_ui_active;
|
|
||||||
s_local_wake.listening_ui_active = false;
|
|
||||||
TaskHandle_t task = s_local_wake.task;
|
TaskHandle_t task = s_local_wake.task;
|
||||||
portEXIT_CRITICAL(&s_local_wake_lock);
|
portEXIT_CRITICAL(&s_local_wake_lock);
|
||||||
if (restore_idle_ui) {
|
|
||||||
local_wake_request_expression(DOMAIN_EXPRESSION_IDLE);
|
|
||||||
}
|
|
||||||
if (task != NULL) {
|
if (task != NULL) {
|
||||||
xTaskNotifyGive(task);
|
xTaskNotifyGive(task);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,8 @@ typedef struct {
|
|||||||
bool pending_press_after_teardown;
|
bool pending_press_after_teardown;
|
||||||
bool start_action_sent;
|
bool start_action_sent;
|
||||||
bool speech_action_sent;
|
bool speech_action_sent;
|
||||||
|
bool listening_ui_active;
|
||||||
|
domain_expression_trigger_t listening_ui_trigger;
|
||||||
} ptt_runtime_t;
|
} ptt_runtime_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -552,7 +554,27 @@ static void control_plane_notify_wifi_state_task(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void control_plane_set_ptt_active(bool active)
|
static void control_plane_request_ptt_expression(
|
||||||
|
domain_expression_id_t id,
|
||||||
|
domain_expression_trigger_t trigger)
|
||||||
|
{
|
||||||
|
const domain_expression_request_t request = {
|
||||||
|
.id = id,
|
||||||
|
.trigger = trigger,
|
||||||
|
};
|
||||||
|
esp_err_t err = domain_runtime_request_expression(&request);
|
||||||
|
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||||
|
ESP_LOGW(TAG,
|
||||||
|
"PTT expression request failed: id=%d trigger=%d err=%s",
|
||||||
|
(int)id,
|
||||||
|
(int)trigger,
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void control_plane_set_ptt_active_with_trigger(
|
||||||
|
bool active,
|
||||||
|
domain_expression_trigger_t listening_ui_trigger)
|
||||||
{
|
{
|
||||||
if (active) {
|
if (active) {
|
||||||
control_plane_local_wake_pause_for_foreground();
|
control_plane_local_wake_pause_for_foreground();
|
||||||
@@ -563,6 +585,9 @@ void control_plane_set_ptt_active(bool active)
|
|||||||
uint32_t generation = 0;
|
uint32_t generation = 0;
|
||||||
const char *transition_reason = active ? "press" : "release";
|
const char *transition_reason = active ? "press" : "release";
|
||||||
bool uplink_running = !active && control_plane_multimodal_is_uplink_running();
|
bool uplink_running = !active && control_plane_multimodal_is_uplink_running();
|
||||||
|
bool request_listening_ui = false;
|
||||||
|
bool restore_idle_ui = false;
|
||||||
|
domain_expression_trigger_t expression_trigger = listening_ui_trigger;
|
||||||
portENTER_CRITICAL(&s_runtime_lock);
|
portENTER_CRITICAL(&s_runtime_lock);
|
||||||
old_state = s_ptt_runtime.state;
|
old_state = s_ptt_runtime.state;
|
||||||
s_ptt_active = active;
|
s_ptt_active = active;
|
||||||
@@ -575,6 +600,9 @@ void control_plane_set_ptt_active(bool active)
|
|||||||
s_ptt_runtime.foreground_attempts = 0;
|
s_ptt_runtime.foreground_attempts = 0;
|
||||||
s_ptt_runtime.start_action_sent = false;
|
s_ptt_runtime.start_action_sent = false;
|
||||||
s_ptt_runtime.speech_action_sent = false;
|
s_ptt_runtime.speech_action_sent = false;
|
||||||
|
s_ptt_runtime.listening_ui_active = true;
|
||||||
|
s_ptt_runtime.listening_ui_trigger = listening_ui_trigger;
|
||||||
|
request_listening_ui = true;
|
||||||
if (s_ptt_runtime.state == PTT_STATE_TEARDOWN_LOCAL ||
|
if (s_ptt_runtime.state == PTT_STATE_TEARDOWN_LOCAL ||
|
||||||
s_ptt_runtime.state == PTT_STATE_TEARDOWN_REMOTE) {
|
s_ptt_runtime.state == PTT_STATE_TEARDOWN_REMOTE) {
|
||||||
s_ptt_runtime.pending_press_after_teardown = true;
|
s_ptt_runtime.pending_press_after_teardown = true;
|
||||||
@@ -589,6 +617,9 @@ void control_plane_set_ptt_active(bool active)
|
|||||||
s_ptt_runtime.foreground_attempts = 0;
|
s_ptt_runtime.foreground_attempts = 0;
|
||||||
s_ptt_runtime.pending_press_after_teardown = false;
|
s_ptt_runtime.pending_press_after_teardown = false;
|
||||||
s_ptt_runtime.generation++;
|
s_ptt_runtime.generation++;
|
||||||
|
restore_idle_ui = s_ptt_runtime.listening_ui_active;
|
||||||
|
expression_trigger = s_ptt_runtime.listening_ui_trigger;
|
||||||
|
s_ptt_runtime.listening_ui_active = false;
|
||||||
if (uplink_running || s_ptt_runtime.state == PTT_STATE_STREAMING) {
|
if (uplink_running || s_ptt_runtime.state == PTT_STATE_STREAMING) {
|
||||||
control_plane_ptt_transition_locked(PTT_STATE_TEARDOWN_LOCAL, "release_streaming");
|
control_plane_ptt_transition_locked(PTT_STATE_TEARDOWN_LOCAL, "release_streaming");
|
||||||
transition_reason = "release_streaming";
|
transition_reason = "release_streaming";
|
||||||
@@ -608,6 +639,15 @@ void control_plane_set_ptt_active(bool active)
|
|||||||
generation = s_ptt_runtime.generation;
|
generation = s_ptt_runtime.generation;
|
||||||
portEXIT_CRITICAL(&s_runtime_lock);
|
portEXIT_CRITICAL(&s_runtime_lock);
|
||||||
control_plane_ptt_log_transition(old_state, new_state, generation, transition_reason);
|
control_plane_ptt_log_transition(old_state, new_state, generation, transition_reason);
|
||||||
|
if (request_listening_ui) {
|
||||||
|
control_plane_request_ptt_expression(
|
||||||
|
DOMAIN_EXPRESSION_LISTENING,
|
||||||
|
expression_trigger);
|
||||||
|
} else if (restore_idle_ui) {
|
||||||
|
control_plane_request_ptt_expression(
|
||||||
|
DOMAIN_EXPRESSION_IDLE,
|
||||||
|
expression_trigger);
|
||||||
|
}
|
||||||
if (notify_worker) {
|
if (notify_worker) {
|
||||||
control_plane_notify_wifi_state_task();
|
control_plane_notify_wifi_state_task();
|
||||||
}
|
}
|
||||||
@@ -616,6 +656,20 @@ void control_plane_set_ptt_active(bool active)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void control_plane_set_ptt_active(bool active)
|
||||||
|
{
|
||||||
|
control_plane_set_ptt_active_with_trigger(
|
||||||
|
active,
|
||||||
|
DOMAIN_EXPRESSION_TRIGGER_PTT_BUTTON);
|
||||||
|
}
|
||||||
|
|
||||||
|
void control_plane_set_ptt_active_from_local_wake(void)
|
||||||
|
{
|
||||||
|
control_plane_set_ptt_active_with_trigger(
|
||||||
|
true,
|
||||||
|
DOMAIN_EXPRESSION_TRIGGER_LOCAL_WAKE);
|
||||||
|
}
|
||||||
|
|
||||||
void control_plane_ptt_reset_capture_window(void)
|
void control_plane_ptt_reset_capture_window(void)
|
||||||
{
|
{
|
||||||
bool active = false;
|
bool active = false;
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ typedef enum {
|
|||||||
DOMAIN_EXPRESSION_TRIGGER_LOCAL_WAKE,
|
DOMAIN_EXPRESSION_TRIGGER_LOCAL_WAKE,
|
||||||
DOMAIN_EXPRESSION_TRIGGER_OTA_UPDATE,
|
DOMAIN_EXPRESSION_TRIGGER_OTA_UPDATE,
|
||||||
DOMAIN_EXPRESSION_TRIGGER_MODEL_LUCKY_COLOR,
|
DOMAIN_EXPRESSION_TRIGGER_MODEL_LUCKY_COLOR,
|
||||||
|
DOMAIN_EXPRESSION_TRIGGER_PTT_BUTTON,
|
||||||
} domain_expression_trigger_t;
|
} domain_expression_trigger_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user