feat: Refactor MainUI and MainUIHandler for improved status update handling and UI consistency

This commit is contained in:
GW_MC
2026-02-02 21:55:51 +08:00
parent 08daed936e
commit c51991350f
4 changed files with 30 additions and 17 deletions

View File

@@ -4,6 +4,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_lvgl_port.h" #include "esp_lvgl_port.h"
#define LVGL_LOCK_TIMEOUT 2000 // milliseconds
static const char* TAG = "MainUI"; static const char* TAG = "MainUI";
MainUI::~MainUI() { MainUI::~MainUI() {
@@ -34,7 +35,7 @@ void MainUI::create_ui_(lv_obj_t* parent) {
return; return;
} }
if (!lvgl_port_lock(pdMS_TO_TICKS(100))) { if (!lvgl_port_lock(pdMS_TO_TICKS(LVGL_LOCK_TIMEOUT))) {
ESP_LOGE(TAG, "Failed to acquire LVGL lock for UI creation"); ESP_LOGE(TAG, "Failed to acquire LVGL lock for UI creation");
return; return;
} }
@@ -83,10 +84,13 @@ void MainUI::create_ui_(lv_obj_t* parent) {
// Mute button // Mute button
mute_button_ = lv_btn_create(center_container); mute_button_ = lv_btn_create(center_container);
lv_obj_set_size(mute_button_, 200, 60); lv_obj_set_size(mute_button_, 200, 60);
lv_obj_set_style_bg_color(mute_button_, lv_color_white(), 0);
lv_obj_set_style_border_color(mute_button_, lv_color_black(), 0);
lv_obj_set_style_border_width(mute_button_, 2, 0);
lv_obj_t* mute_label = lv_label_create(mute_button_); lv_obj_t* mute_label = lv_label_create(mute_button_);
lv_label_set_text(mute_label, "MUTE"); lv_label_set_text(mute_label, "MUTE");
lv_obj_center(mute_label); lv_obj_center(mute_label);
lv_obj_set_style_text_color(mute_label, lv_color_black(), 0);
// === Bottom Section: Settings and Config Prompt === // === Bottom Section: Settings and Config Prompt ===
lv_obj_t* bottom_container = lv_obj_create(parent); lv_obj_t* bottom_container = lv_obj_create(parent);
@@ -105,10 +109,14 @@ void MainUI::create_ui_(lv_obj_t* parent) {
// Settings button (right side) // Settings button (right side)
settings_button_ = lv_btn_create(bottom_container); settings_button_ = lv_btn_create(bottom_container);
lv_obj_set_size(settings_button_, 60, 60); lv_obj_set_size(settings_button_, 60, 60);
lv_obj_set_style_bg_color(settings_button_, lv_color_white(), 0);
lv_obj_set_style_border_color(settings_button_, lv_color_black(), 0);
lv_obj_set_style_border_width(settings_button_, 2, 0);
lv_obj_t* settings_icon = lv_label_create(settings_button_); lv_obj_t* settings_icon = lv_label_create(settings_button_);
lv_label_set_text(settings_icon, LV_SYMBOL_SETTINGS); lv_label_set_text(settings_icon, LV_SYMBOL_SETTINGS);
lv_obj_center(settings_icon); lv_obj_center(settings_icon);
lv_obj_set_style_text_color(settings_icon, lv_color_black(), 0);
ESP_LOGI(TAG, "Main UI created"); ESP_LOGI(TAG, "Main UI created");
lvgl_port_unlock(); lvgl_port_unlock();
@@ -130,14 +138,14 @@ esp_err_t MainUI::register_on_mute_button_clicked(lv_event_cb_t cb, void* user_d
return ESP_OK; return ESP_OK;
} }
void MainUI::update_status(VoiceState state) { bool MainUI::update_status(VoiceState state) {
if (!status_icon_label_ || !status_text_label_) { if (!status_icon_label_ || !status_text_label_) {
return; return false;
} }
if (!lvgl_port_lock(pdMS_TO_TICKS(100))) { if (!lvgl_port_lock(pdMS_TO_TICKS(LVGL_LOCK_TIMEOUT))) {
ESP_LOGW(TAG, "Failed to acquire LVGL lock for status update"); ESP_LOGW(TAG, "Failed to acquire LVGL lock for status update");
return; return false;
} }
switch (state) { switch (state) {
@@ -167,6 +175,7 @@ void MainUI::update_status(VoiceState state) {
break; break;
} }
lvgl_port_unlock(); lvgl_port_unlock();
return true;
} }
void MainUI::show_error_notification(bool show) { void MainUI::show_error_notification(bool show) {
@@ -174,7 +183,7 @@ void MainUI::show_error_notification(bool show) {
return; return;
} }
if (!lvgl_port_lock(pdMS_TO_TICKS(100))) { if (!lvgl_port_lock(pdMS_TO_TICKS(LVGL_LOCK_TIMEOUT))) {
ESP_LOGW(TAG, "Failed to acquire LVGL lock for error notification update"); ESP_LOGW(TAG, "Failed to acquire LVGL lock for error notification update");
return; return;
} }
@@ -191,7 +200,7 @@ void MainUI::update_config_prompt(bool configured) {
return; return;
} }
if (!lvgl_port_lock(pdMS_TO_TICKS(100))) { if (!lvgl_port_lock(pdMS_TO_TICKS(LVGL_LOCK_TIMEOUT))) {
ESP_LOGW(TAG, "Failed to acquire LVGL lock for config prompt update"); ESP_LOGW(TAG, "Failed to acquire LVGL lock for config prompt update");
return; return;
} }

View File

@@ -56,7 +56,7 @@ public:
* @brief Update status display with current voice state * @brief Update status display with current voice state
* @param state Current voice state * @param state Current voice state
*/ */
void update_status(VoiceState state); bool update_status(VoiceState state);
/** /**
* @brief Show or hide error notification banner * @brief Show or hide error notification banner

View File

@@ -106,7 +106,7 @@ void MainUIHandler::send_mute_command_() {
} }
void MainUIHandler::on_status_update_(StatusUpdateEventData data) { void MainUIHandler::on_status_update_(StatusUpdateEventData data) {
ESP_LOGI(TAG, "on_status_update_ called with state: %d", data.state); ESP_LOGI(TAG, "on_status_update_ called with state: %d, current_state_: %d", data.state, current_state_);
// Update state in thread-safe manner // Update state in thread-safe manner
bool update_ui = false; bool update_ui = false;
@@ -114,7 +114,6 @@ void MainUIHandler::on_status_update_(StatusUpdateEventData data) {
if (data.state != current_state_) { if (data.state != current_state_) {
update_ui = true; update_ui = true;
} }
current_state_ = data.state;
xSemaphoreGive(state_mutex_); xSemaphoreGive(state_mutex_);
ESP_LOGI(TAG, "State updated in mutex"); ESP_LOGI(TAG, "State updated in mutex");
} }
@@ -125,18 +124,18 @@ void MainUIHandler::on_status_update_(StatusUpdateEventData data) {
return; return;
} }
ESP_LOGI(TAG, "Calling update_ui_()"); ESP_LOGI(TAG, "Calling update_ui_()");
update_ui_(); update_ui_(&data.state);
ESP_LOGI(TAG, "on_status_update_ complete"); ESP_LOGI(TAG, "on_status_update_ complete");
} }
void MainUIHandler::update_ui_() { void MainUIHandler::update_ui_(StatusUpdateEventData::VoiceState* state_ptr) {
ESP_LOGI(TAG, "update_ui_ called"); ESP_LOGI(TAG, "update_ui_ called");
if (main_ui_) { if (main_ui_) {
StatusUpdateEventData::VoiceState state; StatusUpdateEventData::VoiceState state;
if (state_mutex_ && xSemaphoreTake(state_mutex_, pdMS_TO_TICKS(100)) == pdTRUE) { if (state_mutex_ && xSemaphoreTake(state_mutex_, pdMS_TO_TICKS(100)) == pdTRUE) {
state = current_state_; state = state_ptr ? *state_ptr : current_state_;
xSemaphoreGive(state_mutex_); xSemaphoreGive(state_mutex_);
} else { } else {
state = StatusUpdateEventData::VoiceState::UNKNOWN; state = StatusUpdateEventData::VoiceState::UNKNOWN;
@@ -164,7 +163,13 @@ void MainUIHandler::update_ui_() {
ESP_LOGI(TAG, "Calling main_ui_->update_status() with ui_state: %d", ui_state); ESP_LOGI(TAG, "Calling main_ui_->update_status() with ui_state: %d", ui_state);
// Lock LVGL before calling UI functions from another task // Lock LVGL before calling UI functions from another task
main_ui_->update_status(ui_state); bool success = main_ui_->update_status(ui_state);
if (!success) {
ESP_LOGW(TAG, "main_ui_->update_status() failed");
} else {
// Update current state only on successful UI update
current_state_ = state;
}
ESP_LOGI(TAG, "main_ui_->update_status() returned"); ESP_LOGI(TAG, "main_ui_->update_status() returned");
} }

View File

@@ -35,7 +35,7 @@ private:
void on_mute_button_clicked_(); void on_mute_button_clicked_();
void on_status_update_(StatusUpdateEventData data); void on_status_update_(StatusUpdateEventData data);
void send_mute_command_(); void send_mute_command_();
void update_ui_(); void update_ui_(StatusUpdateEventData::VoiceState* state = nullptr);
std::unique_ptr<MainUI> main_ui_ = nullptr; std::unique_ptr<MainUI> main_ui_ = nullptr;
std::unique_ptr<IotDisBridge> bridge_ = nullptr; std::unique_ptr<IotDisBridge> bridge_ = nullptr;
@@ -49,4 +49,3 @@ private:
lv_event_cb_t on_settings_callback_ = nullptr; lv_event_cb_t on_settings_callback_ = nullptr;
void* settings_callback_user_data_ = nullptr; void* settings_callback_user_data_ = nullptr;
}; };