feat: Implement button creation utility and refactor UI components for improved readability

This commit is contained in:
GW_MC
2026-02-03 15:20:35 +08:00
parent f5fae825d6
commit 7bd230f591
5 changed files with 67 additions and 86 deletions

View File

@@ -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,44 +151,49 @@ 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;
}
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_);
}
// Got push update, skip polling
if (event_data.state != StatusUpdateEventData::VoiceState::UNKNOWN) {
return;
} else {
ESP_LOGW(TAG, "Received unknown message: %s", message.c_str());
}
}
// Send STATUS command for polling
ESP_LOGI(TAG, "Sending STATUS command for polling");
} 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 for polling. Consecutive failures: %d",
ESP_LOGW(TAG, "Failed to send STATUS command. Consecutive failures: %d",
consecutive_failures_);
if (consecutive_failures_ >= MAX_FAILURES_BEFORE_ERROR) {
@@ -209,41 +204,14 @@ void IotDisBridge::poll_status_() {
);
}
}
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");
}

View File

@@ -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);

View File

@@ -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;
}

4
main/ui/widgets/button.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include "lvgl.h"
lv_obj_t* button_create(lv_obj_t* parent);

View File

@@ -0,0 +1,4 @@
#pragma once
#include "main/ui/widgets/button.h"
#include "main/ui/widgets/textarea.h"