From 1fade06bdb75819505c4011a2b73ca3c012da28f Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Sun, 18 Jan 2026 14:13:05 +0100 Subject: [PATCH] light on/off via REST or GPIO Signed-off-by: Peter Siegmund --- firmware/components/api-server/CMakeLists.txt | 1 + .../components/api-server/src/api_handlers.c | 18 ++++- firmware/components/insa/CMakeLists.txt | 1 + firmware/components/insa/src/ui/LightMenu.cpp | 14 ++-- .../components/message-manager/CMakeLists.txt | 6 ++ .../message-manager/include/message_manager.h | 65 +++++++++++++++ .../message-manager/src/message_manager.c | 79 +++++++++++++++++++ .../components/simulator/include/simulator.h | 26 +++--- firmware/main/app_task.cpp | 3 + 9 files changed, 197 insertions(+), 16 deletions(-) create mode 100644 firmware/components/message-manager/CMakeLists.txt create mode 100644 firmware/components/message-manager/include/message_manager.h create mode 100644 firmware/components/message-manager/src/message_manager.c diff --git a/firmware/components/api-server/CMakeLists.txt b/firmware/components/api-server/CMakeLists.txt index 0d289d1..6f49796 100644 --- a/firmware/components/api-server/CMakeLists.txt +++ b/firmware/components/api-server/CMakeLists.txt @@ -13,4 +13,5 @@ idf_component_register(SRCS json simulator persistence-manager + message-manager ) diff --git a/firmware/components/api-server/src/api_handlers.c b/firmware/components/api-server/src/api_handlers.c index 043e220..fb47a8d 100644 --- a/firmware/components/api-server/src/api_handlers.c +++ b/firmware/components/api-server/src/api_handlers.c @@ -1,5 +1,6 @@ #include "api_handlers.h" #include "common.h" +#include "message_manager.h" #include #include @@ -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\"}"); } diff --git a/firmware/components/insa/CMakeLists.txt b/firmware/components/insa/CMakeLists.txt index 6c3388d..3e5360f 100644 --- a/firmware/components/insa/CMakeLists.txt +++ b/firmware/components/insa/CMakeLists.txt @@ -18,4 +18,5 @@ idf_component_register(SRCS led-manager persistence-manager simulator + message-manager ) diff --git a/firmware/components/insa/src/ui/LightMenu.cpp b/firmware/components/insa/src/ui/LightMenu.cpp index bc556c5..1ae2885 100644 --- a/firmware/components/insa/src/ui/LightMenu.cpp +++ b/firmware/components/insa/src/ui/LightMenu.cpp @@ -1,6 +1,7 @@ #include "ui/LightMenu.h" #include "led_strip_ws2812.h" +#include "message_manager.h" #include "simulator.h" /** @@ -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(); + // Änderung über message_manager posten + 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; } diff --git a/firmware/components/message-manager/CMakeLists.txt b/firmware/components/message-manager/CMakeLists.txt new file mode 100644 index 0000000..74259a9 --- /dev/null +++ b/firmware/components/message-manager/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register( + SRCS "src/message_manager.c" + INCLUDE_DIRS "include" + PRIV_REQUIRES + persistence-manager +) diff --git a/firmware/components/message-manager/include/message_manager.h b/firmware/components/message-manager/include/message_manager.h new file mode 100644 index 0000000..6274aa3 --- /dev/null +++ b/firmware/components/message-manager/include/message_manager.h @@ -0,0 +1,65 @@ +#pragma once + +#include +#include +#include +#include + +#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; + + void message_manager_init(void); + bool message_manager_post(const message_t *msg, TickType_t timeout); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/components/message-manager/src/message_manager.c b/firmware/components/message-manager/src/message_manager.c new file mode 100644 index 0000000..b3bc810 --- /dev/null +++ b/firmware/components/message-manager/src/message_manager.c @@ -0,0 +1,79 @@ +#include "message_manager.h" +#include +#include +#include +#include +#include +#include + +#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; + +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); + + // Reagiere auf Änderung von light_active + if (strcmp(msg.data.settings.key, "light_active") == 0) + { + extern void start_simulation(void); + start_simulation(); + } + } + 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; + } + } + } +} + +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; +} diff --git a/firmware/components/simulator/include/simulator.h b/firmware/components/simulator/include/simulator.h index f15f057..9614a2a 100644 --- a/firmware/components/simulator/include/simulator.h +++ b/firmware/components/simulator/include/simulator.h @@ -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 \ No newline at end of file diff --git a/firmware/main/app_task.cpp b/firmware/main/app_task.cpp index f910fcf..4ead0ce 100644 --- a/firmware/main/app_task.cpp +++ b/firmware/main/app_task.cpp @@ -7,6 +7,7 @@ #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" @@ -232,6 +233,8 @@ void app_task(void *args) } } + message_manager_init(); + setup_buttons(); init_ui();