Added individual LED control to API and WebUI

This commit is contained in:
Djuri Baars 2023-11-18 14:03:47 +01:00
parent ef70203834
commit 1ad97b9b71
6 changed files with 139 additions and 16 deletions

2
data

@ -1 +1 @@
Subproject commit 58fa1e7ecb49388bc4b59444ab3f5af7b3219699
Subproject commit d3c6e52f3f5bae6054f8fc05b241a1e9b0a6ca1c

View file

@ -209,7 +209,7 @@ void finishSetup()
if (preferences.getBool("ledStatus", false))
{
setLights(preferences.getUInt("ledColor", 0xFFCC00));
restoreLedState();
}
else
{

View file

@ -250,18 +250,44 @@ void setLights(uint32_t color)
{
bool ledStatus = true;
if (color == pixels.Color(0, 0, 0))
{
ledStatus = false;
} else {
preferences.putUInt("ledColor", color);
}
preferences.putBool("ledStatus", ledStatus);
for (int i = 0; i < NEOPIXEL_COUNT; i++)
{
pixels.setPixelColor(i, color);
}
pixels.show();
if (color == pixels.Color(0, 0, 0))
{
ledStatus = false;
} else {
saveLedState();
}
preferences.putBool("ledStatus", ledStatus);
}
void saveLedState() {
for (int i = 0; i < pixels.numPixels(); i++)
{
int pixelColor = pixels.getPixelColor(i);
char key[12];
snprintf(key, 12, "%s%d", "ledColor_", i);
preferences.putUInt(key, pixelColor);
}
xTaskNotifyGive(eventSourceTaskHandle);
}
void restoreLedState() {
for (int i = 0; i < pixels.numPixels(); i++)
{
char key[12];
snprintf(key, 12, "%s%d", "ledColor_", i);
uint pixelColor = preferences.getUInt(key, pixels.Color(0,0,0));
pixels.setPixelColor(i, pixelColor);
}
pixels.show();
}

View file

@ -2,6 +2,9 @@
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "webserver.hpp"
#include "shared.hpp"
#ifndef NEOPIXEL_PIN
@ -38,6 +41,8 @@ void blinkDelay(int d, int times);
void blinkDelayColor(int d, int times, uint r, uint g, uint b);
void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2);
void clearLeds();
void saveLedState();
void restoreLedState();
QueueHandle_t getLedTaskQueue();
bool queueLedEffect(uint effect);
void setLights(int r, int g, int b);

View file

@ -6,7 +6,6 @@ TaskHandle_t eventSourceTaskHandle;
void setupWebserver()
{
events.onConnect([](AsyncEventSourceClient *client)
{ client->send("welcome", NULL, millis(), 1000); });
@ -39,6 +38,9 @@ void setupWebserver()
AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/api/show/custom", onApiShowTextAdvanced);
server.addHandler(handler);
AsyncCallbackJsonWebHandler *lightsJsonHandler = new AsyncCallbackJsonWebHandler("/api/lights", onApiLightsSetJson);
server.addHandler(lightsJsonHandler);
server.on("/api/lights/off", HTTP_GET, onApiLightsOff);
server.on("/api/lights/color", HTTP_GET, onApiLightsSetColor);
server.on("/api/lights", HTTP_GET, onApiLightsStatus);
@ -109,15 +111,16 @@ StaticJsonDocument<512> getLedStatusObject()
{
StaticJsonDocument<512> root;
JsonArray colors = root.createNestedArray("data");
// Adafruit_NeoPixel pix = getPixels();
// Adafruit_NeoPixel pix = getPixels();
for (uint i = 0; i < pixels.numPixels(); i++) {
uint32_t pixColor = pixels.getPixelColor(i);
for (uint i = 0; i < pixels.numPixels(); i++)
{
uint32_t pixColor = pixels.getPixelColor(pixels.numPixels() - i - 1);
uint alpha = (pixColor >> 24) & 0xFF;
uint red = (pixColor >> 16) & 0xFF;
uint green = (pixColor >> 8) & 0xFF;
uint blue = pixColor & 0xFF;
char hexColor[8];
char hexColor[8];
sprintf(hexColor, "#%02X%02X%02X", red, green, blue);
JsonObject object = colors.createNestedObject();
@ -677,7 +680,7 @@ void onApiLightsStatus(AsyncWebServerRequest *request)
{
AsyncResponseStream *response = request->beginResponseStream("application/json");
serializeJson(getLedStatusObject(), *response);
serializeJson(getLedStatusObject()["data"], *response);
request->send(response);
}
@ -708,19 +711,107 @@ void onApiLightsSetColor(AsyncWebServerRequest *request)
}
}
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
{
if (request->method() == HTTP_PATCH) {
JsonArray lights = json.as<JsonArray>();
if (lights.size() != pixels.numPixels())
{
Serial.printf("Invalid values for LED set %d\n", lights.size());
request->send(400);
return;
}
for (uint i = 0; i < pixels.numPixels(); i++)
{
unsigned int red, green, blue;
if (lights[i].containsKey("red") && lights[i].containsKey("green") && lights[i].containsKey("blue"))
{
red = lights[i]["red"].as<uint>();
green = lights[i]["green"].as<uint>();
blue = lights[i]["blue"].as<uint>();
}
else if (lights[i].containsKey("hex"))
{
if (!sscanf(lights[i]["hex"].as<String>().c_str(), "#%02X%02X%02X", &red, &green, &blue) == 3)
{
Serial.printf("Invalid hex for LED %d\n", i);
request->send(400);
return;
}
}
else
{
Serial.printf("No valid color for LED %d\n", i);
request->send(400);
return;
}
pixels.setPixelColor((pixels.numPixels() - i - 1), pixels.Color(
red,
green,
blue));
}
pixels.show();
saveLedState();
request->send(200);
} else {
request->send(404);
}
}
void onIndex(AsyncWebServerRequest *request) { request->send(LittleFS, "/index.html", String(), false); }
void onNotFound(AsyncWebServerRequest *request)
{
// Serial.printf("NotFound, URL[%s]\n", request->url());
// Serial.printf("NotFound, METHOD[%s]\n", request->methodToString());
// int headers = request->headers();
// int i;
// for (i = 0; i < headers; i++)
// {
// AsyncWebHeader *h = request->getHeader(i);
// Serial.printf("NotFound HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
// }
// int params = request->params();
// for (int i = 0; i < params; i++)
// {
// AsyncWebParameter *p = request->getParam(i);
// if (p->isFile())
// { // p->isPost() is also true
// Serial.printf("NotFound FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
// }
// else if (p->isPost())
// {
// Serial.printf("NotFound POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
// }
// else
// {
// Serial.printf("NotFound GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
// }
// }
// Access-Control-Request-Method == POST might be better
if (request->method() == HTTP_OPTIONS || request->hasHeader("Sec-Fetch-Mode"))
{
// Serial.printf("NotFound, Return[%d]\n", 200);
request->send(200);
}
else
{
request->send(200);
// Serial.printf("NotFound, Return[%d]\n", 404);
request->send(404);
}
};

View file

@ -36,6 +36,7 @@ void onApiFullRefresh(AsyncWebServerRequest *request);
void onApiLightsStatus(AsyncWebServerRequest *request);
void onApiLightsOff(AsyncWebServerRequest *request);
void onApiLightsSetColor(AsyncWebServerRequest *request);
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json);
void onApiRestart(AsyncWebServerRequest *request);