light on/off via REST or GPIO

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2026-01-18 14:13:05 +01:00
parent f7cedf24e8
commit 1fade06bdb
9 changed files with 197 additions and 16 deletions

View File

@@ -13,4 +13,5 @@ idf_component_register(SRCS
json
simulator
persistence-manager
message-manager
)

View File

@@ -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\"}");
}

View File

@@ -18,4 +18,5 @@ idf_component_register(SRCS
led-manager
persistence-manager
simulator
message-manager
)

View File

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

View File

@@ -0,0 +1,6 @@
idf_component_register(
SRCS "src/message_manager.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES
persistence-manager
)

View File

@@ -0,0 +1,65 @@
#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;
void message_manager_init(void);
bool message_manager_post(const message_t *msg, TickType_t timeout);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,79 @@
#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;
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;
}

View File

@@ -9,6 +9,11 @@ typedef struct
int cycle_duration_minutes;
} simulation_config_t;
#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);
@@ -18,3 +23,6 @@ void start_simulate_night(void);
void start_simulation_task(void);
void stop_simulation_task(void);
void start_simulation(void);
#ifdef __cplusplus
}
#endif

View File

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