Compare commits
2 Commits
eab10cffa5
...
682849650d
| Author | SHA1 | Date | |
|---|---|---|---|
| 682849650d | |||
| 0f003335b3 |
@@ -195,13 +195,13 @@ void NeoPatternService::registerEventHandlers() {
|
||||
JsonDocument doc;
|
||||
DeserializationError err = deserializeJson(doc, *jsonStr);
|
||||
if (err) {
|
||||
LOG_WARN("NeoPattern", String("Failed to parse CLUSTER_EVENT data: ") + err.c_str());
|
||||
LOG_WARN("NeoPattern", String("Failed to parse cluster/event data: ") + err.c_str());
|
||||
return;
|
||||
}
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
bool applied = applyControlParams(obj);
|
||||
if (applied) {
|
||||
LOG_INFO("NeoPattern", "Applied control from CLUSTER_EVENT");
|
||||
LOG_INFO("NeoPattern", "Applied control from cluster/event");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
// Cluster protocol and API constants
|
||||
namespace ClusterProtocol {
|
||||
// Simplified heartbeat-only protocol
|
||||
constexpr const char* HEARTBEAT_MSG = "CLUSTER_HEARTBEAT";
|
||||
constexpr const char* NODE_UPDATE_MSG = "NODE_UPDATE";
|
||||
constexpr const char* CLUSTER_EVENT_MSG = "CLUSTER_EVENT";
|
||||
constexpr const char* RAW_MSG = "RAW";
|
||||
constexpr const char* HEARTBEAT_MSG = "cluster/heartbeat";
|
||||
constexpr const char* NODE_UPDATE_MSG = "node/update";
|
||||
constexpr const char* CLUSTER_EVENT_MSG = "cluster/event";
|
||||
constexpr const char* RAW_MSG = "raw";
|
||||
constexpr uint16_t UDP_PORT = 4210;
|
||||
// Increased buffer to accommodate larger RAW pixel streams and node info JSON over UDP
|
||||
constexpr size_t UDP_BUF_SIZE = 2048;
|
||||
|
||||
@@ -18,6 +18,15 @@ monitor_speed = 115200
|
||||
lib_deps =
|
||||
esp32async/ESPAsyncWebServer@^3.8.0
|
||||
bblanchon/ArduinoJson@^7.4.2
|
||||
build_flags =
|
||||
-Os ; Optimize for size
|
||||
-ffunction-sections ; Place each function in its own section
|
||||
-fdata-sections ; Place data in separate sections
|
||||
-Wl,--gc-sections ; Remove unused sections at link time
|
||||
-DNDEBUG ; Disable debug assertions
|
||||
-DVTABLES_IN_FLASH ; Move virtual tables to flash
|
||||
-fno-exceptions ; Disable C++ exceptions
|
||||
-fno-rtti ; Disable runtime type information
|
||||
|
||||
[env:base]
|
||||
platform = platformio/espressif8266@^4.2.1
|
||||
@@ -31,6 +40,7 @@ board_build.filesystem = littlefs
|
||||
; note: somehow partition table is not working, so we need to use the ldscript
|
||||
board_build.ldscript = eagle.flash.1m64.ld ; 64KB -> FS Size
|
||||
lib_deps = ${common.lib_deps}
|
||||
build_flags = ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/base/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -51,6 +61,7 @@ board_build.flash_mode = dio ; D1 Mini uses DIO on 4 Mbit flash
|
||||
board_build.flash_size = 4M
|
||||
board_build.ldscript = eagle.flash.4m1m.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
build_flags = ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/base/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -71,6 +82,7 @@ board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.1m64.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
;data_dir = examples/relay/data
|
||||
build_flags = ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/relay/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -91,7 +103,7 @@ board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.1m64.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
adafruit/Adafruit NeoPixel@^1.15.1
|
||||
build_flags = -DLED_STRIP_PIN=2
|
||||
build_flags = -DLED_STRIP_PIN=2 ;${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/neopattern/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -112,7 +124,7 @@ board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.1m64.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
adafruit/Adafruit NeoPixel@^1.15.1
|
||||
build_flags =
|
||||
build_flags = ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/pixelstream/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -133,7 +145,7 @@ board_build.flash_mode = dout
|
||||
board_build.ldscript = eagle.flash.4m1m.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
adafruit/Adafruit NeoPixel@^1.15.1
|
||||
build_flags = -DPIXEL_PIN=TX -DPIXEL_COUNT=256 -DMATRIX_WIDTH=16
|
||||
build_flags = -DPIXEL_PIN=TX -DPIXEL_COUNT=256 -DMATRIX_WIDTH=16 ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/pixelstream/*.cpp>
|
||||
+<src/spore/*.cpp>
|
||||
@@ -156,6 +168,7 @@ board_build.ldscript = eagle.flash.4m1m.ld
|
||||
lib_deps = ${common.lib_deps}
|
||||
adafruit/Adafruit NeoPixel@^1.15.1
|
||||
dfrobot/DFRobotDFPlayerMini@^1.0.6
|
||||
build_flags = ${common.build_flags}
|
||||
build_src_filter =
|
||||
+<examples/multimatrix/*.cpp>
|
||||
+<examples/pixelstream/PixelStreamController.cpp>
|
||||
|
||||
@@ -9,7 +9,7 @@ ClusterManager::ClusterManager(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx
|
||||
NodeInfo* node = static_cast<NodeInfo*>(data);
|
||||
this->addOrUpdateNode(node->hostname, node->ip);
|
||||
});
|
||||
// Centralized broadcast handler: services fire 'cluster/broadcast' with CLUSTER_EVENT JSON payload
|
||||
// Centralized broadcast handler: services fire 'cluster/broadcast' with cluster/event JSON payload
|
||||
ctx.on("cluster/broadcast", [this](void* data) {
|
||||
String* jsonStr = static_cast<String*>(data);
|
||||
if (!jsonStr) {
|
||||
@@ -20,7 +20,7 @@ ClusterManager::ClusterManager(NodeContext& ctx, TaskManager& taskMgr) : ctx(ctx
|
||||
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_DEBUG("Cluster", String("Broadcasting CLUSTER_EVENT to ") + bcast.toString() + " len=" + String(jsonStr->length()));
|
||||
LOG_DEBUG("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());
|
||||
@@ -120,7 +120,7 @@ bool ClusterManager::isRawMsg(const char* msg) {
|
||||
// Discovery functionality removed - using heartbeat-only approach
|
||||
|
||||
void ClusterManager::onHeartbeat(const char* msg) {
|
||||
// Extract hostname from heartbeat message: "CLUSTER_HEARTBEAT:hostname"
|
||||
// Extract hostname from heartbeat message: "cluster/heartbeat:hostname"
|
||||
const char* colon = strchr(msg, ':');
|
||||
if (!colon) {
|
||||
LOG_WARN("Cluster", "Invalid heartbeat message format");
|
||||
@@ -138,7 +138,7 @@ void ClusterManager::onHeartbeat(const char* msg) {
|
||||
}
|
||||
|
||||
void ClusterManager::onNodeUpdate(const char* msg) {
|
||||
// Message format: "NODE_UPDATE:hostname:{json}"
|
||||
// Message format: "node/update:hostname:{json}"
|
||||
const char* firstColon = strchr(msg, ':');
|
||||
if (!firstColon) {
|
||||
LOG_WARN("Cluster", "Invalid NODE_UPDATE message format");
|
||||
@@ -286,17 +286,17 @@ void ClusterManager::sendNodeInfo(const String& targetHostname, const IPAddress&
|
||||
}
|
||||
|
||||
void ClusterManager::onClusterEvent(const char* msg) {
|
||||
// Message format: CLUSTER_EVENT:{"event":"...","data":"<json string>"}
|
||||
// Message format: cluster/event:{"event":"...","data":"<json string>"}
|
||||
const char* jsonStart = msg + strlen(ClusterProtocol::CLUSTER_EVENT_MSG) + 1; // skip prefix and ':'
|
||||
if (*jsonStart == '\0') {
|
||||
LOG_DEBUG("Cluster", "CLUSTER_EVENT received with empty payload");
|
||||
LOG_DEBUG("Cluster", "cluster/event received with empty payload");
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG("Cluster", String("CLUSTER_EVENT raw from ") + ctx.udp->remoteIP().toString() + " len=" + String(strlen(jsonStart)));
|
||||
LOG_DEBUG("Cluster", String("cluster/event raw from ") + ctx.udp->remoteIP().toString() + " len=" + String(strlen(jsonStart)));
|
||||
JsonDocument doc;
|
||||
DeserializationError err = deserializeJson(doc, jsonStart);
|
||||
if (err) {
|
||||
LOG_ERROR("Cluster", String("Failed to parse CLUSTER_EVENT JSON from ") + ctx.udp->remoteIP().toString());
|
||||
LOG_ERROR("Cluster", String("Failed to parse cluster/event JSON from ") + ctx.udp->remoteIP().toString());
|
||||
return;
|
||||
}
|
||||
// Robust extraction of event and data
|
||||
@@ -320,7 +320,7 @@ void ClusterManager::onClusterEvent(const char* msg) {
|
||||
if (eventStr.length() == 0 || data.length() == 0) {
|
||||
String dbg;
|
||||
serializeJson(doc, dbg);
|
||||
LOG_WARN("Cluster", String("CLUSTER_EVENT missing 'event' or 'data' | payload=") + dbg);
|
||||
LOG_WARN("Cluster", String("cluster/event missing 'event' or 'data' | payload=") + dbg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user