diff --git a/examples/neopattern/NeoPatternService.cpp b/examples/neopattern/NeoPatternService.cpp index eb7cc85..c5db8df 100644 --- a/examples/neopattern/NeoPatternService.cpp +++ b/examples/neopattern/NeoPatternService.cpp @@ -154,7 +154,7 @@ void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) { updated = true; } - // Broadcast to peers if requested + // Broadcast to peers if requested (delegate to core broadcast handler) if (broadcast && any) { JsonDocument eventDoc; eventDoc["event"] = "api/neopattern"; @@ -163,15 +163,10 @@ void NeoPatternService::handleControlRequest(AsyncWebServerRequest* request) { String eventJson; serializeJson(eventDoc, eventJson); - // Compute subnet-directed broadcast to improve delivery on some networks - IPAddress ip = WiFi.localIP(); - IPAddress mask = WiFi.subnetMask(); - IPAddress bcast(ip[0] | ~mask[0], ip[1] | ~mask[1], ip[2] | ~mask[2], ip[3] | ~mask[3]); - LOG_INFO("NeoPattern", String("Broadcasting CLUSTER_EVENT api/neopattern to ") + bcast.toString() + " payloadLen=" + String(payloadStr.length())); - ctx.udp->beginPacket(bcast, ctx.config.udp_port); - String msg = String(ClusterProtocol::CLUSTER_EVENT_MSG) + ":" + eventJson; - ctx.udp->write(msg.c_str()); - ctx.udp->endPacket(); + LOG_INFO("NeoPattern", String("Submitting cluster/broadcast for api/neopattern payloadLen=") + String(payloadStr.length())); + std::string ev = "cluster/broadcast"; + String eventStr = eventJson; + ctx.fire(ev, &eventStr); } // Return current state diff --git a/src/spore/core/ClusterManager.cpp b/src/spore/core/ClusterManager.cpp index 0d84378..1d6e2e9 100644 --- a/src/spore/core/ClusterManager.cpp +++ b/src/spore/core/ClusterManager.cpp @@ -8,6 +8,23 @@ ClusterManager::ClusterManager(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx NodeInfo* node = static_cast(data); this->addOrUpdateNode(node->hostname, node->ip); }); + // Centralized broadcast handler: services fire 'cluster/broadcast' with CLUSTER_EVENT JSON payload + ctx.on("cluster/broadcast", [this](void* data) { + String* jsonStr = static_cast(data); + if (!jsonStr) { + LOG_WARN("Cluster", "cluster/broadcast called with null data"); + return; + } + // Subnet-directed broadcast (more reliable than 255.255.255.255 on some networks) + IPAddress ip = WiFi.localIP(); + IPAddress mask = WiFi.subnetMask(); + IPAddress bcast(ip[0] | ~mask[0], ip[1] | ~mask[1], ip[2] | ~mask[2], ip[3] | ~mask[3]); + LOG_INFO("Cluster", String("Broadcasting CLUSTER_EVENT to ") + bcast.toString() + " len=" + String(jsonStr->length())); + this->ctx.udp->beginPacket(bcast, this->ctx.config.udp_port); + String msg = String(ClusterProtocol::CLUSTER_EVENT_MSG) + ":" + *jsonStr; + this->ctx.udp->write(msg.c_str()); + this->ctx.udp->endPacket(); + }); // Register tasks registerTasks(); initMessageHandlers();