diff --git a/examples/neopattern/NeoPatternService.cpp b/examples/neopattern/NeoPatternService.cpp index 378177a..eb7cc85 100644 --- a/examples/neopattern/NeoPatternService.cpp +++ b/examples/neopattern/NeoPatternService.cpp @@ -126,87 +126,43 @@ void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) { bool updated = false; bool broadcast = false; - if (request->hasParam("pattern", true)) { - String name = request->getParam("pattern", true)->value(); - 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)) { - String colorStr = request->getParam("color", true)->value(); - uint32_t color = parseColor(colorStr); - setColor(color); - updated = true; - } - - if (request->hasParam("color2", true)) { - String colorStr = request->getParam("color2", true)->value(); - uint32_t color = parseColor(colorStr); - setColor2(color); - updated = true; - } - - if (request->hasParam("brightness", true)) { - int b = request->getParam("brightness", true)->value().toInt(); - if (b < 0) b = 0; - if (b > 255) b = 255; - setBrightness(static_cast(b)); - updated = true; - } - - if (request->hasParam("total_steps", true)) { - int steps = request->getParam("total_steps", true)->value().toInt(); - if (steps > 0) { - setTotalSteps(static_cast(steps)); - updated = true; - } - } - - if (request->hasParam("direction", true)) { - String dirStr = request->getParam("direction", true)->value(); - NeoDirection dir = (dirStr.equalsIgnoreCase("reverse")) ? NeoDirection::REVERSE : NeoDirection::FORWARD; - setDirection(dir); - updated = true; - } - - if (request->hasParam("interval", true)) { - unsigned long interval = request->getParam("interval", true)->value().toInt(); - if (interval > 0) { - setUpdateInterval(interval); - updated = true; - } - } - if (request->hasParam("broadcast", true)) { String b = request->getParam("broadcast", true)->value(); broadcast = b.equalsIgnoreCase("true") || b == "1"; } - if (broadcast) { - // Build JSON payload from provided params - JsonDocument payload; - if (request->hasParam("pattern", true)) payload["pattern"] = request->getParam("pattern", true)->value(); - if (request->hasParam("color", true)) payload["color"] = request->getParam("color", true)->value(); - if (request->hasParam("color2", true)) payload["color2"] = request->getParam("color2", true)->value(); - if (request->hasParam("brightness", true)) payload["brightness"] = request->getParam("brightness", true)->value(); - if (request->hasParam("total_steps", true)) payload["total_steps"] = request->getParam("total_steps", true)->value(); - if (request->hasParam("direction", true)) payload["direction"] = request->getParam("direction", true)->value(); - if (request->hasParam("interval", true)) payload["interval"] = request->getParam("interval", true)->value(); + // Build JSON payload from provided params (single source of truth) + JsonDocument payload; + bool any = false; + if (request->hasParam("pattern", true)) { payload["pattern"] = request->getParam("pattern", true)->value(); any = true; } + if (request->hasParam("color", true)) { payload["color"] = request->getParam("color", true)->value(); any = true; } + if (request->hasParam("color2", true)) { payload["color2"] = request->getParam("color2", true)->value(); any = true; } + if (request->hasParam("brightness", true)) { payload["brightness"] = request->getParam("brightness", true)->value(); any = true; } + if (request->hasParam("total_steps", true)) { payload["total_steps"] = request->getParam("total_steps", true)->value(); any = true; } + if (request->hasParam("direction", true)) { payload["direction"] = request->getParam("direction", true)->value(); any = true; } + if (request->hasParam("interval", true)) { payload["interval"] = request->getParam("interval", true)->value(); any = true; } - String payloadStr; - serializeJson(payload, payloadStr); + String payloadStr; + serializeJson(payload, payloadStr); + // Always apply locally via event so we have a single codepath for updates + if (any) { + std::string ev = "api/neopattern"; + String localData = payloadStr; + LOG_INFO("NeoPattern", String("Applying local api/neopattern via event payloadLen=") + String(payloadStr.length())); + ctx.fire(ev, &localData); + updated = true; + } + + // Broadcast to peers if requested + if (broadcast && any) { JsonDocument eventDoc; eventDoc["event"] = "api/neopattern"; - eventDoc["data"] = payloadStr; // data is arbitrary JSON string + eventDoc["data"] = payloadStr; // data is JSON string String eventJson; serializeJson(eventDoc, eventJson); + // Compute subnet-directed broadcast to improve delivery on some networks IPAddress ip = WiFi.localIP(); IPAddress mask = WiFi.subnetMask(); @@ -216,12 +172,6 @@ void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) { String msg = String(ClusterProtocol::CLUSTER_EVENT_MSG) + ":" + eventJson; ctx.udp->write(msg.c_str()); ctx.udp->endPacket(); - - // Fire locally as well so the sender applies the change - std::string ev = "api/neopattern"; - String localData = payloadStr; - LOG_INFO("NeoPattern", "Firing local api/neopattern event after broadcast"); - ctx.fire(ev, &localData); } // Return current state