优化了不必要的任务,待测

This commit is contained in:
CSBOOK\44744
2026-06-26 22:20:39 +08:00
parent 7d915e6fb0
commit 0635bd17f7
6 changed files with 126 additions and 356 deletions
@@ -125,3 +125,4 @@ const char *control_plane_key_event_type_name(control_plane_key_event_type_t typ
esp_err_t control_plane_start_key_input_task(void); esp_err_t control_plane_start_key_input_task(void);
void control_plane_stop_key_input_task(void); void control_plane_stop_key_input_task(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);
@@ -35,14 +35,6 @@
#define CONFIG_MULTIMODAL_AUDIO_PREWARM_OPUS_BEFORE_WS 1 #define CONFIG_MULTIMODAL_AUDIO_PREWARM_OPUS_BEFORE_WS 1
#endif #endif
#if defined(CONFIG_MULTIMODAL_AUTO_START_ON_WAKEUP)
#define CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG CONFIG_MULTIMODAL_AUTO_START_ON_WAKEUP
#elif defined(CONFIG_MULTIMODAL_WS_AUTO_START)
#define CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG CONFIG_MULTIMODAL_WS_AUTO_START
#else
#define CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG 0
#endif
#define CONTROL_PLANE_DOWNSTREAM_PLAYBACK_GUARD_MS 220 #define CONTROL_PLANE_DOWNSTREAM_PLAYBACK_GUARD_MS 220
#define CONTROL_PLANE_IDLE_TRANSPORT_SHUTDOWN_MS 30000 #define CONTROL_PLANE_IDLE_TRANSPORT_SHUTDOWN_MS 30000
#define CONTROL_PLANE_WATCHDOG_TASK_STACK_SIZE 6144 #define CONTROL_PLANE_WATCHDOG_TASK_STACK_SIZE 6144
@@ -60,11 +52,8 @@
static const char *TAG = "control_plane_mm_rt"; static const char *TAG = "control_plane_mm_rt";
static TaskHandle_t s_multimodal_watchdog_task; static TaskHandle_t s_multimodal_watchdog_task;
static TaskHandle_t s_multimodal_autostart_task;
static bool s_multimodal_watchdog_stop_requested; static bool s_multimodal_watchdog_stop_requested;
static bool s_multimodal_autostart_stop_requested;
static bool s_multimodal_watchdog_task_starting; static bool s_multimodal_watchdog_task_starting;
static bool s_multimodal_autostart_task_starting;
static bool s_model_command_dispatched; static bool s_model_command_dispatched;
static bool s_server_success_prompt_played; static bool s_server_success_prompt_played;
static control_plane_model_command_callback_t s_model_command_cb; static control_plane_model_command_callback_t s_model_command_cb;
@@ -370,104 +359,6 @@ esp_err_t control_plane_multimodal_update_info(
return control_plane_multimodal_send_update_info(request); return control_plane_multimodal_send_update_info(request);
} }
static void multimodal_autostart_task(void *arg)
{
(void)arg;
TaskHandle_t self = xTaskGetCurrentTaskHandle();
TickType_t wait_step = pdMS_TO_TICKS(200);
TickType_t wait_timeout = pdMS_TO_TICKS(CONFIG_MULTIMODAL_RECONNECT_DELAY_MS + 3000);
if (wait_timeout < pdMS_TO_TICKS(3000)) {
wait_timeout = pdMS_TO_TICKS(3000);
}
TickType_t start_tick = xTaskGetTickCount();
while (!get_multimodal_stop_flag(&s_multimodal_autostart_stop_requested) &&
!control_plane_multimodal_is_connected()) {
if ((xTaskGetTickCount() - start_tick) >= wait_timeout) {
ESP_LOGW(TAG, "Auto Start aborted: transport not ready");
clear_multimodal_task_handle_if_match(&s_multimodal_autostart_task, self);
vTaskDelete(NULL);
return;
}
vTaskDelay(wait_step);
}
for (int attempt = 1;
!get_multimodal_stop_flag(&s_multimodal_autostart_stop_requested) && attempt <= 5 &&
control_plane_multimodal_is_connected();
++attempt) {
esp_err_t err = control_plane_multimodal_send_start();
if (err == ESP_OK) {
break;
}
if (attempt < 5 && control_plane_multimodal_is_connected()) {
ESP_LOGW(TAG,
"Auto Start send failed (%d/5): %s",
attempt,
esp_err_to_name(err));
vTaskDelay(pdMS_TO_TICKS(300));
} else {
ESP_LOGW(TAG, "Auto Start send failed: %s", esp_err_to_name(err));
}
}
clear_multimodal_task_handle_if_match(&s_multimodal_autostart_task, self);
vTaskDelete(NULL);
}
static void stop_autostart_task(void)
{
set_multimodal_stop_flag(&s_multimodal_autostart_stop_requested, true);
if (get_multimodal_task_handle(&s_multimodal_autostart_task) != NULL ||
get_multimodal_start_flag(&s_multimodal_autostart_task_starting)) {
if (!wait_task_exit(&s_multimodal_autostart_task,
&s_multimodal_autostart_task_starting,
800)) {
TaskHandle_t task = get_multimodal_task_handle(&s_multimodal_autostart_task);
if (task != NULL) {
vTaskDelete(task);
}
set_multimodal_task_handle(&s_multimodal_autostart_task, NULL);
}
}
set_multimodal_start_flag(&s_multimodal_autostart_task_starting, false);
set_multimodal_stop_flag(&s_multimodal_autostart_stop_requested, false);
}
static void schedule_autostart_if_enabled(void)
{
if (!CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG) {
return;
}
if (get_multimodal_task_handle(&s_multimodal_autostart_task) != NULL ||
get_multimodal_start_flag(&s_multimodal_autostart_task_starting)) {
return;
}
if (!try_begin_multimodal_task_start(&s_multimodal_autostart_task,
&s_multimodal_autostart_task_starting)) {
return;
}
set_multimodal_stop_flag(&s_multimodal_autostart_stop_requested, false);
if (xTaskCreatePinnedToCore(multimodal_autostart_task,
"mm_autostart",
6144,
NULL,
4,
&s_multimodal_autostart_task,
CONTROL_PLANE_MULTIMODAL_NETWORK_TASK_CORE) != pdPASS) {
set_multimodal_task_handle(&s_multimodal_autostart_task, NULL);
set_multimodal_start_flag(&s_multimodal_autostart_task_starting, false);
ESP_LOGW(TAG, "Auto Start task create failed");
return;
}
set_multimodal_start_flag(&s_multimodal_autostart_task_starting, false);
}
static void stop_watchdog_task(void) static void stop_watchdog_task(void)
{ {
set_multimodal_stop_flag(&s_multimodal_watchdog_stop_requested, true); set_multimodal_stop_flag(&s_multimodal_watchdog_stop_requested, true);
@@ -520,7 +411,6 @@ static void multimodal_watchdog_task(void *arg)
"Idle multimodal transport timeout, stopping client after %u ms", "Idle multimodal transport timeout, stopping client after %u ms",
(unsigned)CONTROL_PLANE_IDLE_TRANSPORT_SHUTDOWN_MS); (unsigned)CONTROL_PLANE_IDLE_TRANSPORT_SHUTDOWN_MS);
control_plane_multimodal_stop_uplink(); control_plane_multimodal_stop_uplink();
stop_autostart_task();
control_plane_multimodal_stop(); control_plane_multimodal_stop();
idle_transport_started_ms = 0U; idle_transport_started_ms = 0U;
} }
@@ -599,21 +489,16 @@ static void control_plane_multimodal_event_bridge(control_plane_multimodal_event
if (should_play_prompt) { if (should_play_prompt) {
(void)domain_runtime_behavior_play_prompt_file(CONTROL_PLANE_SERVER_SUCCESS_PROMPT_FILE); (void)domain_runtime_behavior_play_prompt_file(CONTROL_PLANE_SERVER_SUCCESS_PROMPT_FILE);
} }
if (CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG) {
schedule_autostart_if_enabled();
}
break; break;
} }
case CONTROL_PLANE_MULTIMODAL_EVENT_TRANSPORT_DISCONNECTED: case CONTROL_PLANE_MULTIMODAL_EVENT_TRANSPORT_DISCONNECTED:
control_plane_multimodal_stop_uplink(); control_plane_multimodal_stop_uplink();
stop_autostart_task();
break; break;
case CONTROL_PLANE_MULTIMODAL_EVENT_TASK_FAILED: case CONTROL_PLANE_MULTIMODAL_EVENT_TASK_FAILED:
control_plane_request_server_error_expression(DOMAIN_EXPRESSION_TRIGGER_SERVER_TASK_FAILED); control_plane_request_server_error_expression(DOMAIN_EXPRESSION_TRIGGER_SERVER_TASK_FAILED);
control_plane_multimodal_stop_uplink(); control_plane_multimodal_stop_uplink();
schedule_autostart_if_enabled();
break; break;
case CONTROL_PLANE_MULTIMODAL_EVENT_TASK_STARTED: case CONTROL_PLANE_MULTIMODAL_EVENT_TASK_STARTED:
@@ -701,16 +586,11 @@ esp_err_t control_plane_start_multimodal_client(void)
return err; return err;
} }
if (CONTROL_PLANE_MULTIMODAL_AUTO_START_FLAG && control_plane_multimodal_is_connected()) {
schedule_autostart_if_enabled();
}
return ESP_OK; return ESP_OK;
} }
void control_plane_stop_multimodal_client(void) void control_plane_stop_multimodal_client(void)
{ {
stop_autostart_task();
stop_watchdog_task(); stop_watchdog_task();
control_plane_multimodal_stop(); control_plane_multimodal_stop();
} }
@@ -20,7 +20,6 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#define CONTROL_PLANE_WS_WAIT_TASK_STACK_SIZE (1024 * 10)
#define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4) #define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_DIRECTION_TASK_STACK_SIZE (1024 * 4) #define CONTROL_PLANE_DIRECTION_TASK_STACK_SIZE (1024 * 4)
#define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12) #define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12)
@@ -32,6 +31,7 @@
#define CONTROL_PLANE_TASK_START_GATE_WAIT_MS 5000 #define CONTROL_PLANE_TASK_START_GATE_WAIT_MS 5000
#define CONTROL_PLANE_INPUT_BUF_SIZE 64 #define CONTROL_PLANE_INPUT_BUF_SIZE 64
#define CONTROL_PLANE_WIFI_STATE_POLL_INTERVAL_MS 1000 #define CONTROL_PLANE_WIFI_STATE_POLL_INTERVAL_MS 1000
#define CONTROL_PLANE_PTT_ACTIVE_POLL_INTERVAL_MS 80
#define CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS 5000 #define CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS 5000
#define CONTROL_PLANE_WIFI_DISCONNECT_GRACE_MS 3000 #define CONTROL_PLANE_WIFI_DISCONNECT_GRACE_MS 3000
#define CONTROL_PLANE_WIFI_RECONNECT_TIMEOUT_MS 10000 #define CONTROL_PLANE_WIFI_RECONNECT_TIMEOUT_MS 10000
@@ -66,6 +66,10 @@
#define CONFIG_TQ_TASK_MONITOR_ENABLE 0 #define CONFIG_TQ_TASK_MONITOR_ENABLE 0
#endif #endif
#ifndef CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
#define CONFIG_TQ_DIRECTION_CONSOLE_ENABLE 0
#endif
#ifndef CONFIG_TQ_TASK_MONITOR_INTERVAL_MS #ifndef CONFIG_TQ_TASK_MONITOR_INTERVAL_MS
#define CONFIG_TQ_TASK_MONITOR_INTERVAL_MS 10000 #define CONFIG_TQ_TASK_MONITOR_INTERVAL_MS 10000
#endif #endif
@@ -134,9 +138,11 @@ typedef struct {
static QueueHandle_t s_model_cmd_queue; static QueueHandle_t s_model_cmd_queue;
static bool s_model_cmd_queue_with_caps; static bool s_model_cmd_queue_with_caps;
static TaskHandle_t s_model_cmd_task; static TaskHandle_t s_model_cmd_task;
static TaskHandle_t s_ws_wait_task; static bool s_ws_start_requested;
static bool s_ws_wait_task_starting; static bool s_ptt_active;
#if CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
static TaskHandle_t s_direction_console_task; static TaskHandle_t s_direction_console_task;
#endif
static TaskHandle_t s_lcd_render_loop_task; static TaskHandle_t s_lcd_render_loop_task;
static TaskHandle_t s_wifi_state_task; static TaskHandle_t s_wifi_state_task;
#if CONFIG_TQ_TASK_MONITOR_ENABLE #if CONFIG_TQ_TASK_MONITOR_ENABLE
@@ -166,6 +172,35 @@ static void control_plane_set_runtime_stop_requested(bool stop_requested)
portEXIT_CRITICAL(&s_runtime_lock); portEXIT_CRITICAL(&s_runtime_lock);
} }
void control_plane_set_ptt_active(bool active)
{
portENTER_CRITICAL(&s_runtime_lock);
s_ptt_active = active;
if (active) {
s_ws_start_requested = true;
}
portEXIT_CRITICAL(&s_runtime_lock);
}
static bool control_plane_get_ptt_active(void)
{
bool active = false;
portENTER_CRITICAL(&s_runtime_lock);
active = s_ptt_active;
portEXIT_CRITICAL(&s_runtime_lock);
return active;
}
static bool control_plane_consume_ws_start_requested(void)
{
bool requested = false;
portENTER_CRITICAL(&s_runtime_lock);
requested = s_ws_start_requested;
s_ws_start_requested = false;
portEXIT_CRITICAL(&s_runtime_lock);
return requested;
}
static TaskHandle_t control_plane_get_task_handle(TaskHandle_t *slot) static TaskHandle_t control_plane_get_task_handle(TaskHandle_t *slot)
{ {
TaskHandle_t task = NULL; TaskHandle_t task = NULL;
@@ -184,45 +219,6 @@ static void control_plane_set_task_handle(TaskHandle_t *slot, TaskHandle_t task)
static void control_plane_task_start_gate(void *arg); static void control_plane_task_start_gate(void *arg);
static void control_plane_clear_websocket_wait_task_if_match(TaskHandle_t task)
{
portENTER_CRITICAL(&s_runtime_lock);
if (s_ws_wait_task == task) {
s_ws_wait_task = NULL;
}
s_ws_wait_task_starting = false;
portEXIT_CRITICAL(&s_runtime_lock);
}
static bool control_plane_websocket_wait_task_idle(void)
{
bool idle = false;
portENTER_CRITICAL(&s_runtime_lock);
idle = (s_ws_wait_task == NULL && !s_ws_wait_task_starting);
portEXIT_CRITICAL(&s_runtime_lock);
return idle;
}
static bool control_plane_wait_websocket_wait_task_idle(int timeout_ms)
{
if (control_plane_websocket_wait_task_idle()) {
return true;
}
TickType_t timeout_ticks = pdMS_TO_TICKS(timeout_ms > 0 ? timeout_ms : 1);
if (timeout_ticks == 0) {
timeout_ticks = 1;
}
TickType_t start_tick = xTaskGetTickCount();
while (!control_plane_websocket_wait_task_idle() &&
(xTaskGetTickCount() - start_tick) < timeout_ticks) {
vTaskDelay(pdMS_TO_TICKS(20));
}
return control_plane_websocket_wait_task_idle();
}
static QueueHandle_t control_plane_get_model_cmd_queue(void) static QueueHandle_t control_plane_get_model_cmd_queue(void)
{ {
QueueHandle_t queue = NULL; QueueHandle_t queue = NULL;
@@ -492,6 +488,7 @@ static void control_plane_task_start_gate(void *arg)
control_plane_delete_task(NULL, task_with_caps); control_plane_delete_task(NULL, task_with_caps);
} }
#if CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
static void control_plane_print_help(void) static void control_plane_print_help(void)
{ {
printf("\n========================================\n"); printf("\n========================================\n");
@@ -573,6 +570,7 @@ static void control_plane_process_direction_command(char *input)
printf("Type 'help' to list available directions\n"); printf("Type 'help' to list available directions\n");
} }
} }
#endif
static void control_plane_on_model_command(control_plane_model_command_type_t command_type, static void control_plane_on_model_command(control_plane_model_command_type_t command_type,
const char *value, const char *value,
@@ -688,71 +686,14 @@ static void control_plane_model_command_task(void *arg)
return; return;
} }
static void control_plane_websocket_wait_task(void *arg)
{
(void)arg;
TaskHandle_t self = xTaskGetCurrentTaskHandle();
if (!control_plane_runtime_stop_requested()) {
(void)control_plane_register_model_command_callback(control_plane_on_model_command, NULL);
while (!control_plane_runtime_stop_requested()) {
while (!control_plane_runtime_stop_requested() && !control_plane_is_sta_connected()) {
vTaskDelay(pdMS_TO_TICKS(500));
}
if (control_plane_runtime_stop_requested()) {
break;
}
esp_err_t err = control_plane_start_multimodal_client();
if (err == ESP_OK) {
ESP_LOGI(TAG, "Multimodal client started");
break;
}
ESP_LOGW(TAG, "Multimodal client start failed: %s", esp_err_to_name(err));
for (int waited_ms = 0;
waited_ms < CONTROL_PLANE_WS_START_RETRY_DELAY_MS &&
!control_plane_runtime_stop_requested() &&
control_plane_is_sta_connected();
waited_ms += 500) {
vTaskDelay(pdMS_TO_TICKS(500));
}
}
}
control_plane_clear_websocket_wait_task_if_match(self);
return;
}
esp_err_t control_plane_schedule_websocket_wait_task(void) esp_err_t control_plane_schedule_websocket_wait_task(void)
{ {
bool should_create = false;
portENTER_CRITICAL(&s_runtime_lock); portENTER_CRITICAL(&s_runtime_lock);
if (!s_runtime_stop_requested && if (!s_runtime_stop_requested) {
s_ws_wait_task == NULL && s_ws_start_requested = true;
!s_ws_wait_task_starting) {
s_ws_wait_task_starting = true;
should_create = true;
} }
portEXIT_CRITICAL(&s_runtime_lock); portEXIT_CRITICAL(&s_runtime_lock);
return ESP_OK;
if (!should_create) {
return ESP_OK;
}
esp_err_t err = control_plane_create_task(control_plane_websocket_wait_task,
"cp_ws_wait",
CONTROL_PLANE_WS_WAIT_TASK_STACK_SIZE,
4,
CONTROL_PLANE_NETWORK_TASK_CORE,
&s_ws_wait_task);
portENTER_CRITICAL(&s_runtime_lock);
s_ws_wait_task_starting = false;
portEXIT_CRITICAL(&s_runtime_lock);
return err;
} }
#if CONFIG_TQ_TASK_MONITOR_ENABLE #if CONFIG_TQ_TASK_MONITOR_ENABLE
@@ -878,6 +819,7 @@ static void control_plane_task_monitor_task(void *arg)
} }
#endif #endif
#if CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
static void control_plane_direction_console_task(void *arg) static void control_plane_direction_console_task(void *arg)
{ {
(void)arg; (void)arg;
@@ -943,6 +885,7 @@ static void control_plane_direction_console_task(void *arg)
control_plane_set_task_handle(&s_direction_console_task, NULL); control_plane_set_task_handle(&s_direction_console_task, NULL);
return; return;
} }
#endif
#if CONFIG_TQ_SCREEN_ENABLE #if CONFIG_TQ_SCREEN_ENABLE
static void control_plane_lcd_render_loop_task(void *arg) static void control_plane_lcd_render_loop_task(void *arg)
@@ -1041,6 +984,53 @@ static esp_err_t control_plane_ensure_user_config_server(void)
#endif #endif
} }
static void control_plane_try_start_multimodal_from_state_machine(TickType_t *last_attempt_tick)
{
TickType_t now = xTaskGetTickCount();
TickType_t retry_ticks = pdMS_TO_TICKS(CONTROL_PLANE_WS_START_RETRY_DELAY_MS);
if (retry_ticks == 0) {
retry_ticks = 1;
}
if (last_attempt_tick != NULL &&
*last_attempt_tick != 0 &&
(now - *last_attempt_tick) < retry_ticks) {
return;
}
if (last_attempt_tick != NULL) {
*last_attempt_tick = now;
}
esp_err_t err = control_plane_start_multimodal_client();
if (err == ESP_OK) {
ESP_LOGI(TAG, "Multimodal client started");
return;
}
ESP_LOGW(TAG, "Multimodal client start failed: %s", esp_err_to_name(err));
}
static void control_plane_drive_ptt_state_machine(void)
{
if (!control_plane_get_ptt_active()) {
return;
}
if (!control_plane_is_sta_connected()) {
return;
}
if (!control_plane_multimodal_is_connected()) {
(void)control_plane_schedule_websocket_wait_task();
}
esp_err_t press_err = control_plane_multimodal_handle_ptt_press_step();
if (press_err != ESP_OK &&
press_err != ESP_ERR_INVALID_STATE &&
press_err != ESP_ERR_NOT_SUPPORTED) {
ESP_LOGW(TAG, "PTT press step failed: %s", esp_err_to_name(press_err));
}
}
static void control_plane_stop_user_config_server(void) static void control_plane_stop_user_config_server(void)
{ {
#if CONFIG_FORTUNE_ENABLE #if CONFIG_FORTUNE_ENABLE
@@ -1058,6 +1048,7 @@ static void control_plane_wifi_state_task(void *arg)
(void)arg; (void)arg;
ESP_LOGI(TAG, "Wi-Fi state monitor task started"); ESP_LOGI(TAG, "Wi-Fi state monitor task started");
(void)control_plane_register_model_command_callback(control_plane_on_model_command, NULL);
const TickType_t poll_ticks = pdMS_TO_TICKS(CONTROL_PLANE_WIFI_STATE_POLL_INTERVAL_MS); const TickType_t poll_ticks = pdMS_TO_TICKS(CONTROL_PLANE_WIFI_STATE_POLL_INTERVAL_MS);
const TickType_t refresh_ticks = pdMS_TO_TICKS(CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS); const TickType_t refresh_ticks = pdMS_TO_TICKS(CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS);
@@ -1072,6 +1063,7 @@ static void control_plane_wifi_state_task(void *arg)
TickType_t last_disconnected_request_tick = 0; TickType_t last_disconnected_request_tick = 0;
TickType_t last_reconnect_attempt_tick = 0; TickType_t last_reconnect_attempt_tick = 0;
TickType_t last_user_web_attempt_tick = 0; TickType_t last_user_web_attempt_tick = 0;
TickType_t last_ws_start_attempt_tick = 0;
uint32_t reconnect_delay_ms = CONTROL_PLANE_WIFI_RECONNECT_BASE_DELAY_MS; uint32_t reconnect_delay_ms = CONTROL_PLANE_WIFI_RECONNECT_BASE_DELAY_MS;
bool reconnect_attempted = false; bool reconnect_attempted = false;
@@ -1083,6 +1075,7 @@ static void control_plane_wifi_state_task(void *arg)
disconnected_expression_active = true; disconnected_expression_active = true;
last_disconnected_request_tick = xTaskGetTickCount(); last_disconnected_request_tick = xTaskGetTickCount();
} else { } else {
(void)control_plane_schedule_websocket_wait_task();
esp_err_t web_err = control_plane_ensure_user_config_server(); esp_err_t web_err = control_plane_ensure_user_config_server();
if (web_err != ESP_OK) { if (web_err != ESP_OK) {
ESP_LOGW(TAG, "Initial user configuration server start failed: %s", ESP_LOGW(TAG, "Initial user configuration server start failed: %s",
@@ -1092,7 +1085,10 @@ static void control_plane_wifi_state_task(void *arg)
} }
while (!control_plane_runtime_stop_requested()) { while (!control_plane_runtime_stop_requested()) {
vTaskDelay(poll_ticks > 0 ? poll_ticks : 1); TickType_t next_delay_ticks = control_plane_get_ptt_active() ?
pdMS_TO_TICKS(CONTROL_PLANE_PTT_ACTIVE_POLL_INTERVAL_MS) :
poll_ticks;
vTaskDelay(next_delay_ticks > 0 ? next_delay_ticks : 1);
bool connected = control_plane_is_sta_connected(); bool connected = control_plane_is_sta_connected();
TickType_t now_tick = xTaskGetTickCount(); TickType_t now_tick = xTaskGetTickCount();
@@ -1165,12 +1161,7 @@ static void control_plane_wifi_state_task(void *arg)
control_plane_request_wifi_state_expression(DOMAIN_EXPRESSION_IDLE, control_plane_request_wifi_state_expression(DOMAIN_EXPRESSION_IDLE,
DOMAIN_EXPRESSION_TRIGGER_WIFI_RECONNECTED, DOMAIN_EXPRESSION_TRIGGER_WIFI_RECONNECTED,
"Wi-Fi reconnected"); "Wi-Fi reconnected");
esp_err_t ws_task_err = control_plane_schedule_websocket_wait_task(); (void)control_plane_schedule_websocket_wait_task();
if (ws_task_err != ESP_OK) {
ESP_LOGW(TAG,
"Schedule multimodal client restart failed: %s",
esp_err_to_name(ws_task_err));
}
disconnected_expression_active = false; disconnected_expression_active = false;
disconnect_pending = false; disconnect_pending = false;
disconnect_started_tick = 0; disconnect_started_tick = 0;
@@ -1185,6 +1176,13 @@ static void control_plane_wifi_state_task(void *arg)
} }
if (connected) { if (connected) {
bool ws_start_due = control_plane_consume_ws_start_requested();
if (ws_start_due && !control_plane_multimodal_is_connected()) {
control_plane_try_start_multimodal_from_state_machine(&last_ws_start_attempt_tick);
now_tick = xTaskGetTickCount();
}
control_plane_drive_ptt_state_machine();
TickType_t web_retry_ticks = pdMS_TO_TICKS(CONTROL_PLANE_USER_WEB_RETRY_MS); TickType_t web_retry_ticks = pdMS_TO_TICKS(CONTROL_PLANE_USER_WEB_RETRY_MS);
if (web_retry_ticks == 0) { if (web_retry_ticks == 0) {
web_retry_ticks = 1; web_retry_ticks = 1;
@@ -1519,14 +1517,9 @@ esp_err_t control_plane_start_runtime_workers(void)
} }
} }
if (control_plane_get_task_handle(&s_ws_wait_task) == NULL) { (void)control_plane_schedule_websocket_wait_task();
esp_err_t task_err = control_plane_schedule_websocket_wait_task();
if (task_err != ESP_OK) {
control_plane_stop_runtime_workers();
return task_err;
}
}
#if CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
if (control_plane_get_task_handle(&s_direction_console_task) == NULL) { if (control_plane_get_task_handle(&s_direction_console_task) == NULL) {
esp_err_t task_err = control_plane_create_task(control_plane_direction_console_task, esp_err_t task_err = control_plane_create_task(control_plane_direction_console_task,
"cp_direction", "cp_direction",
@@ -1539,6 +1532,9 @@ esp_err_t control_plane_start_runtime_workers(void)
return task_err; return task_err;
} }
} }
#else
ESP_LOGI(TAG, "Direction console disabled by configuration");
#endif
#if CONFIG_TQ_SCREEN_ENABLE #if CONFIG_TQ_SCREEN_ENABLE
esp_err_t lcd_worker_err = control_plane_start_lcd_render_worker(); esp_err_t lcd_worker_err = control_plane_start_lcd_render_worker();
@@ -1667,21 +1663,11 @@ void control_plane_stop_runtime_workers(void)
ESP_LOGW(TAG, "LCD render loop stop ended with %s", esp_err_to_name(lcd_stop_err)); ESP_LOGW(TAG, "LCD render loop stop ended with %s", esp_err_to_name(lcd_stop_err));
} }
if (!control_plane_wait_task_exit(&s_ws_wait_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) { #if CONFIG_TQ_DIRECTION_CONSOLE_ENABLE
control_plane_force_delete_task(&s_ws_wait_task, "cp_ws_wait");
}
if (!control_plane_wait_websocket_wait_task_idle(CONTROL_PLANE_TASK_STOP_WAIT_MS)) {
ESP_LOGW(TAG, "cp_ws_wait start did not quiesce before stop timeout");
portENTER_CRITICAL(&s_runtime_lock);
s_ws_wait_task_starting = false;
portEXIT_CRITICAL(&s_runtime_lock);
if (!control_plane_wait_task_exit(&s_ws_wait_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) {
control_plane_force_delete_task(&s_ws_wait_task, "cp_ws_wait");
}
}
if (!control_plane_wait_task_exit(&s_direction_console_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) { if (!control_plane_wait_task_exit(&s_direction_console_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) {
control_plane_force_delete_task(&s_direction_console_task, "cp_direction"); control_plane_force_delete_task(&s_direction_console_task, "cp_direction");
} }
#endif
if (!control_plane_wait_task_exit(&s_lcd_render_loop_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) { if (!control_plane_wait_task_exit(&s_lcd_render_loop_task, CONTROL_PLANE_TASK_STOP_WAIT_MS)) {
control_plane_force_delete_task(&s_lcd_render_loop_task, "cp_lcd_render"); control_plane_force_delete_task(&s_lcd_render_loop_task, "cp_lcd_render");
} }
@@ -31,9 +31,6 @@
#endif #endif
#define CONTROL_PLANE_PTT_HOLD_STEP_MS 80 #define CONTROL_PLANE_PTT_HOLD_STEP_MS 80
#define CONTROL_PLANE_PTT_HOLD_START_DELAY_MS 320
#define CONTROL_PLANE_PTT_HOLD_TASK_STACK 4096
#define CONTROL_PLANE_PTT_HOLD_TASK_PRIORITY 4
#ifndef CONFIG_TQ_LOCAL_TASK_CORE #ifndef CONFIG_TQ_LOCAL_TASK_CORE
#define CONFIG_TQ_LOCAL_TASK_CORE 1 #define CONFIG_TQ_LOCAL_TASK_CORE 1
@@ -49,9 +46,7 @@ static const char *TAG = "cp_system_event";
static QueueHandle_t s_system_event_queue; static QueueHandle_t s_system_event_queue;
static TaskHandle_t s_system_event_task; static TaskHandle_t s_system_event_task;
static TaskHandle_t s_ptt_hold_task;
static volatile bool s_stop_requested; static volatile bool s_stop_requested;
static volatile bool s_ptt_hold_active;
static const char *control_plane_event_family_name(control_plane_event_family_t family) static const char *control_plane_event_family_name(control_plane_event_family_t family)
{ {
@@ -113,88 +108,6 @@ const char *control_plane_key_event_type_name(control_plane_key_event_type_t typ
} }
} }
static void control_plane_ptt_hold_task(void *arg)
{
(void)arg;
ESP_LOGI(TAG, "PTT hold task started");
bool start_requested = false;
uint32_t waited_ms = 0;
while (s_ptt_hold_active &&
!s_stop_requested &&
waited_ms < CONTROL_PLANE_PTT_HOLD_START_DELAY_MS) {
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PTT_HOLD_STEP_MS));
waited_ms += CONTROL_PLANE_PTT_HOLD_STEP_MS;
}
while (s_ptt_hold_active && !s_stop_requested) {
if (!control_plane_is_sta_connected()) {
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PTT_HOLD_STEP_MS));
continue;
}
if (!control_plane_multimodal_is_connected() && !start_requested) {
esp_err_t schedule_err = control_plane_schedule_websocket_wait_task();
if (schedule_err != ESP_OK && schedule_err != ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG,
"PTT multimodal start schedule failed: %s",
esp_err_to_name(schedule_err));
} else {
start_requested = true;
}
}
esp_err_t press_err = control_plane_multimodal_handle_ptt_press_step();
if (press_err != ESP_OK &&
press_err != ESP_ERR_INVALID_STATE &&
press_err != ESP_ERR_NOT_SUPPORTED) {
ESP_LOGW(TAG, "PTT press step failed: %s", esp_err_to_name(press_err));
}
vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PTT_HOLD_STEP_MS));
}
ESP_LOGI(TAG, "PTT hold task stopped");
s_ptt_hold_task = NULL;
vTaskDelete(NULL);
}
static esp_err_t control_plane_start_ptt_hold_task(void)
{
s_ptt_hold_active = true;
if (s_ptt_hold_task != NULL) {
return ESP_OK;
}
BaseType_t created = xTaskCreatePinnedToCore(control_plane_ptt_hold_task,
"cp_ptt_hold",
CONTROL_PLANE_PTT_HOLD_TASK_STACK,
NULL,
CONTROL_PLANE_PTT_HOLD_TASK_PRIORITY,
&s_ptt_hold_task,
CONTROL_PLANE_SYSTEM_EVENT_TASK_CORE);
if (created != pdPASS) {
s_ptt_hold_task = NULL;
s_ptt_hold_active = false;
return ESP_ERR_NO_MEM;
}
return ESP_OK;
}
static void control_plane_stop_ptt_hold_task(void)
{
s_ptt_hold_active = false;
for (int i = 0; i < 10 && s_ptt_hold_task != NULL; ++i) {
vTaskDelay(pdMS_TO_TICKS(20));
}
if (s_ptt_hold_task != NULL) {
vTaskDelete(s_ptt_hold_task);
s_ptt_hold_task = NULL;
}
}
static void control_plane_dispatch_key_event(const control_plane_key_event_t *event) static void control_plane_dispatch_key_event(const control_plane_key_event_t *event)
{ {
if (event == NULL) { if (event == NULL) {
@@ -216,15 +129,12 @@ static void control_plane_dispatch_key_event(const control_plane_key_event_t *ev
switch (event->type) { switch (event->type) {
case CONTROL_PLANE_KEY_EVENT_PRESSED: { case CONTROL_PLANE_KEY_EVENT_PRESSED: {
esp_err_t start_err = control_plane_start_ptt_hold_task(); control_plane_set_ptt_active(true);
if (start_err != ESP_OK) {
ESP_LOGW(TAG, "PTT hold task start failed: %s", esp_err_to_name(start_err));
}
break; break;
} }
case CONTROL_PLANE_KEY_EVENT_RELEASED: { case CONTROL_PLANE_KEY_EVENT_RELEASED: {
control_plane_stop_ptt_hold_task(); control_plane_set_ptt_active(false);
esp_err_t release_err = control_plane_multimodal_handle_ptt_release(); esp_err_t release_err = control_plane_multimodal_handle_ptt_release();
if (release_err != ESP_OK && release_err != ESP_ERR_INVALID_STATE) { if (release_err != ESP_OK && release_err != ESP_ERR_INVALID_STATE) {
ESP_LOGW(TAG, "PTT release failed: %s", esp_err_to_name(release_err)); ESP_LOGW(TAG, "PTT release failed: %s", esp_err_to_name(release_err));
@@ -352,7 +262,7 @@ void control_plane_stop_system_event_task(void)
{ {
#if CONFIG_TQ_SYSTEM_EVENT_ENABLE #if CONFIG_TQ_SYSTEM_EVENT_ENABLE
s_stop_requested = true; s_stop_requested = true;
control_plane_stop_ptt_hold_task(); control_plane_set_ptt_active(false);
for (int i = 0; i < 20 && s_system_event_task != NULL; ++i) { for (int i = 0; i < 20 && s_system_event_task != NULL; ++i) {
vTaskDelay(pdMS_TO_TICKS(50)); vTaskDelay(pdMS_TO_TICKS(50));
+7 -13
View File
@@ -88,6 +88,13 @@ menu "Example Configuration"
Core used for local device workers such as LCD rendering, Core used for local device workers such as LCD rendering,
key input, system events, direction console, and diagnostics. key input, system events, direction console, and diagnostics.
config TQ_DIRECTION_CONSOLE_ENABLE
bool "Enable UART direction debug console"
default n
help
Start the serial direction console for development or factory
diagnostics. Normal product runtime should leave this disabled.
config TQ_TASK_MONITOR_ENABLE config TQ_TASK_MONITOR_ENABLE
bool "Enable periodic FreeRTOS task monitor log" bool "Enable periodic FreeRTOS task monitor log"
default y default y
@@ -1301,19 +1308,6 @@ menu "Example Configuration"
help help
Delay between reconnect attempts if auto-reconnect is enabled. Delay between reconnect attempts if auto-reconnect is enabled.
config MULTIMODAL_WS_AUTO_START
bool "Send Start directive after connection"
default MULTIMODAL_AUTO_START_ON_WAKEUP
help
When enabled, send Start immediately after WebSocket is connected.
config MULTIMODAL_AUTO_START_ON_WAKEUP
bool "Auto send Start on wakeup/connect"
default n
help
Alias used by documentation. When enabled, Start is sent
automatically after WebSocket is connected.
endmenu endmenu
endmenu endmenu
+1 -2
View File
@@ -14,6 +14,7 @@ CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY=y
CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM=y
CONFIG_FREERTOS_USE_TRACE_FACILITY=y CONFIG_FREERTOS_USE_TRACE_FACILITY=y
# CONFIG_TQ_TASK_MONITOR_ENABLE is not set # CONFIG_TQ_TASK_MONITOR_ENABLE is not set
# CONFIG_TQ_DIRECTION_CONSOLE_ENABLE is not set
# CONFIG_TQ_BOOT_SEQUENCE_DRY_RUN is not set # CONFIG_TQ_BOOT_SEQUENCE_DRY_RUN is not set
CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS=3000 CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS=3000
CONFIG_TQ_BOOT_SOUND_FILE="boot.opus" CONFIG_TQ_BOOT_SOUND_FILE="boot.opus"
@@ -152,8 +153,6 @@ CONFIG_MULTIMODAL_WS_OPUS_TASK_STACK_BYTES=12288
CONFIG_MULTIMODAL_WS_MSG_QUEUE_LEN=512 CONFIG_MULTIMODAL_WS_MSG_QUEUE_LEN=512
CONFIG_MULTIMODAL_RECONNECT_DELAY_MS=2000 CONFIG_MULTIMODAL_RECONNECT_DELAY_MS=2000
# Keep both symbols for compatibility; defaults follow doc behavior. # Keep both symbols for compatibility; defaults follow doc behavior.
CONFIG_MULTIMODAL_AUTO_START_ON_WAKEUP=n
CONFIG_MULTIMODAL_WS_AUTO_START=n
# Disable separate TX lock for stability; single lock avoids close/send race under high-frequency uplink. # Disable separate TX lock for stability; single lock avoids close/send race under high-frequency uplink.
CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK=y CONFIG_ESP_WS_CLIENT_SEPARATE_TX_LOCK=y
CONFIG_ESP_WS_CLIENT_TX_LOCK_TIMEOUT_MS=2000 CONFIG_ESP_WS_CLIENT_TX_LOCK_TIMEOUT_MS=2000