refresh device ui after REST call

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2026-01-18 15:12:09 +01:00
parent cdac9cbfb8
commit 7d12d98ec9
7 changed files with 96 additions and 21 deletions

View File

@@ -29,6 +29,18 @@ static EventGroupHandle_t s_wifi_event_group;
static const char *TAG = "wifi_manager";
static void led_status_reconnect()
{
led_behavior_t led_behavior = {
.on_time_ms = 250,
.off_time_ms = 100,
.color = {.red = 50, .green = 50, .blue = 0},
.index = 0,
.mode = LED_MODE_BLINK,
};
led_status_set_behavior(led_behavior);
}
static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
@@ -40,6 +52,8 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e
{
ESP_LOGW(TAG, "WIFI_EVENT_STA_DISCONNECTED: Verbindung verloren, versuche erneut...");
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
led_status_reconnect();
esp_wifi_connect();
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
@@ -49,8 +63,10 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t e
}
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP)
{
ESP_LOGW(TAG, "IP_EVENT_STA_LOST_IP: IP-Adresse verloren!");
ESP_LOGW(TAG, "IP_EVENT_STA_LOST_IP: IP-Adresse verloren! Versuche Reconnect...");
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
led_status_reconnect();
esp_wifi_connect();
}
}
@@ -105,14 +121,7 @@ void wifi_manager_init()
if (have_ssid && have_password)
{
led_behavior_t led_behavior = {
.on_time_ms = 250,
.off_time_ms = 100,
.color = {.red = 50, .green = 50, .blue = 0},
.index = 0,
.mode = LED_MODE_BLINK,
};
led_status_set_behavior(led_behavior);
led_status_reconnect();
ESP_LOGI(TAG, "Found WiFi configuration: SSID='%s'", ssid);
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

View File

@@ -175,6 +175,21 @@ class Menu : public Widget
*/
void toggle(const MenuItem &menuItem);
/**
* @brief Setzt den Zustand eines Toggle-Menüeintrags explizit
* @param menuItem Der zu ändernde Toggle-Menüeintrag
* @param state Neuer Zustand (true = aktiviert, false = deaktiviert)
*
* @pre menuItem muss vom Typ TOGGLE sein
* @post Der Wert des Menüeintrags wird auf den angegebenen Zustand gesetzt
*
* @details Diese Methode setzt den Wert eines Toggle-Menüeintrags gezielt auf den gewünschten Zustand.
* Der geänderte Eintrag ersetzt das Original in der internen Menüstruktur.
*
* @note Diese Methode verändert direkt den internen Zustand des Menüs.
*/
void setToggle(const MenuItem &menuItem, const bool state);
/**
* @brief Changes the selected value of a selection menu item based on button input
* @param menuItem The selection menu item to modify

View File

@@ -13,6 +13,7 @@
#include "u8g2.h"
#include "common/Common.h"
#include "message_manager.h"
/**
* @class Widget
@@ -49,7 +50,9 @@ class Widget
* @details Ensures that derived class destructors are called correctly when
* a widget is destroyed through a base class pointer.
*/
virtual ~Widget() = default;
virtual ~Widget();
virtual void onMessageReceived(const message_t *msg);
/**
* @brief Called when the widget becomes active or enters the foreground
@@ -178,4 +181,8 @@ class Widget
* the u8g2 context and assumes it is managed externally.
*/
u8g2_t *u8g2;
private:
static std::vector<Widget *> s_instances;
static void globalMessageCallback(const message_t *msg);
};

View File

@@ -120,6 +120,8 @@ class LightMenu final : public Menu
*/
void onButtonPressed(const MenuItem &menuItem, ButtonType button) override;
void onMessageReceived(const message_t *msg);
/**
* @brief Pointer to menu options configuration structure
* @details Stores a reference to the menu configuration passed during construction.

View File

@@ -28,7 +28,7 @@ constexpr int BOTTOM_OFFSET = 10;
Menu::Menu(menu_options_t *options) : Widget(options->u8g2), m_options(options)
{
// Set up button callback using lambda to forward to member function
// Set up button callback using a lambda to forward to the member function
m_options->onButtonClicked = [this](const ButtonType button) { OnButtonClicked(button); };
}
@@ -82,6 +82,12 @@ void Menu::toggle(const MenuItem &menuItem)
replaceItem(menuItem.getId(), item);
}
void Menu::setToggle(const MenuItem &menuItem, const bool state)
{
const auto item = menuItem.copyWith(state ? std::to_string(true) : std::to_string(false));
replaceItem(menuItem.getId(), item);
}
MenuItem Menu::switchValue(const MenuItem &menuItem, ButtonType button)
{
MenuItem result = menuItem;
@@ -134,13 +140,13 @@ void Menu::Render()
m_selected_item = 0;
}
// Early return if no items to render
// Early return if there are no items to render
if (m_items.empty())
{
return;
}
// Clear screen with black background
// Clear the screen with a black background
u8g2_SetDrawColor(u8g2, 0);
u8g2_DrawBox(u8g2, 0, 0, u8g2->width, u8g2->height);
@@ -151,7 +157,7 @@ void Menu::Render()
drawScrollBar();
drawSelectionBox();
// Calculate center position for main item
// Calculate center position for the main item
const int centerY = u8g2->height / 2 + 3;
// Render the currently selected item (main/center item)
@@ -176,7 +182,7 @@ void Menu::Render()
void Menu::renderWidget(const MenuItem *item, const uint8_t *font, const int x, const int y) const
{
// Set font and draw main text
// Set font and draw the main text
u8g2_SetFont(u8g2, font);
u8g2_DrawStr(u8g2, x, y, item->getText().c_str());
@@ -206,7 +212,7 @@ void Menu::renderWidget(const MenuItem *item, const uint8_t *font, const int x,
}
case MenuItemTypes::TOGGLE: {
// Draw checkbox frame
// Draw the checkbox frame
const int frameX = u8g2->width - UIConstants::FRAME_BOX_SIZE - UIConstants::SELECTION_MARGIN;
const int frameY = y - UIConstants::FRAME_OFFSET;
u8g2_DrawFrame(u8g2, frameX, frameY, UIConstants::FRAME_BOX_SIZE, UIConstants::FRAME_BOX_SIZE);
@@ -272,7 +278,7 @@ void Menu::onPressedDown()
if (m_items.empty())
return;
// Wrap around to first item when at the end
// Wrap around to the first item when at the end
m_selected_item = (m_selected_item + 1) % m_items.size();
}
@@ -281,7 +287,7 @@ void Menu::onPressedUp()
if (m_items.empty())
return;
// Wrap around to last item when at the beginning
// Wrap around to the last item when at the beginning
m_selected_item = (m_selected_item == 0) ? m_items.size() - 1 : m_selected_item - 1;
}
@@ -314,7 +320,7 @@ void Menu::onPressedSelect() const
void Menu::onPressedBack() const
{
// Navigate back to previous screen if callback is available
// Navigate back to the previous screen if callback is available
if (m_options && m_options->popScreen)
{
m_options->popScreen();

View File

@@ -1,7 +1,20 @@
#include "common/Widget.h"
#include <algorithm>
std::vector<Widget *> Widget::s_instances;
Widget::Widget(u8g2_t *u8g2) : u8g2(u8g2)
{
s_instances.push_back(this);
if (s_instances.size() == 1)
{
message_manager_register_listener(globalMessageCallback);
}
}
Widget::~Widget()
{
s_instances.erase(std::remove(s_instances.begin(), s_instances.end(), this), s_instances.end());
}
void Widget::onEnter()
@@ -36,3 +49,15 @@ const char *Widget::getName() const
{
return "Widget";
}
void Widget::onMessageReceived(const message_t *msg)
{
}
void Widget::globalMessageCallback(const message_t *msg)
{
for (auto *w : s_instances)
{
w->onMessageReceived(msg);
}
}

View File

@@ -1,8 +1,8 @@
#include "ui/LightMenu.h"
#include "led_strip_ws2812.h"
#include "message_manager.h"
#include "simulator.h"
#include <cstring>
/**
* @namespace LightMenuItem
@@ -72,7 +72,7 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
{
toggle(menuItem);
const auto value = getItem(menuItem.getId()).getValue() == "1";
// Änderung über message_manager posten
// Post change via message_manager
message_t msg = {};
msg.type = MESSAGE_TYPE_SETTINGS;
msg.data.settings.type = SETTINGS_TYPE_BOOL;
@@ -129,4 +129,15 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
}
}
void LightMenu::onMessageReceived(const message_t *msg)
{
// Here you can react to messages, e.g. set toggle status
// Example: If light_active was changed, synchronize toggle
if (msg && msg->type == MESSAGE_TYPE_SETTINGS && msg->data.settings.type == SETTINGS_TYPE_BOOL &&
std::strcmp(msg->data.settings.key, "light_active") == 0)
{
setToggle(getItem(LightMenuItem::ACTIVATE), msg->data.settings.value.bool_value);
}
}
IMPLEMENT_GET_NAME(LightMenu)