From 7bd230f591e7939a5b85fb6e3b98154ffeba791d Mon Sep 17 00:00:00 2001 From: GW_MC <72297530+GWMCwing@users.noreply.github.com> Date: Tue, 3 Feb 2026 15:20:35 +0800 Subject: [PATCH] feat: Implement button creation utility and refactor UI components for improved readability --- main/ui/apps/iotdis/bridge/bridge.cpp | 120 +++++++++----------------- main/ui/apps/iotdis/ui/main.cpp | 13 +-- main/ui/widgets/button.cpp | 12 +++ main/ui/widgets/button.h | 4 + main/ui/widgets/widgets.h | 4 + 5 files changed, 67 insertions(+), 86 deletions(-) create mode 100644 main/ui/widgets/button.cpp create mode 100644 main/ui/widgets/button.h create mode 100644 main/ui/widgets/widgets.h diff --git a/main/ui/apps/iotdis/bridge/bridge.cpp b/main/ui/apps/iotdis/bridge/bridge.cpp index 59bedcf..f859537 100644 --- a/main/ui/apps/iotdis/bridge/bridge.cpp +++ b/main/ui/apps/iotdis/bridge/bridge.cpp @@ -135,19 +135,9 @@ void IotDisBridge::poll_task_(void* param) { ESP_LOGI(TAG, "Polling task started"); while (!bridge->stop_polling_) { - ESP_LOGI(TAG, "Polling for status update..."); bridge->poll_status_(); - ESP_LOGI(TAG, "poll_status_() returned"); - - // Yield to allow display updates to complete + // Yield to allow other tasks to run taskYIELD(); - - // Use longer interval if in error state - int interval = (bridge->consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) - ? ERROR_POLL_INTERVAL_MS - : POLL_INTERVAL_MS; - ESP_LOGI(TAG, "Next poll in %d ms", interval); - vTaskDelay(pdMS_TO_TICKS(interval)); } ESP_LOGI(TAG, "Polling task stopped"); @@ -161,89 +151,67 @@ void IotDisBridge::poll_status_() { return; } - // First check for any unsolicited push messages (non-blocking) - std::string push_message; - esp_err_t err = udp_client_.receive_response(push_message, 0); // 0 = non-blocking + // Continuously listen for messages (blocking with timeout) + // Use longer timeout if in error state + int listen_timeout = (consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) + ? ERROR_POLL_INTERVAL_MS + : POLL_INTERVAL_MS; + + ESP_LOGI(TAG, "Listening for messages (timeout: %dms)", listen_timeout); + std::string message; + esp_err_t err = udp_client_.receive_response(message, listen_timeout); + + if (err == ESP_OK && !message.empty()) { + // Received a message (either push update or status response) + ESP_LOGI(TAG, "Received message: %s", message.c_str()); - if (err == ESP_OK && !push_message.empty()) { - // Received push update from remote - ESP_LOGI(TAG, "Received push update: %s", push_message.c_str()); StatusUpdateEventData event_data { .state = StatusUpdateEventData::VoiceState::UNKNOWN }; - if (push_message == MUTED_RESPONSE) { + if (message == MUTED_RESPONSE) { event_data.state = StatusUpdateEventData::VoiceState::MUTED; - } else if (push_message == UNMUTED_RESPONSE) { + } else if (message == UNMUTED_RESPONSE) { event_data.state = StatusUpdateEventData::VoiceState::UNMUTED; } - // Reset failure counter on successful push update + // Reset failure counter on successful message if (event_data.state != StatusUpdateEventData::VoiceState::UNKNOWN) { consecutive_failures_ = 0; - } - if (on_status_update_callback_) { - on_status_update_callback_(event_data, status_event_user_data_); - } - - // Got push update, skip polling - if (event_data.state != StatusUpdateEventData::VoiceState::UNKNOWN) { - return; - } - } - - // Send STATUS command for polling - ESP_LOGI(TAG, "Sending STATUS command for polling"); - err = udp_client_.send_command(STATUS_COMMAND); - if (err != ESP_OK) { - consecutive_failures_++; - ESP_LOGW(TAG, "Failed to send STATUS command for polling. Consecutive failures: %d", - consecutive_failures_); - - if (consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) { + ESP_LOGI(TAG, "Invoking status update callback with state: %d", event_data.state); if (on_status_update_callback_) { - on_status_update_callback_( - StatusUpdateEventData { .state = StatusUpdateEventData::VoiceState::ERROR }, - status_event_user_data_ - ); + on_status_update_callback_(event_data, status_event_user_data_); + } + } else { + ESP_LOGW(TAG, "Received unknown message: %s", message.c_str()); + } + } else if (err == ESP_ERR_TIMEOUT) { + // Timeout - send STATUS command to verify connection is still alive + ESP_LOGI(TAG, "Listen timeout, sending STATUS command to verify connection"); + err = udp_client_.send_command(STATUS_COMMAND); + + if (err != ESP_OK) { + consecutive_failures_++; + ESP_LOGW(TAG, "Failed to send STATUS command. Consecutive failures: %d", + consecutive_failures_); + + if (consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) { + if (on_status_update_callback_) { + on_status_update_callback_( + StatusUpdateEventData { .state = StatusUpdateEventData::VoiceState::ERROR }, + status_event_user_data_ + ); + } } } - return; - } - - // Wait for response to STATUS command - ESP_LOGI(TAG, "Waiting for response to STATUS command (timeout: %dms)", RESPONSE_TIMEOUT_MS); - std::string response; - err = udp_client_.receive_response(response, RESPONSE_TIMEOUT_MS); - ESP_LOGI(TAG, "Received response from STATUS command: err=%d", err); - - if (err == ESP_OK) { - // Success - reset failure counter - consecutive_failures_ = 0; - ESP_LOGI(TAG, "STATUS response: %s", response.c_str()); - - StatusUpdateEventData event_data { - .state = StatusUpdateEventData::VoiceState::UNKNOWN - }; - if (response == MUTED_RESPONSE) { - event_data.state = StatusUpdateEventData::VoiceState::MUTED; - } else if (response == UNMUTED_RESPONSE) { - event_data.state = StatusUpdateEventData::VoiceState::UNMUTED; - } - - ESP_LOGI(TAG, "Invoking status update callback with state: %d", event_data.state); - if (on_status_update_callback_) { - on_status_update_callback_(event_data, status_event_user_data_); - ESP_LOGI(TAG, "Status update callback returned"); - } + // The response to STATUS command will be received in the next iteration } else { - // Timeout or error + // Error receiving consecutive_failures_++; - ESP_LOGW(TAG, "No response to STATUS (failures: %d, error: %d)", consecutive_failures_, err); + ESP_LOGW(TAG, "Error receiving message: %d (failures: %d)", err, consecutive_failures_); if (consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) { - ESP_LOGW(TAG, "Max failures reached, sending ERROR state"); if (on_status_update_callback_) { on_status_update_callback_( StatusUpdateEventData { .state = StatusUpdateEventData::VoiceState::ERROR }, @@ -252,6 +220,4 @@ void IotDisBridge::poll_status_() { } } } - - ESP_LOGI(TAG, "poll_status_ complete"); } \ No newline at end of file diff --git a/main/ui/apps/iotdis/ui/main.cpp b/main/ui/apps/iotdis/ui/main.cpp index 115c940..c49af57 100644 --- a/main/ui/apps/iotdis/ui/main.cpp +++ b/main/ui/apps/iotdis/ui/main.cpp @@ -1,10 +1,11 @@ #include "ui/apps/iotdis/ui/main.h" #include "ui/apps/iotdis/app.h" #include "ui/interaction_handler.h" +#include "ui/widgets/button.h" #include "esp_log.h" #include "esp_lvgl_port.h" -#define LVGL_LOCK_TIMEOUT 2000 // milliseconds +#define LVGL_LOCK_TIMEOUT 4000 // milliseconds static const char* TAG = "MainUI"; MainUI::~MainUI() { @@ -82,11 +83,8 @@ void MainUI::create_ui_(lv_obj_t* parent) { lv_label_set_text(status_text_label_, "Unknown Status"); // Mute button - mute_button_ = lv_btn_create(center_container); + mute_button_ = button_create(center_container); 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_label_set_text(mute_label, "MUTE"); lv_obj_center(mute_label); @@ -107,11 +105,8 @@ void MainUI::create_ui_(lv_obj_t* parent) { lv_obj_set_style_text_color(config_prompt_, lv_color_black(), 0); // Settings button (right side) - settings_button_ = lv_btn_create(bottom_container); + settings_button_ = button_create(bottom_container); 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_label_set_text(settings_icon, LV_SYMBOL_SETTINGS); diff --git a/main/ui/widgets/button.cpp b/main/ui/widgets/button.cpp new file mode 100644 index 0000000..b58f32b --- /dev/null +++ b/main/ui/widgets/button.cpp @@ -0,0 +1,12 @@ +#include "ui/widgets/button.h" + +lv_obj_t* button_create(lv_obj_t* parent) { + lv_obj_t* button = lv_button_create(parent); + lv_obj_set_style_bg_color(button, lv_color_white(), 0); + lv_obj_set_style_border_color(button, lv_color_black(), 0); + lv_obj_set_style_border_width(button, 2, 0); + lv_anim_delete(button, nullptr); + + return button; +} + diff --git a/main/ui/widgets/button.h b/main/ui/widgets/button.h new file mode 100644 index 0000000..30e9d72 --- /dev/null +++ b/main/ui/widgets/button.h @@ -0,0 +1,4 @@ +#pragma once +#include "lvgl.h" + +lv_obj_t* button_create(lv_obj_t* parent); diff --git a/main/ui/widgets/widgets.h b/main/ui/widgets/widgets.h new file mode 100644 index 0000000..029cc71 --- /dev/null +++ b/main/ui/widgets/widgets.h @@ -0,0 +1,4 @@ +#pragma once + +#include "main/ui/widgets/button.h" +#include "main/ui/widgets/textarea.h"