From 10a599cacc00a523ef46a4d54bd39c47e64dcad5 Mon Sep 17 00:00:00 2001 From: Arthur Suzuki Date: Sat, 11 Jan 2025 15:24:17 +0100 Subject: [PATCH 1/5] also sync segment name through udp --- wled00/udp.cpp | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 4395b285d0..6c528b50a6 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -4,9 +4,9 @@ * UDP sync notifier / Realtime / Hyperion / TPM2.NET */ -#define UDP_SEG_SIZE 36 +#define UDP_SEG_SIZE (36+WLED_MAX_SEGNAME_LEN) #define SEG_OFFSET (41) -#define WLEDPACKETSIZE (41+(MAX_NUM_SEGMENTS*UDP_SEG_SIZE)+0) +#define WLEDPACKETSIZE (SEG_OFFSET+(MAX_NUM_SEGMENTS*UDP_SEG_SIZE)+0) #define UDP_IN_MAXSIZE 1472 #define PRESUMED_NETWORK_DELAY 3 //how many ms could it take on avg to reach the receiver? This will be added to transmitted times @@ -14,7 +14,7 @@ typedef struct PartialEspNowPacket { uint8_t magic; uint8_t packet; uint8_t noOfPackets; - uint8_t data[247]; + uint8_t data[277+WLED_MAX_SEGNAME_LEN]; } partial_packet_t; void notify(byte callMode, bool followUp) @@ -143,6 +143,11 @@ void notify(byte callMode, bool followUp) udpOut[33+ofs] = selseg.startY & 0xFF; udpOut[34+ofs] = selseg.stopY >> 8; // ATM always 0 as Segment::stopY is 8-bit udpOut[35+ofs] = selseg.stopY & 0xFF; + + if(selseg.name){ + strcpy((char *)&udpOut[36+ofs], selseg.name); + } + ++s; } @@ -155,7 +160,7 @@ void notify(byte callMode, bool followUp) // send global data DEBUG_PRINTLN(F("ESP-NOW sending first packet.")); const size_t bufferSize = sizeof(buffer.data)/sizeof(uint8_t); - size_t packetSize = 41; + size_t packetSize = SEG_OFFSET; size_t s0 = 0; memcpy(buffer.data, udpOut, packetSize); // stuff as many segments in first packet as possible (normally up to 5) @@ -267,7 +272,7 @@ static void parseNotifyPacket(const uint8_t *udpIn) { } size_t inactiveSegs = 0; for (size_t i = 0; i < numSrcSegs && i < strip.getMaxSegments(); i++) { - unsigned ofs = 41 + i*udpIn[40]; //start of segment offset byte + unsigned ofs = SEG_OFFSET + i*udpIn[40]; //start of segment offset byte unsigned id = udpIn[0 +ofs]; DEBUG_PRINTF_P(PSTR("UDP segment received: %u\n"), id); if (id > strip.getSegmentsNum()) break; @@ -296,6 +301,7 @@ static void parseNotifyPacket(const uint8_t *udpIn) { uint16_t startY = version > 11 ? (udpIn[32+ofs] << 8 | udpIn[33+ofs]) : 0; uint16_t stopY = version > 11 ? (udpIn[34+ofs] << 8 | udpIn[35+ofs]) : 1; uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]); + if (!receiveSegmentOptions) { DEBUG_PRINTF_P(PSTR("Set segment w/o options: %d [%d,%d;%d,%d]\n"), id, (int)start, (int)stop, (int)startY, (int)stopY); strip.suspend(); //should not be needed as UDP handling is not done in ISR callbacks but still added "just in case" @@ -337,6 +343,20 @@ static void parseNotifyPacket(const uint8_t *udpIn) { selseg.check1 = (udpIn[31+ofs]>>6) & 0x1; selseg.check1 = (udpIn[31+ofs]>>7) & 0x1; } + + if (selseg.name) { //clear old name + delete[] selseg.name; + selseg.name = nullptr; + } + + const char * name = (char *) &udpIn[36+ofs]; + size_t len = 0; + if (name != nullptr) len = strlen(name); + if (len > 0) { + if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN; + selseg.name = new char[len+1]; + if (selseg.name) strcpy(selseg.name, name); + } } if (receiveSegmentBounds) { DEBUG_PRINTF_P(PSTR("Set segment w/ options: %d [%d,%d;%d,%d]\n"), id, (int)start, (int)stop, (int)startY, (int)stopY); From 56804d7e9438147fd92b60afdd0914164dbea2ba Mon Sep 17 00:00:00 2001 From: Arthur Suzuki Date: Tue, 14 Jan 2025 11:13:25 +0100 Subject: [PATCH 2/5] add a new option "Segment name" in the sync settings this option is disabled by default. When enabled, the segment name is applied when received from another WLED instance. --- wled00/data/settings_sync.htm | 2 +- wled00/set.cpp | 1 + wled00/udp.cpp | 15 ++++++++------- wled00/wled.h | 6 +++++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index ca6c0fb59c..ebaea5f32f 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -101,7 +101,7 @@

Sync groups

Receive

Brightness, Color, Effects, and Palette
- Segment options, bounds + Segment options, Segment name, bounds

Send

Enable Sync on start:
Send notifications on direct change:
diff --git a/wled00/set.cpp b/wled00/set.cpp index c0977f262c..4158945374 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -378,6 +378,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) receiveNotificationEffects = request->hasArg(F("RX")); receiveNotificationPalette = request->hasArg(F("RP")); receiveSegmentOptions = request->hasArg(F("SO")); + receiveSegmentName = request->hasArg(F("SN")); receiveSegmentBounds = request->hasArg(F("SG")); sendNotifications = request->hasArg(F("SS")); notifyDirect = request->hasArg(F("SD")); diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 6c528b50a6..1740b1226f 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -343,20 +343,21 @@ static void parseNotifyPacket(const uint8_t *udpIn) { selseg.check1 = (udpIn[31+ofs]>>6) & 0x1; selseg.check1 = (udpIn[31+ofs]>>7) & 0x1; } - + } + if (receiveSegmentName) { if (selseg.name) { //clear old name - delete[] selseg.name; - selseg.name = nullptr; + delete[] selseg.name; + selseg.name = nullptr; } const char * name = (char *) &udpIn[36+ofs]; size_t len = 0; if (name != nullptr) len = strlen(name); if (len > 0) { - if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN; - selseg.name = new char[len+1]; - if (selseg.name) strcpy(selseg.name, name); - } + if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN; + selseg.name = new char[len+1]; + if (selseg.name) strcpy(selseg.name, name); + } } if (receiveSegmentBounds) { DEBUG_PRINTF_P(PSTR("Set segment w/ options: %d [%d,%d;%d,%d]\n"), id, (int)start, (int)stop, (int)startY, (int)stopY); diff --git a/wled00/wled.h b/wled00/wled.h index a18199446c..c610d47c55 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -647,6 +647,7 @@ typedef class Receive { bool Color : 1; bool Effects : 1; bool SegmentOptions : 1; + bool SegmentName : 1; bool SegmentBounds : 1; bool Direct : 1; bool Palette : 1; @@ -654,11 +655,12 @@ typedef class Receive { }; }; Receive(int i) { Options = i; } - Receive(bool b, bool c, bool e, bool sO, bool sB, bool p) + Receive(bool b, bool c, bool e, bool sO, bool sN, bool sB, bool p) : Brightness(b) , Color(c) , Effects(e) , SegmentOptions(sO) + , SegmentName(sN) , SegmentBounds(sB) , Palette(p) {}; @@ -690,6 +692,7 @@ WLED_GLOBAL send_notification_t notifyG _INIT(0b00001111); #define receiveNotificationEffects receiveN.Effects #define receiveNotificationPalette receiveN.Palette #define receiveSegmentOptions receiveN.SegmentOptions +#define receiveSegmentName receiveN.SegmentName #define receiveSegmentBounds receiveN.SegmentBounds #define receiveDirect receiveN.Direct #define notifyDirect notifyG.Direct @@ -702,6 +705,7 @@ WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup WLED_GLOBAL bool receiveNotificationPalette _INIT(true); // apply palette WLED_GLOBAL bool receiveSegmentOptions _INIT(false); // apply segment options +WLED_GLOBAL bool receiveSegmentName _INIT(false); WLED_GLOBAL bool receiveSegmentBounds _INIT(false); // apply segment bounds (start, stop, offset) WLED_GLOBAL bool receiveDirect _INIT(true); // receive UDP/Hyperion realtime WLED_GLOBAL bool notifyDirect _INIT(false); // send notification if change via UI or HTTP API From 12bbd20ecf53e44ae3aa7f878328323d27c2c87d Mon Sep 17 00:00:00 2001 From: Arthur Suzuki Date: Thu, 30 Jan 2025 14:19:44 +0100 Subject: [PATCH 3/5] fix JSON and checkbox now properly reflects current state --- wled00/cfg.cpp | 2 ++ wled00/xml.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 00cfc60d7e..b40b744cfc 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -481,6 +481,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(receiveNotificationPalette, if_sync_recv["pal"]); CJSON(receiveGroups, if_sync_recv["grp"]); CJSON(receiveSegmentOptions, if_sync_recv["seg"]); + CJSON(receiveSegmentName, if_sync_recv["sn"]); CJSON(receiveSegmentBounds, if_sync_recv["sb"]); JsonObject if_sync_send = if_sync[F("send")]; @@ -974,6 +975,7 @@ void serializeConfig() { if_sync_recv["pal"] = receiveNotificationPalette; if_sync_recv["grp"] = receiveGroups; if_sync_recv["seg"] = receiveSegmentOptions; + if_sync_recv["sn"] = receiveSegmentName; if_sync_recv["sb"] = receiveSegmentBounds; JsonObject if_sync_send = if_sync.createNestedObject(F("send")); diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 78d2d7d567..2143d612af 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -416,6 +416,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormCheckbox(settingsScript,PSTR("RX"),receiveNotificationEffects); printSetFormCheckbox(settingsScript,PSTR("RP"),receiveNotificationPalette); printSetFormCheckbox(settingsScript,PSTR("SO"),receiveSegmentOptions); + printSetFormCheckbox(settingsScript,PSTR("SN"),receiveSegmentName); printSetFormCheckbox(settingsScript,PSTR("SG"),receiveSegmentBounds); printSetFormCheckbox(settingsScript,PSTR("SS"),sendNotifications); printSetFormCheckbox(settingsScript,PSTR("SD"),notifyDirect); From 712eee732d13ce26d3e4a8e061d1e84d17a17e7d Mon Sep 17 00:00:00 2001 From: Arthur Suzuki Date: Wed, 5 Feb 2025 00:47:43 +0100 Subject: [PATCH 4/5] couple optimization after review --- wled00/data/settings_sync.htm | 4 ++-- wled00/udp.cpp | 28 +++++++--------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index ebaea5f32f..08a84465f3 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -101,7 +101,7 @@

Sync groups

Receive

Brightness, Color, Effects, and Palette
- Segment options, Segment name, bounds + Segment options, name, bounds

Send

Enable Sync on start:
Send notifications on direct change:
@@ -241,4 +241,4 @@

Serial

- \ No newline at end of file + diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 1740b1226f..68f42994c9 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -14,7 +14,7 @@ typedef struct PartialEspNowPacket { uint8_t magic; uint8_t packet; uint8_t noOfPackets; - uint8_t data[277+WLED_MAX_SEGNAME_LEN]; + uint8_t data[247]; } partial_packet_t; void notify(byte callMode, bool followUp) @@ -161,14 +161,10 @@ void notify(byte callMode, bool followUp) DEBUG_PRINTLN(F("ESP-NOW sending first packet.")); const size_t bufferSize = sizeof(buffer.data)/sizeof(uint8_t); size_t packetSize = SEG_OFFSET; - size_t s0 = 0; memcpy(buffer.data, udpOut, packetSize); - // stuff as many segments in first packet as possible (normally up to 5) - for (size_t i = 0; packetSize < bufferSize && i < s; i++) { - memcpy(buffer.data + packetSize, &udpOut[41+i*UDP_SEG_SIZE], UDP_SEG_SIZE); - packetSize += UDP_SEG_SIZE; - s0++; - } + // since we sync the name, only one segment can fit in the first packet + memcpy(buffer.data + packetSize, &udpOut[41+UDP_SEG_SIZE], UDP_SEG_SIZE); + size_t s0 = 1; if (s > s0) buffer.noOfPackets += 1 + ((s - s0) * UDP_SEG_SIZE) / bufferSize; // set number of packets auto err = quickEspNow.send(ESPNOW_BROADCAST_ADDRESS, reinterpret_cast(&buffer), packetSize+3); if (!err && s0 < s) { @@ -345,19 +341,9 @@ static void parseNotifyPacket(const uint8_t *udpIn) { } } if (receiveSegmentName) { - if (selseg.name) { //clear old name - delete[] selseg.name; - selseg.name = nullptr; - } - - const char * name = (char *) &udpIn[36+ofs]; - size_t len = 0; - if (name != nullptr) len = strlen(name); - if (len > 0) { - if (len > WLED_MAX_SEGNAME_LEN) len = WLED_MAX_SEGNAME_LEN; - selseg.name = new char[len+1]; - if (selseg.name) strcpy(selseg.name, name); - } + const char* name = (char *) &udpIn[36+ofs]; + selseg.clearName(); + selseg.setName(name); } if (receiveSegmentBounds) { DEBUG_PRINTF_P(PSTR("Set segment w/ options: %d [%d,%d;%d,%d]\n"), id, (int)start, (int)stop, (int)startY, (int)stopY); From 26081bfa906f02f39ca98f9d88f60ead3e21c9ae Mon Sep 17 00:00:00 2001 From: Liliputech Date: Wed, 19 Feb 2025 15:00:56 +0100 Subject: [PATCH 5/5] Check if received segment name is not longer than allowed Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- wled00/udp.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 68f42994c9..14414b4705 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -341,9 +341,11 @@ static void parseNotifyPacket(const uint8_t *udpIn) { } } if (receiveSegmentName) { - const char* name = (char *) &udpIn[36+ofs]; - selseg.clearName(); - selseg.setName(name); + const char* name = (char *) &udpIn[36+ofs]; + if (strlen(name) < WLED_MAX_SEGNAME_LEN) { + selseg.clearName(); + selseg.setName(name); + } } if (receiveSegmentBounds) { DEBUG_PRINTF_P(PSTR("Set segment w/ options: %d [%d,%d;%d,%d]\n"), id, (int)start, (int)stop, (int)startY, (int)stopY);