feat: optimize neopattern example

This commit is contained in:
2025-09-20 22:05:52 +02:00
parent 51d4d4bc94
commit c11652c123
8 changed files with 737 additions and 487 deletions

View File

@@ -86,6 +86,12 @@ void NeoPatternService::handleStatusRequest(AsyncWebServerRequest* request) {
doc["interval"] = updateIntervalMs;
doc["active"] = initialized;
// Add pattern metadata
String currentPattern = currentPatternName();
doc["pattern_description"] = getPatternDescription(currentPattern);
doc["pattern_requires_color2"] = patternRequiresColor2(currentPattern);
doc["pattern_supports_direction"] = patternSupportsDirection(currentPattern);
String json;
serializeJson(doc, json);
request->send(200, "application/json", json);
@@ -94,8 +100,16 @@ void NeoPatternService::handleStatusRequest(AsyncWebServerRequest* request) {
void NeoPatternService::handlePatternsRequest(AsyncWebServerRequest* request) {
JsonDocument doc;
JsonArray arr = doc.to<JsonArray>();
for (const auto& kv : patternUpdaters) {
arr.add(kv.first);
// Get all patterns from registry and include metadata
auto patterns = patternRegistry.getAllPatterns();
for (const auto& pattern : patterns) {
JsonObject patternObj = arr.add<JsonObject>();
patternObj["name"] = pattern.name;
patternObj["type"] = pattern.type;
patternObj["description"] = pattern.description;
patternObj["requires_color2"] = pattern.requiresColor2;
patternObj["supports_direction"] = pattern.supportsDirection;
}
String json;
@@ -108,8 +122,13 @@ void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) {
if (request->hasParam("pattern", true)) {
String name = request->getParam("pattern", true)->value();
setPatternByName(name);
updated = true;
if (isValidPattern(name)) {
setPatternByName(name);
updated = true;
} else {
// Invalid pattern name - could add error handling here
LOG_WARN("NeoPattern", "Invalid pattern name: " + name);
}
}
if (request->hasParam("color", true)) {
@@ -195,6 +214,9 @@ void NeoPatternService::setPattern(NeoPatternType pattern) {
currentState.pattern = static_cast<uint>(pattern);
neoPattern->ActivePattern = static_cast<::pattern>(pattern);
resetStateForPattern(pattern);
// Initialize the pattern using the registry
patternRegistry.initializePattern(static_cast<uint8_t>(pattern));
}
void NeoPatternService::setPatternByName(const String& name) {
@@ -263,46 +285,89 @@ void NeoPatternService::registerTasks() {
}
void NeoPatternService::registerPatterns() {
// Register pattern updaters
patternUpdaters["none"] = [this]() { updateNone(); };
patternUpdaters["rainbow_cycle"] = [this]() { updateRainbowCycle(); };
patternUpdaters["theater_chase"] = [this]() { updateTheaterChase(); };
patternUpdaters["color_wipe"] = [this]() { updateColorWipe(); };
patternUpdaters["scanner"] = [this]() { updateScanner(); };
patternUpdaters["fade"] = [this]() { updateFade(); };
patternUpdaters["fire"] = [this]() { updateFire(); };
// Register name to pattern mapping
nameToPatternMap["none"] = NeoPatternType::NONE;
nameToPatternMap["rainbow_cycle"] = NeoPatternType::RAINBOW_CYCLE;
nameToPatternMap["theater_chase"] = NeoPatternType::THEATER_CHASE;
nameToPatternMap["color_wipe"] = NeoPatternType::COLOR_WIPE;
nameToPatternMap["scanner"] = NeoPatternType::SCANNER;
nameToPatternMap["fade"] = NeoPatternType::FADE;
nameToPatternMap["fire"] = NeoPatternType::FIRE;
// Register all patterns with their metadata and callbacks
patternRegistry.registerPattern(
"none",
static_cast<uint8_t>(NeoPatternType::NONE),
"No pattern - solid color",
[this]() { /* No initialization needed */ },
[this]() { updateNone(); },
false, // doesn't require color2
false // doesn't support direction
);
patternRegistry.registerPattern(
"rainbow_cycle",
static_cast<uint8_t>(NeoPatternType::RAINBOW_CYCLE),
"Rainbow cycle pattern",
[this]() { neoPattern->RainbowCycle(updateIntervalMs, static_cast<::direction>(direction)); },
[this]() { updateRainbowCycle(); },
false, // doesn't require color2
true // supports direction
);
patternRegistry.registerPattern(
"theater_chase",
static_cast<uint8_t>(NeoPatternType::THEATER_CHASE),
"Theater chase pattern",
[this]() { neoPattern->TheaterChase(currentState.color, currentState.color2, updateIntervalMs, static_cast<::direction>(direction)); },
[this]() { updateTheaterChase(); },
true, // requires color2
true // supports direction
);
patternRegistry.registerPattern(
"color_wipe",
static_cast<uint8_t>(NeoPatternType::COLOR_WIPE),
"Color wipe pattern",
[this]() { neoPattern->ColorWipe(currentState.color, updateIntervalMs, static_cast<::direction>(direction)); },
[this]() { updateColorWipe(); },
false, // doesn't require color2
true // supports direction
);
patternRegistry.registerPattern(
"scanner",
static_cast<uint8_t>(NeoPatternType::SCANNER),
"Scanner pattern",
[this]() { neoPattern->Scanner(currentState.color, updateIntervalMs); },
[this]() { updateScanner(); },
false, // doesn't require color2
false // doesn't support direction
);
patternRegistry.registerPattern(
"fade",
static_cast<uint8_t>(NeoPatternType::FADE),
"Fade pattern",
[this]() { neoPattern->Fade(currentState.color, currentState.color2, currentState.totalSteps, updateIntervalMs, static_cast<::direction>(direction)); },
[this]() { updateFade(); },
true, // requires color2
true // supports direction
);
patternRegistry.registerPattern(
"fire",
static_cast<uint8_t>(NeoPatternType::FIRE),
"Fire effect pattern",
[this]() { neoPattern->Fire(50, 120); },
[this]() { updateFire(); },
false, // doesn't require color2
false // doesn't support direction
);
}
std::vector<String> NeoPatternService::patternNamesVector() const {
std::vector<String> names;
names.reserve(patternUpdaters.size());
for (const auto& kv : patternUpdaters) {
names.push_back(kv.first);
}
return names;
return patternRegistry.getAllPatternNames();
}
String NeoPatternService::currentPatternName() const {
for (const auto& kv : nameToPatternMap) {
if (kv.second == activePattern) {
return kv.first;
}
}
return "none";
return patternRegistry.getPatternName(static_cast<uint8_t>(activePattern));
}
NeoPatternService::NeoPatternType NeoPatternService::nameToPattern(const String& name) const {
auto it = nameToPatternMap.find(name);
return (it != nameToPatternMap.end()) ? it->second : NeoPatternType::NONE;
uint8_t type = patternRegistry.getPatternType(name);
return static_cast<NeoPatternType>(type);
}
void NeoPatternService::resetStateForPattern(NeoPatternType pattern) {
@@ -322,6 +387,29 @@ uint32_t NeoPatternService::parseColor(const String& colorStr) const {
}
}
bool NeoPatternService::isValidPattern(const String& name) const {
return patternRegistry.isValidPattern(name);
}
bool NeoPatternService::isValidPattern(NeoPatternType type) const {
return patternRegistry.isValidPattern(static_cast<uint8_t>(type));
}
bool NeoPatternService::patternRequiresColor2(const String& name) const {
const PatternInfo* info = patternRegistry.getPattern(name);
return info ? info->requiresColor2 : false;
}
bool NeoPatternService::patternSupportsDirection(const String& name) const {
const PatternInfo* info = patternRegistry.getPattern(name);
return info ? info->supportsDirection : false;
}
String NeoPatternService::getPatternDescription(const String& name) const {
const PatternInfo* info = patternRegistry.getPattern(name);
return info ? info->description : "";
}
void NeoPatternService::update() {
if (!initialized) return;
@@ -329,13 +417,8 @@ void NeoPatternService::update() {
//if (now - lastUpdateMs < updateIntervalMs) return;
//lastUpdateMs = now;
const String name = currentPatternName();
auto it = patternUpdaters.find(name);
if (it != patternUpdaters.end()) {
it->second();
} else {
updateNone();
}
// Use pattern registry to execute the current pattern
patternRegistry.executePattern(static_cast<uint8_t>(activePattern));
}
void NeoPatternService::updateRainbowCycle() {