diff --git a/usermods/udp_name_sync/library.json b/usermods/udp_name_sync/library.json new file mode 100644 index 00000000..4c5bb448 --- /dev/null +++ b/usermods/udp_name_sync/library.json @@ -0,0 +1,5 @@ +{ + "name": "udp_name_sync", + "build": { "libArchive": false }, + "dependencies": {} +} diff --git a/usermods/udp_name_sync/udp_name_sync.cpp b/usermods/udp_name_sync/udp_name_sync.cpp new file mode 100644 index 00000000..d926e1b6 --- /dev/null +++ b/usermods/udp_name_sync/udp_name_sync.cpp @@ -0,0 +1,79 @@ +#include "wled.h" + +class UdpNameSync : public Usermod { + + private: + + bool enabled = false; + bool initDone = false; + unsigned long lastTime = 0; + char segmentName[WLED_MAX_SEGNAME_LEN] = {0}; + static const char _name[]; + static const char _enabled[]; + + public: + /** + * Enable/Disable the usermod + */ + inline void enable(bool enable) { enabled = enable; } + + /** + * Get usermod enabled/disabled state + */ + inline bool isEnabled() { return enabled; } + + void setup() override { + initDone = true; + } + + void loop() override { + if (!WLED_CONNECTED) return; + if (!udpConnected) return; + Segment& mainseg = strip.getMainSegment(); + if (!strlen(segmentName) && !mainseg.name) return; //name was never set, do nothing + + IPAddress broadcastIp = ~uint32_t(Network.subnetMask()) | uint32_t(Network.gatewayIP()); + byte udpOut[WLED_MAX_SEGNAME_LEN + 2]; + udpOut[0] = 2; // 0: wled notifier protocol, 1: warls protocol, 2 is free + + if (strlen(segmentName) && !mainseg.name) { //name is back to null + notifierUdp.beginPacket(broadcastIp, udpPort); + strcpy(segmentName,""); + DEBUG_PRINTLN(F("UdpNameSync: sending Null name")); + notifierUdp.write( udpOut , 2); + notifierUdp.endPacket(); + return; + } + + if (0 == strcmp(mainseg.name, segmentName)) return; //same name, do nothing + + notifierUdp.beginPacket(broadcastIp, udpPort); + DEBUG_PRINT(F("UdpNameSync: saving segment name ")); + DEBUG_PRINTLN(mainseg.name); + byte length = strlen(mainseg.name); + strlcpy(segmentName, mainseg.name, length+1); + strlcpy((char *)&udpOut[1], segmentName, length+1); + notifierUdp.write(udpOut, length + 2); + notifierUdp.endPacket(); + DEBUG_PRINT(F("UdpNameSync: Sent segment name : ")); + DEBUG_PRINTLN(segmentName); + } + + bool onUdpPacket(uint8_t * payload, uint8_t len) override { + DEBUG_PRINT(F("UdpNameSync: Received packet")); + if (payload[0] != 2) return false; + //else + Segment& mainseg = strip.getMainSegment(); + mainseg.setName((char *)&payload[1]); + DEBUG_PRINT(F("UdpNameSync: set segment name")); + return true; + } +}; + + +// add more strings here to reduce flash memory usage +const char UdpNameSync::_name[] PROGMEM = "UdpNameSync"; +const char UdpNameSync::_enabled[] PROGMEM = "enabled"; + +static UdpNameSync udp_name_sync; +REGISTER_USERMOD(udp_name_sync); diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 0cd28a31..326ae122 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -442,6 +442,7 @@ class Usermod { virtual void onMqttConnect(bool sessionPresent) {} // fired when MQTT connection is established (so usermod can subscribe) virtual bool onMqttMessage(char* topic, char* payload) { return false; } // fired upon MQTT message received (wled topic) virtual bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len) { return false; } // fired upon ESP-NOW message received + virtual bool onUdpPacket(uint8_t* payload, uint8_t len) { return false; } //fired upon UDP packet received virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;} @@ -481,6 +482,7 @@ namespace UsermodManager { #ifndef WLED_DISABLE_ESPNOW bool onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t len); #endif + bool onUdpPacket(uint8_t* payload, uint8_t len); void onUpdateBegin(bool); void onStateChange(uint8_t); Usermod* lookup(uint16_t mod_id); diff --git a/wled00/udp.cpp b/wled00/udp.cpp index bdb60c36..7b9e53bc 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -557,6 +557,9 @@ void handleNotifications() return; } + // usermods hook can override processing + if (UsermodManager::onUdpPacket(udpIn, packetSize)) return; + //wled notifier, ignore if realtime packets active if (udpIn[0] == 0 && !realtimeMode && receiveGroups) { diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index 1a7cc226..483fdc68 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -68,6 +68,10 @@ bool UsermodManager::onEspNowMessage(uint8_t* sender, uint8_t* payload, uint8_t return false; } #endif +bool UsermodManager::onUdpPacket(uint8_t* payload, uint8_t len) { + for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) if ((*mod)->onUdpPacket(payload, len)) return true; + return false; +} void UsermodManager::onUpdateBegin(bool init) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->onUpdateBegin(init); } // notify usermods that update is to begin void UsermodManager::onStateChange(uint8_t mode) { for (auto mod = _usermod_table_begin; mod < _usermod_table_end; ++mod) (*mod)->onStateChange(mode); } // notify usermods that WLED state changed