188 lines
8.0 KiB
C++
188 lines
8.0 KiB
C++
#include "NeoPatternService.h"
|
|
#include "ApiServer.h"
|
|
|
|
NeoPatternService::NeoPatternService(TaskManager& taskMgr, uint16_t numPixels, uint8_t pin, uint8_t type)
|
|
: taskManager(taskMgr),
|
|
pixels(numPixels, pin, type),
|
|
updateIntervalMs(100),
|
|
brightness(48) {
|
|
pixels.setBrightness(brightness);
|
|
pixels.show();
|
|
|
|
registerTasks();
|
|
setPatternByName("rainbow_cycle");
|
|
}
|
|
|
|
void NeoPatternService::registerEndpoints(ApiServer& api) {
|
|
api.addEndpoint("/api/neopattern/status", HTTP_GET,
|
|
[this](AsyncWebServerRequest* request) { handleStatusRequest(request); },
|
|
std::vector<ParamSpec>{});
|
|
|
|
api.addEndpoint("/api/neopattern/patterns", HTTP_GET,
|
|
[this](AsyncWebServerRequest* request) { handlePatternsRequest(request); },
|
|
std::vector<ParamSpec>{});
|
|
|
|
api.addEndpoint("/api/neopattern", HTTP_POST,
|
|
[this](AsyncWebServerRequest* request) { handleControlRequest(request); },
|
|
std::vector<ParamSpec>{
|
|
ParamSpec{String("pattern"), false, String("body"), String("string"), patternNamesVector()},
|
|
ParamSpec{String("interval_ms"), false, String("body"), String("number"), {}, String("100")},
|
|
ParamSpec{String("brightness"), false, String("body"), String("number"), {}, String("50")},
|
|
ParamSpec{String("color"), false, String("body"), String("color"), {}},
|
|
ParamSpec{String("color2"), false, String("body"), String("color"), {}},
|
|
ParamSpec{String("r"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("g"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("b"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("r2"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("g2"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("b2"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("total_steps"), false, String("body"), String("number"), {}},
|
|
ParamSpec{String("direction"), false, String("body"), String("string"), {String("forward"), String("reverse")}}
|
|
});
|
|
}
|
|
|
|
void NeoPatternService::handleStatusRequest(AsyncWebServerRequest* request) {
|
|
JsonDocument doc;
|
|
doc["pin"] = pixels.getPin();
|
|
doc["count"] = pixels.numPixels();
|
|
doc["interval_ms"] = updateIntervalMs;
|
|
doc["brightness"] = brightness;
|
|
doc["pattern"] = currentPatternName();
|
|
doc["total_steps"] = pixels.TotalSteps;
|
|
doc["color1"] = pixels.Color1;
|
|
doc["color2"] = pixels.Color2;
|
|
|
|
String json;
|
|
serializeJson(doc, json);
|
|
request->send(200, "application/json", json);
|
|
}
|
|
|
|
void NeoPatternService::handlePatternsRequest(AsyncWebServerRequest* request) {
|
|
JsonDocument doc;
|
|
JsonArray arr = doc.to<JsonArray>();
|
|
for (auto& kv : patternSetters) arr.add(kv.first);
|
|
|
|
String json;
|
|
serializeJson(doc, json);
|
|
request->send(200, "application/json", json);
|
|
}
|
|
|
|
void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) {
|
|
if (request->hasParam("pattern", true)) {
|
|
String name = request->getParam("pattern", true)->value();
|
|
setPatternByName(name);
|
|
}
|
|
|
|
if (request->hasParam("interval_ms", true)) {
|
|
unsigned long v = request->getParam("interval_ms", true)->value().toInt();
|
|
if (v < 1) v = 1;
|
|
updateIntervalMs = v;
|
|
taskManager.setTaskInterval("neopattern_update", updateIntervalMs);
|
|
}
|
|
|
|
if (request->hasParam("brightness", true)) {
|
|
int b = request->getParam("brightness", true)->value().toInt();
|
|
if (b < 0) b = 0; if (b > 255) b = 255;
|
|
setBrightness((uint8_t)b);
|
|
}
|
|
|
|
// Accept packed color ints or r,g,b triplets
|
|
if (request->hasParam("color", true)) {
|
|
pixels.Color1 = (uint32_t)strtoul(request->getParam("color", true)->value().c_str(), nullptr, 0);
|
|
}
|
|
if (request->hasParam("color2", true)) {
|
|
pixels.Color2 = (uint32_t)strtoul(request->getParam("color2", true)->value().c_str(), nullptr, 0);
|
|
}
|
|
if (request->hasParam("r", true) || request->hasParam("g", true) || request->hasParam("b", true)) {
|
|
int r = request->hasParam("r", true) ? request->getParam("r", true)->value().toInt() : 0;
|
|
int g = request->hasParam("g", true) ? request->getParam("g", true)->value().toInt() : 0;
|
|
int b = request->hasParam("b", true) ? request->getParam("b", true)->value().toInt() : 0;
|
|
pixels.Color1 = pixels.Color(r, g, b);
|
|
}
|
|
if (request->hasParam("r2", true) || request->hasParam("g2", true) || request->hasParam("b2", true)) {
|
|
int r = request->hasParam("r2", true) ? request->getParam("r2", true)->value().toInt() : 0;
|
|
int g = request->hasParam("g2", true) ? request->getParam("g2", true)->value().toInt() : 0;
|
|
int b = request->hasParam("b2", true) ? request->getParam("b2", true)->value().toInt() : 0;
|
|
pixels.Color2 = pixels.Color(r, g, b);
|
|
}
|
|
|
|
if (request->hasParam("total_steps", true)) {
|
|
pixels.TotalSteps = request->getParam("total_steps", true)->value().toInt();
|
|
}
|
|
|
|
if (request->hasParam("direction", true)) {
|
|
String dir = request->getParam("direction", true)->value();
|
|
if (dir.equalsIgnoreCase("forward")) pixels.Direction = FORWARD;
|
|
else if (dir.equalsIgnoreCase("reverse")) pixels.Direction = REVERSE;
|
|
}
|
|
|
|
JsonDocument resp;
|
|
resp["ok"] = true;
|
|
resp["pattern"] = currentPatternName();
|
|
resp["interval_ms"] = updateIntervalMs;
|
|
resp["brightness"] = brightness;
|
|
|
|
String json;
|
|
serializeJson(resp, json);
|
|
request->send(200, "application/json", json);
|
|
}
|
|
|
|
void NeoPatternService::setBrightness(uint8_t b) {
|
|
brightness = b;
|
|
pixels.setBrightness(brightness);
|
|
pixels.show();
|
|
}
|
|
|
|
void NeoPatternService::registerTasks() {
|
|
taskManager.registerTask("neopattern_update", updateIntervalMs, [this]() { update(); });
|
|
taskManager.registerTask("neopattern_status_print", 10000, [this]() {
|
|
Serial.printf("[NeoPattern] pattern=%s interval=%lu ms brightness=%u\n",
|
|
currentPatternName().c_str(), updateIntervalMs, brightness);
|
|
});
|
|
}
|
|
|
|
void NeoPatternService::registerPatterns() {
|
|
patternSetters["off"] = [this]() { pixels.ActivePattern = NONE; };
|
|
patternSetters["rainbow_cycle"] = [this]() { pixels.RainbowCycle(updateIntervalMs); };
|
|
patternSetters["theater_chase"] = [this]() { pixels.TheaterChase(pixels.Color1 ? pixels.Color1 : pixels.Color(127,127,127), pixels.Color2, updateIntervalMs); };
|
|
patternSetters["color_wipe"] = [this]() { pixels.ColorWipe(pixels.Color1 ? pixels.Color1 : pixels.Color(255,0,0), updateIntervalMs); };
|
|
patternSetters["scanner"] = [this]() { pixels.Scanner(pixels.Color1 ? pixels.Color1 : pixels.Color(0,0,255), updateIntervalMs); };
|
|
patternSetters["fade"] = [this]() { pixels.Fade(pixels.Color1, pixels.Color2, pixels.TotalSteps ? pixels.TotalSteps : 32, updateIntervalMs); };
|
|
patternSetters["fire"] = [this]() { pixels.ActivePattern = FIRE; pixels.Interval = updateIntervalMs; };
|
|
}
|
|
|
|
std::vector<String> NeoPatternService::patternNamesVector() {
|
|
if (patternSetters.empty()) registerPatterns();
|
|
std::vector<String> v;
|
|
v.reserve(patternSetters.size());
|
|
for (const auto& kv : patternSetters) v.push_back(kv.first);
|
|
return v;
|
|
}
|
|
|
|
String NeoPatternService::currentPatternName() {
|
|
switch (pixels.ActivePattern) {
|
|
case NONE: return String("off");
|
|
case RAINBOW_CYCLE: return String("rainbow_cycle");
|
|
case THEATER_CHASE: return String("theater_chase");
|
|
case COLOR_WIPE: return String("color_wipe");
|
|
case SCANNER: return String("scanner");
|
|
case FADE: return String("fade");
|
|
case FIRE: return String("fire");
|
|
}
|
|
return String("off");
|
|
}
|
|
|
|
void NeoPatternService::setPatternByName(const String& name) {
|
|
if (patternSetters.empty()) registerPatterns();
|
|
auto it = patternSetters.find(name);
|
|
if (it != patternSetters.end()) {
|
|
pixels.Index = 0;
|
|
pixels.Direction = FORWARD;
|
|
it->second();
|
|
}
|
|
}
|
|
|
|
void NeoPatternService::update() {
|
|
pixels.Update();
|
|
}
|