get/post led segments
Some checks failed
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 4m49s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 4m44s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 4m34s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 4m43s
Some checks failed
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 4m49s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 4m44s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 4m34s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 4m43s
Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -2,14 +2,17 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "message_manager.h"
|
#include "message_manager.h"
|
||||||
|
|
||||||
|
#include "led_segment.h"
|
||||||
|
#include "persistence_manager.h"
|
||||||
#include <cJSON.h>
|
#include <cJSON.h>
|
||||||
#include <esp_http_server.h>
|
#include <esp_http_server.h>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
#include <persistence_manager.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define MAX_BODY_SIZE 4096
|
||||||
|
|
||||||
static const char *TAG = "api_handlers";
|
static const char *TAG = "api_handlers";
|
||||||
|
|
||||||
// Helper function to set CORS headers
|
// Helper function to set CORS headers
|
||||||
@@ -400,31 +403,113 @@ esp_err_t api_wled_config_get_handler(httpd_req_t *req)
|
|||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "GET /api/wled/config");
|
ESP_LOGI(TAG, "GET /api/wled/config");
|
||||||
|
|
||||||
// TODO: Implement actual LED config retrieval
|
extern led_segment_t segments[LED_SEGMENT_MAX_LEN];
|
||||||
const char *response = "{"
|
extern size_t segment_count;
|
||||||
"\"segments\":["
|
size_t required_size = sizeof(segments) * segment_count;
|
||||||
"{\"name\":\"Main Light\",\"start\":0,\"leds\":60},"
|
|
||||||
"{\"name\":\"Accent Light\",\"start\":60,\"leds\":30}"
|
cJSON *json = cJSON_CreateObject();
|
||||||
"]"
|
|
||||||
"}";
|
persistence_manager_t pm;
|
||||||
return send_json_response(req, response);
|
if (persistence_manager_init(&pm, "led_config") == ESP_OK)
|
||||||
|
{
|
||||||
|
persistence_manager_get_blob(&pm, "segments", segments, required_size, NULL);
|
||||||
|
uint8_t segment_count = persistence_manager_get_int(&pm, "segment_count", 0);
|
||||||
|
persistence_manager_deinit(&pm);
|
||||||
|
|
||||||
|
cJSON *segments_arr = cJSON_CreateArray();
|
||||||
|
for (uint8_t i = 0; i < segment_count; ++i)
|
||||||
|
{
|
||||||
|
cJSON *seg = cJSON_CreateObject();
|
||||||
|
cJSON_AddStringToObject(seg, "name", segments[i].name);
|
||||||
|
cJSON_AddNumberToObject(seg, "start", segments[i].start);
|
||||||
|
cJSON_AddNumberToObject(seg, "leds", segments[i].leds);
|
||||||
|
cJSON_AddItemToArray(segments_arr, seg);
|
||||||
|
}
|
||||||
|
cJSON_AddItemToObject(json, "segments", segments_arr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cJSON_AddItemToObject(json, "segments", cJSON_CreateArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
char *response = cJSON_PrintUnformatted(json);
|
||||||
|
cJSON_Delete(json);
|
||||||
|
esp_err_t res = send_json_response(req, response);
|
||||||
|
free(response);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t api_wled_config_post_handler(httpd_req_t *req)
|
esp_err_t api_wled_config_post_handler(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "POST /api/wled/config");
|
ESP_LOGI(TAG, "POST /api/wled/config");
|
||||||
|
|
||||||
char buf[512];
|
char *buf = malloc(MAX_BODY_SIZE);
|
||||||
int ret = httpd_req_recv(req, buf, sizeof(buf) - 1);
|
if (!buf)
|
||||||
if (ret <= 0)
|
return send_error_response(req, 500, "Memory allocation failed");
|
||||||
|
int total = 0, ret;
|
||||||
|
while (total < MAX_BODY_SIZE - 1)
|
||||||
{
|
{
|
||||||
return send_error_response(req, 400, "Failed to receive request body");
|
ret = httpd_req_recv(req, buf + total, MAX_BODY_SIZE - 1 - total);
|
||||||
|
if (ret <= 0)
|
||||||
|
break;
|
||||||
|
total += ret;
|
||||||
}
|
}
|
||||||
buf[ret] = '\0';
|
buf[total] = '\0';
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Received WLED config: %s", buf);
|
ESP_LOGI(TAG, "Received WLED config: %s", buf);
|
||||||
|
|
||||||
// TODO: Parse JSON and save LED configuration
|
cJSON *json = cJSON_Parse(buf);
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
if (!json)
|
||||||
|
{
|
||||||
|
return send_error_response(req, 400, "Invalid JSON");
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON *segments_arr = cJSON_GetObjectItem(json, "segments");
|
||||||
|
if (!cJSON_IsArray(segments_arr))
|
||||||
|
{
|
||||||
|
cJSON_Delete(json);
|
||||||
|
return send_error_response(req, 400, "Missing segments array");
|
||||||
|
}
|
||||||
|
|
||||||
|
extern led_segment_t segments[LED_SEGMENT_MAX_LEN];
|
||||||
|
extern size_t segment_count;
|
||||||
|
size_t count = cJSON_GetArraySize(segments_arr);
|
||||||
|
if (count > LED_SEGMENT_MAX_LEN)
|
||||||
|
count = LED_SEGMENT_MAX_LEN;
|
||||||
|
segment_count = count;
|
||||||
|
for (size_t i = 0; i < LED_SEGMENT_MAX_LEN; ++i)
|
||||||
|
{
|
||||||
|
cJSON *seg = cJSON_GetArrayItem(segments_arr, i);
|
||||||
|
cJSON *name = cJSON_GetObjectItem(seg, "name");
|
||||||
|
cJSON *start = cJSON_GetObjectItem(seg, "start");
|
||||||
|
cJSON *leds = cJSON_GetObjectItem(seg, "leds");
|
||||||
|
if (cJSON_IsString(name) && cJSON_IsNumber(start) && cJSON_IsNumber(leds) && i < count)
|
||||||
|
{
|
||||||
|
strncpy(segments[i].name, name->valuestring, sizeof(segments[i].name) - 1);
|
||||||
|
segments[i].name[sizeof(segments[i].name) - 1] = '\0';
|
||||||
|
segments[i].start = (uint16_t)start->valuedouble;
|
||||||
|
segments[i].leds = (uint16_t)leds->valuedouble;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid entry, skip or set defaults
|
||||||
|
segments[i].name[0] = '\0';
|
||||||
|
segments[i].start = 0;
|
||||||
|
segments[i].leds = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cJSON_Delete(json);
|
||||||
|
|
||||||
|
persistence_manager_t pm;
|
||||||
|
if (persistence_manager_init(&pm, "led_config") == ESP_OK)
|
||||||
|
{
|
||||||
|
persistence_manager_set_blob(&pm, "segments", segments, sizeof(led_segment_t) * segment_count);
|
||||||
|
persistence_manager_set_int(&pm, "segment_count", (int32_t)segment_count);
|
||||||
|
persistence_manager_deinit(&pm);
|
||||||
|
}
|
||||||
|
|
||||||
set_cors_headers(req);
|
set_cors_headers(req);
|
||||||
return httpd_resp_sendstr(req, "{\"status\":\"ok\"}");
|
return httpd_resp_sendstr(req, "{\"status\":\"ok\"}");
|
||||||
}
|
}
|
||||||
|
|||||||
16
firmware/components/led-manager/include/led_segment.h
Normal file
16
firmware/components/led-manager/include/led_segment.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define LED_SEGMENT_MAX_LEN 15
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char name[32];
|
||||||
|
uint16_t start;
|
||||||
|
uint16_t leds;
|
||||||
|
} led_segment_t;
|
||||||
|
|
||||||
|
led_segment_t segments[LED_SEGMENT_MAX_LEN];
|
||||||
|
size_t segment_count;
|
||||||
@@ -205,6 +205,33 @@ extern "C"
|
|||||||
void persistence_manager_get_string(const persistence_manager_t *pm, const char *key, char *out_value,
|
void persistence_manager_get_string(const persistence_manager_t *pm, const char *key, char *out_value,
|
||||||
size_t max_len, const char *default_value);
|
size_t max_len, const char *default_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set a blob (binary data) value for a key in NVS storage.
|
||||||
|
*
|
||||||
|
* This function stores arbitrary binary data under the given key.
|
||||||
|
*
|
||||||
|
* @param pm Pointer to the persistence manager structure.
|
||||||
|
* @param key Key to set.
|
||||||
|
* @param value Pointer to the data to store.
|
||||||
|
* @param length Length of the data in bytes.
|
||||||
|
*/
|
||||||
|
void persistence_manager_set_blob(persistence_manager_t *pm, const char *key, const void *value, size_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a blob (binary data) value for a key from NVS storage.
|
||||||
|
*
|
||||||
|
* This function retrieves binary data previously stored under the given key.
|
||||||
|
*
|
||||||
|
* @param pm Pointer to the persistence manager structure.
|
||||||
|
* @param key Key to retrieve.
|
||||||
|
* @param out_value Buffer to store the retrieved data.
|
||||||
|
* @param max_length Maximum length of the output buffer in bytes.
|
||||||
|
* @param out_length Pointer to variable to receive the actual data length.
|
||||||
|
* @return true if the blob was found and read successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
bool persistence_manager_get_blob(const persistence_manager_t *pm, const char *key, void *out_value,
|
||||||
|
size_t max_length, size_t *out_length);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include "persistence_manager.h"
|
#include "persistence_manager.h"
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -174,6 +173,17 @@ void persistence_manager_set_string(persistence_manager_t *pm, const char *key,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void persistence_manager_set_blob(persistence_manager_t *pm, const char *key, const void *value, size_t length)
|
||||||
|
{
|
||||||
|
if (!persistence_manager_is_initialized(pm) || !value || length == 0)
|
||||||
|
return;
|
||||||
|
esp_err_t err = nvs_set_blob(pm->nvs_handle, key, value, length);
|
||||||
|
if (err != ESP_OK)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Failed to set blob key '%s': %s", key, esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool persistence_manager_get_bool(const persistence_manager_t *pm, const char *key, bool default_value)
|
bool persistence_manager_get_bool(const persistence_manager_t *pm, const char *key, bool default_value)
|
||||||
{
|
{
|
||||||
if (!persistence_manager_is_initialized(pm))
|
if (!persistence_manager_is_initialized(pm))
|
||||||
@@ -245,3 +255,20 @@ void persistence_manager_get_string(const persistence_manager_t *pm, const char
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool persistence_manager_get_blob(const persistence_manager_t *pm, const char *key, void *out_value, size_t max_length,
|
||||||
|
size_t *out_length)
|
||||||
|
{
|
||||||
|
if (!persistence_manager_is_initialized(pm) || !out_value || max_length == 0)
|
||||||
|
return false;
|
||||||
|
size_t required_size = 0;
|
||||||
|
esp_err_t err = nvs_get_blob(pm->nvs_handle, key, NULL, &required_size);
|
||||||
|
if (err != ESP_OK || required_size == 0 || required_size > max_length)
|
||||||
|
return false;
|
||||||
|
err = nvs_get_blob(pm->nvs_handle, key, out_value, &required_size);
|
||||||
|
if (err != ESP_OK)
|
||||||
|
return false;
|
||||||
|
if (out_length)
|
||||||
|
*out_length = required_size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user