Compare commits
4 Commits
f7cedf24e8
...
ccdc2bb63f
| Author | SHA1 | Date | |
|---|---|---|---|
|
ccdc2bb63f
|
|||
|
7d12d98ec9
|
|||
|
cdac9cbfb8
|
|||
|
1fade06bdb
|
@@ -13,4 +13,5 @@ idf_component_register(SRCS
|
||||
json
|
||||
simulator
|
||||
persistence-manager
|
||||
message-manager
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "api_handlers.h"
|
||||
#include "common.h"
|
||||
#include "message_manager.h"
|
||||
|
||||
#include <cJSON.h>
|
||||
#include <esp_http_server.h>
|
||||
@@ -255,7 +256,22 @@ esp_err_t api_light_power_handler(httpd_req_t *req)
|
||||
|
||||
ESP_LOGI(TAG, "Received light power: %s", buf);
|
||||
|
||||
// TODO: Parse JSON and control light
|
||||
cJSON *json = cJSON_Parse(buf);
|
||||
if (json)
|
||||
{
|
||||
cJSON *active = cJSON_GetObjectItem(json, "on");
|
||||
if (cJSON_IsBool(active))
|
||||
{
|
||||
message_t msg = {};
|
||||
msg.type = MESSAGE_TYPE_SETTINGS;
|
||||
msg.data.settings.type = SETTINGS_TYPE_BOOL;
|
||||
strncpy(msg.data.settings.key, "light_active", sizeof(msg.data.settings.key) - 1);
|
||||
msg.data.settings.value.bool_value = cJSON_IsTrue(active);
|
||||
message_manager_post(&msg, pdMS_TO_TICKS(100));
|
||||
}
|
||||
cJSON_Delete(json);
|
||||
}
|
||||
|
||||
set_cors_headers(req);
|
||||
return httpd_resp_sendstr(req, "{\"status\":\"ok\"}");
|
||||
}
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
#include <cJSON.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "persistence_manager.h"
|
||||
|
||||
// Gibt ein cJSON-Objekt with dem aktuellen Lichtstatus zurück
|
||||
cJSON *create_light_status_json(void)
|
||||
{
|
||||
persistence_manager_t pm;
|
||||
persistence_manager_init(&pm, "config");
|
||||
cJSON *json = cJSON_CreateObject();
|
||||
// TODO: Echte Werte einfügen, aktuell Dummy-Daten
|
||||
cJSON_AddBoolToObject(json, "on", false);
|
||||
|
||||
bool light_active = persistence_manager_get_bool(&pm, "light_active", false);
|
||||
cJSON_AddBoolToObject(json, "on", light_active);
|
||||
cJSON_AddBoolToObject(json, "thunder", false);
|
||||
cJSON_AddStringToObject(json, "mode", "day");
|
||||
cJSON_AddStringToObject(json, "schema", "schema_03.csv");
|
||||
@@ -16,5 +21,8 @@ cJSON *create_light_status_json(void)
|
||||
cJSON_AddNumberToObject(color, "g", 240);
|
||||
cJSON_AddNumberToObject(color, "b", 220);
|
||||
cJSON_AddItemToObject(json, "color", color);
|
||||
|
||||
persistence_manager_deinit(&pm);
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "websocket_handler.h"
|
||||
#include "api_server.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "message_manager.h"
|
||||
#include <esp_http_server.h>
|
||||
#include <esp_log.h>
|
||||
#include <string.h>
|
||||
@@ -11,6 +13,16 @@ static const char *TAG = "websocket_handler";
|
||||
static int ws_clients[WS_MAX_CLIENTS];
|
||||
static int ws_client_count = 0;
|
||||
|
||||
static void on_message_received(const message_t *msg)
|
||||
{
|
||||
cJSON *json = create_light_status_json();
|
||||
cJSON_AddStringToObject(json, "type", "status");
|
||||
char *response = cJSON_PrintUnformatted(json);
|
||||
cJSON_Delete(json);
|
||||
api_server_ws_broadcast(response);
|
||||
free(response);
|
||||
}
|
||||
|
||||
static void ws_clients_init(void)
|
||||
{
|
||||
for (int i = 0; i < WS_MAX_CLIENTS; i++)
|
||||
@@ -179,6 +191,8 @@ static void ws_async_send(void *arg)
|
||||
|
||||
esp_err_t websocket_handler_init(httpd_handle_t server)
|
||||
{
|
||||
message_manager_register_listener(on_message_received);
|
||||
|
||||
ws_clients_init();
|
||||
// Register WebSocket URI handler
|
||||
httpd_uri_t ws_uri = {.uri = "/ws",
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -18,4 +18,5 @@ idf_component_register(SRCS
|
||||
led-manager
|
||||
persistence-manager
|
||||
simulator
|
||||
message-manager
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "ui/LightMenu.h"
|
||||
|
||||
#include "led_strip_ws2812.h"
|
||||
#include "message_manager.h"
|
||||
#include "simulator.h"
|
||||
#include <cstring>
|
||||
|
||||
/**
|
||||
* @namespace LightMenuItem
|
||||
@@ -71,12 +72,13 @@ void LightMenu::onButtonPressed(const MenuItem &menuItem, const ButtonType butto
|
||||
{
|
||||
toggle(menuItem);
|
||||
const auto value = getItem(menuItem.getId()).getValue() == "1";
|
||||
if (m_options && m_options->persistenceManager)
|
||||
{
|
||||
persistence_manager_set_bool(m_options->persistenceManager, LightMenuOptions::LIGHT_ACTIVE, value);
|
||||
}
|
||||
|
||||
start_simulation();
|
||||
// Post change via message_manager
|
||||
message_t msg = {};
|
||||
msg.type = MESSAGE_TYPE_SETTINGS;
|
||||
msg.data.settings.type = SETTINGS_TYPE_BOOL;
|
||||
strncpy(msg.data.settings.key, LightMenuOptions::LIGHT_ACTIVE, sizeof(msg.data.settings.key) - 1);
|
||||
msg.data.settings.value.bool_value = value;
|
||||
message_manager_post(&msg, pdMS_TO_TICKS(100));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -127,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)
|
||||
|
||||
6
firmware/components/message-manager/CMakeLists.txt
Normal file
6
firmware/components/message-manager/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
idf_component_register(
|
||||
SRCS "src/message_manager.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES
|
||||
persistence-manager
|
||||
)
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MESSAGE_TYPE_SETTINGS,
|
||||
MESSAGE_TYPE_BUTTON
|
||||
} message_type_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUTTON_EVENT_PRESS,
|
||||
BUTTON_EVENT_RELEASE
|
||||
} button_event_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
button_event_type_t event_type;
|
||||
uint8_t button_id;
|
||||
} button_message_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SETTINGS_TYPE_BOOL,
|
||||
SETTINGS_TYPE_INT,
|
||||
SETTINGS_TYPE_FLOAT,
|
||||
SETTINGS_TYPE_STRING
|
||||
} settings_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
settings_type_t type;
|
||||
char key[32];
|
||||
union {
|
||||
bool bool_value;
|
||||
int32_t int_value;
|
||||
float float_value;
|
||||
char string_value[64];
|
||||
} value;
|
||||
} settings_message_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
message_type_t type;
|
||||
union {
|
||||
settings_message_t settings;
|
||||
button_message_t button;
|
||||
} data;
|
||||
} message_t;
|
||||
|
||||
// Observer Pattern: Listener-Typ und Registrierungsfunktionen
|
||||
typedef void (*message_listener_t)(const message_t *msg);
|
||||
void message_manager_register_listener(message_listener_t listener);
|
||||
void message_manager_unregister_listener(message_listener_t listener);
|
||||
void message_manager_init(void);
|
||||
bool message_manager_post(const message_t *msg, TickType_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
106
firmware/components/message-manager/src/message_manager.c
Normal file
106
firmware/components/message-manager/src/message_manager.c
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "message_manager.h"
|
||||
#include <esp_log.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/task.h>
|
||||
#include <persistence_manager.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MESSAGE_QUEUE_LENGTH 16
|
||||
#define MESSAGE_QUEUE_ITEM_SIZE sizeof(message_t)
|
||||
|
||||
static const char *TAG = "message_manager";
|
||||
static QueueHandle_t message_queue = NULL;
|
||||
|
||||
// Observer Pattern: Listener-Liste
|
||||
#define MAX_MESSAGE_LISTENERS 8
|
||||
static message_listener_t message_listeners[MAX_MESSAGE_LISTENERS] = {0};
|
||||
static size_t message_listener_count = 0;
|
||||
|
||||
void message_manager_register_listener(message_listener_t listener) {
|
||||
if (listener && message_listener_count < MAX_MESSAGE_LISTENERS) {
|
||||
// Doppelte Registrierung vermeiden
|
||||
for (size_t i = 0; i < message_listener_count; ++i) {
|
||||
if (message_listeners[i] == listener) return;
|
||||
}
|
||||
message_listeners[message_listener_count++] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
void message_manager_unregister_listener(message_listener_t listener) {
|
||||
for (size_t i = 0; i < message_listener_count; ++i) {
|
||||
if (message_listeners[i] == listener) {
|
||||
// Nachfolgende Listener nach vorne schieben
|
||||
for (size_t j = i; j < message_listener_count - 1; ++j) {
|
||||
message_listeners[j] = message_listeners[j + 1];
|
||||
}
|
||||
message_listeners[--message_listener_count] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void message_manager_task(void *param)
|
||||
{
|
||||
message_t msg;
|
||||
persistence_manager_t pm;
|
||||
while (1)
|
||||
{
|
||||
if (xQueueReceive(message_queue, &msg, portMAX_DELAY) == pdTRUE)
|
||||
{
|
||||
switch (msg.type)
|
||||
{
|
||||
case MESSAGE_TYPE_SETTINGS:
|
||||
if (persistence_manager_init(&pm, "config") == ESP_OK)
|
||||
{
|
||||
switch (msg.data.settings.type)
|
||||
{
|
||||
case SETTINGS_TYPE_BOOL:
|
||||
persistence_manager_set_bool(&pm, msg.data.settings.key, msg.data.settings.value.bool_value);
|
||||
break;
|
||||
case SETTINGS_TYPE_INT:
|
||||
persistence_manager_set_int(&pm, msg.data.settings.key, msg.data.settings.value.int_value);
|
||||
break;
|
||||
case SETTINGS_TYPE_FLOAT:
|
||||
persistence_manager_set_float(&pm, msg.data.settings.key, msg.data.settings.value.float_value);
|
||||
break;
|
||||
case SETTINGS_TYPE_STRING:
|
||||
persistence_manager_set_string(&pm, msg.data.settings.key,
|
||||
msg.data.settings.value.string_value);
|
||||
break;
|
||||
}
|
||||
persistence_manager_deinit(&pm);
|
||||
ESP_LOGI(TAG, "Setting written: %s", msg.data.settings.key);
|
||||
}
|
||||
break;
|
||||
case MESSAGE_TYPE_BUTTON:
|
||||
ESP_LOGI(TAG, "Button event: id=%d, type=%d", msg.data.button.button_id, msg.data.button.event_type);
|
||||
// TODO: Weiterverarbeitung/Callback für Button-Events
|
||||
break;
|
||||
}
|
||||
// Observer Pattern: Listener benachrichtigen
|
||||
for (size_t i = 0; i < message_listener_count; ++i) {
|
||||
if (message_listeners[i]) {
|
||||
message_listeners[i](&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void message_manager_init(void)
|
||||
{
|
||||
if (!message_queue)
|
||||
{
|
||||
message_queue = xQueueCreate(MESSAGE_QUEUE_LENGTH, MESSAGE_QUEUE_ITEM_SIZE);
|
||||
xTaskCreate(message_manager_task, "message_manager_task", 4096, NULL, 5, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool message_manager_post(const message_t *msg, TickType_t timeout)
|
||||
{
|
||||
if (!message_queue)
|
||||
return false;
|
||||
ESP_LOGI(TAG, "Post: type=%d", msg->type);
|
||||
return xQueueSend(message_queue, msg, timeout) == pdTRUE;
|
||||
}
|
||||
@@ -9,12 +9,20 @@ typedef struct
|
||||
int cycle_duration_minutes;
|
||||
} simulation_config_t;
|
||||
|
||||
char *get_time(void);
|
||||
esp_err_t add_light_item(const char time[5], uint8_t red, uint8_t green, uint8_t blue, uint8_t white,
|
||||
uint8_t brightness, uint8_t saturation);
|
||||
void cleanup_light_items(void);
|
||||
void start_simulate_day(void);
|
||||
void start_simulate_night(void);
|
||||
void start_simulation_task(void);
|
||||
void stop_simulation_task(void);
|
||||
void start_simulation(void);
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
char *get_time(void);
|
||||
esp_err_t add_light_item(const char time[5], uint8_t red, uint8_t green, uint8_t blue, uint8_t white,
|
||||
uint8_t brightness, uint8_t saturation);
|
||||
void cleanup_light_items(void);
|
||||
void start_simulate_day(void);
|
||||
void start_simulate_night(void);
|
||||
void start_simulation_task(void);
|
||||
void stop_simulation_task(void);
|
||||
void start_simulation(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -7,12 +7,14 @@
|
||||
#include "hal/u8g2_esp32_hal.h"
|
||||
#include "i2c_checker.h"
|
||||
#include "led_status.h"
|
||||
#include "message_manager.h"
|
||||
#include "persistence_manager.h"
|
||||
#include "simulator.h"
|
||||
#include "ui/ClockScreenSaver.h"
|
||||
#include "ui/ScreenSaver.h"
|
||||
#include "ui/SplashScreen.h"
|
||||
#include "wifi_manager.h"
|
||||
#include <cstring>
|
||||
#include <driver/i2c.h>
|
||||
#include <esp_diagnostics.h>
|
||||
#include <esp_insights.h>
|
||||
@@ -126,6 +128,15 @@ static void init_ui(void)
|
||||
u8g2_SendBuffer(&u8g2);
|
||||
}
|
||||
|
||||
static void on_message_received(const message_t *msg)
|
||||
{
|
||||
if (msg && msg->type == MESSAGE_TYPE_SETTINGS && msg->data.settings.type == SETTINGS_TYPE_BOOL &&
|
||||
std::strcmp(msg->data.settings.key, "light_active") == 0)
|
||||
{
|
||||
start_simulation();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_button(uint8_t button)
|
||||
{
|
||||
m_inactivityTracker->reset();
|
||||
@@ -232,11 +243,15 @@ void app_task(void *args)
|
||||
}
|
||||
}
|
||||
|
||||
message_manager_init();
|
||||
|
||||
setup_buttons();
|
||||
init_ui();
|
||||
|
||||
wifi_manager_init();
|
||||
|
||||
message_manager_register_listener(on_message_received);
|
||||
|
||||
start_simulation();
|
||||
|
||||
auto oldTime = esp_timer_get_time();
|
||||
|
||||
Reference in New Issue
Block a user