diff --git a/HyperionRGB/Config.cpp b/HyperionRGB/Config.cpp index 80b61cf..4501513 100644 --- a/HyperionRGB/Config.cpp +++ b/HyperionRGB/Config.cpp @@ -29,6 +29,7 @@ void Config::initConfig(void) { _cfgStruct.ports.udpLed = 19446; _cfgStruct.led.timeoutMs = 5000; _cfgStruct.led.autoswitch = true; + _cfgStruct.misc.udpProtocol = 0; EEPROM.end(); saveConfig(); Log.info("Configuration at 0x%x with v%i (v%i expected), new configuration created", CONFIG_START_ADDRESS, version, CONFIG_ACTIVE_VERSION); @@ -76,6 +77,8 @@ void Config::loadStaticConfig(void) { _cfgStruct.ports.jsonServer = CONFIG_PORT_JSON_SERVER; _cfgStruct.ports.udpLed = CONFIG_PORT_UDP_LED; + _cfgStruct.misc.udpProtocol = CONFIG_PROTOCOL_UDP; + saveConfig(); Log.info("CFG=%s", "loadStaticConfig END"); } diff --git a/HyperionRGB/ConfigStatic.h.example b/HyperionRGB/ConfigStatic.h.example index ad41c4f..6286f4a 100644 --- a/HyperionRGB/ConfigStatic.h.example +++ b/HyperionRGB/ConfigStatic.h.example @@ -57,3 +57,5 @@ #define CONFIG_PORT_JSON_SERVER 19444 #define CONFIG_PORT_UDP_LED 19446 + +#define CONFIG_PROTOCOL_UDP 0 diff --git a/HyperionRGB/ConfigStructures.h b/HyperionRGB/ConfigStructures.h index 0a467bb..3fa0270 100644 --- a/HyperionRGB/ConfigStructures.h +++ b/HyperionRGB/ConfigStructures.h @@ -30,7 +30,7 @@ typedef struct { uint8_t idleMode; uint32_t timeoutMs; boolean autoswitch; - + char spacer[59]; } ConfigLed; @@ -41,11 +41,18 @@ typedef struct { char spacer[32]; } ConfigPort; +typedef struct { + uint8_t udpProtocol; + + char spacer[63]; +} ConfigMisc; + typedef struct { uint8_t version; ConfigWifi wifi; ConfigLed led; ConfigPort ports; + ConfigMisc misc; } ConfigStruct; #endif diff --git a/HyperionRGB/HyperionRGB.ino b/HyperionRGB/HyperionRGB.ino index b195b30..1571bb4 100644 --- a/HyperionRGB/HyperionRGB.ino +++ b/HyperionRGB/HyperionRGB.ino @@ -142,6 +142,7 @@ void initConfig(void) { const byte* dns; uint16_t jsonServerPort; uint16_t udpLedPort; + uint8_t udpProtocol; #ifdef CONFIG_ENABLE_WEBCONFIG //TODO Fallback @@ -154,6 +155,7 @@ void initConfig(void) { dns = Config::cfg2ip(cfg->wifi.dns); jsonServerPort = cfg->ports.jsonServer; udpLedPort = cfg->ports.udpLed; + udpProtocol = cfg->misc.udpProtocol; autoswitch = cfg->led.autoswitch; Log.info("CFG=%s", "EEPROM config loaded"); @@ -171,13 +173,14 @@ void initConfig(void) { #endif jsonServerPort = CONFIG_PORT_JSON_SERVER; udpLedPort = CONFIG_PORT_UDP_LED; + udpProtocol = CONFIG_PROTOCOL_UDP; autoswitch = CONFIG_LED_HYPERION_AUTOSWITCH; Log.info("CFG=%s", "Static config loaded"); #endif wifi = WrapperWiFi(ssid, password, ip, subnet, dns); - udpLed = WrapperUdpLed(CONFIG_LED_COUNT, udpLedPort); + udpLed = WrapperUdpLed(CONFIG_LED_COUNT, udpLedPort, udpProtocol); jsonServer = WrapperJsonServer(CONFIG_LED_COUNT, jsonServerPort); } diff --git a/HyperionRGB/WrapperUdpLed.cpp b/HyperionRGB/WrapperUdpLed.cpp index df0b99c..5dd4e95 100644 --- a/HyperionRGB/WrapperUdpLed.cpp +++ b/HyperionRGB/WrapperUdpLed.cpp @@ -1,9 +1,10 @@ #include "WrapperUdpLed.h" -WrapperUdpLed::WrapperUdpLed(uint16_t ledCount, uint16_t udpPort) { +WrapperUdpLed::WrapperUdpLed(uint16_t ledCount, uint16_t udpPort, uint8_t udpProtocol) { _udp = WiFiUDP(); _ledCount = ledCount; _udpPort = udpPort; + _udpProtocol = udpProtocol; _bufferSize = _ledCount * 3; //3 bytes per LED @@ -15,7 +16,7 @@ WrapperUdpLed::WrapperUdpLed(uint16_t ledCount, uint16_t udpPort) { void WrapperUdpLed::begin(void) { if (!_opened) { - Log.info("Open port %i for UDP...", _udpPort); + Log.info("Open port %i for UDP with protocol %i...", _udpPort, _udpProtocol); if (_udp.begin(_udpPort)) { Log.info("success"); _opened = true; @@ -35,15 +36,35 @@ void WrapperUdpLed::handle(void) { int bytes = _udp.parsePacket(); if (bytes > 0) { Log.debug("UDP-Packet received, length: %i", bytes); - if (bytes == _bufferSize) { - _udp.readBytes(_udpBuffer, _bufferSize); - Log.verbose("Contents: %s", _udpBuffer); - for (int i=0; i<_ledCount; i++) { - updateLed(i, _udpBuffer[i*3+0], _udpBuffer[i*3+1], _udpBuffer[i*3+2]); + //See @https://hyperion-project.org/wiki/UDP-Device + if (_udpProtocol == 0) { + //Protocol 0: Raw Format, 3 bytes per LED, Full LED set. + /// {0: R, 1: G, 2: B} + if (bytes == _bufferSize) { + _udp.readBytes(_udpBuffer, _bufferSize); + Log.verbose("Contents: %s", _udpBuffer); + for (int i=0; i<_ledCount; i++) { + updateLed(i, _udpBuffer[i*3+0], _udpBuffer[i*3+1], _udpBuffer[i*3+2]); + } + refreshLeds(); + } else { + Log.debug("UDP-Packet size expected=%i, actual=%i", _bufferSize, bytes); } - refreshLeds(); - } else { - Log.debug("UDP-Packet size expected=%i, actual=%i", _bufferSize, bytes); + } else (_udpProtocol == 2) { + //Protocol 2: + /// 0: Update ID & 0xF + /// 1: Fragment ?! + /// 2: First LED ID, high byte / 3: First LED ID, low byte --> int16_t? + /// 4: {0: R, 1: G, 2: B} + } else (_udpProtocol == 3) { + //Protocol 3: TPM2.net + /// 0: 0x9C + /// 1: 0xDA + /// 2: Data length (LED count * 3), high byte, 3: Data length (LED count * 3), low byte --> int16_t? + /// 4: Fragment ID + /// 5: Fragment ID maximum + /// 6: {0: R, 1: G, 2: B} + /// 7: 0x36 } } } diff --git a/HyperionRGB/WrapperUdpLed.h b/HyperionRGB/WrapperUdpLed.h index c769eb2..8fb546f 100644 --- a/HyperionRGB/WrapperUdpLed.h +++ b/HyperionRGB/WrapperUdpLed.h @@ -7,7 +7,7 @@ class WrapperUdpLed { public: WrapperUdpLed() {}; - WrapperUdpLed(uint16_t ledCount, uint16_t udpPort); + WrapperUdpLed(uint16_t ledCount, uint16_t udpPort, uint8_t udpProtocol); void begin(void), @@ -22,6 +22,7 @@ class WrapperUdpLed { WiFiUDP _udp; uint16_t _ledCount; uint16_t _udpPort; + uint8_t _udpProtocol; byte* _udpBuffer; uint16_t _bufferSize; boolean _opened; diff --git a/HyperionRGB/WrapperWebconfig.cpp b/HyperionRGB/WrapperWebconfig.cpp index 85bbcf2..1b73ba8 100644 --- a/HyperionRGB/WrapperWebconfig.cpp +++ b/HyperionRGB/WrapperWebconfig.cpp @@ -120,6 +120,8 @@ void WrapperWebconfig::changeConfig(void) { cfg->ports.udpLed = 19446; } else if (argName == "led-idleMode") { cfg->led.idleMode = getSelectedEntry(argValue, _idleModes); + } else if (argName == "led-udpProtocol") { + cfg->misc.udpProtocol = getSelectedEntry(argValue, _udpProtocols); } else if (argName == "led-timeoutMs") { if (argValue.equals("0")) { cfg->led.timeoutMs = 0; @@ -322,11 +324,15 @@ String WrapperWebconfig::config(void) { groupContent = ""; _idleModes = new LinkedList(); + _udpProtocols = new LinkedList(); getIdleModes(cfg->led.idleMode, _idleModes); + getUdpProtocols(cfg->misc.udpProtocol, _udpProtocols); groupContent += selectTemplate("LED Idle Mode", "", "led-idleMode", _idleModes); groupContent += checkboxTemplate("Autoswitch to Hyperion_UDP/Idle Mode", "Automatically switch to Hyperion_UDP when UDP Data arriving and switch back to idle mode after timeout", "led-autoswitch", cfg->led.autoswitch); groupContent += textTemplate("Timeout Fallback in MS", "Switches back to Idle Mode after x milliseconds when no UDP data is arriving", "led-timeoutMs", escape(cfg->led.timeoutMs), "5000", 10); + groupContent += selectTemplate("LED UDP Protocol", "", "led-udpProtocol", _udpProtocols); clearLinkedList(_idleModes); + clearLinkedList(_udpProtocols); html += groupTemplate("LEDs", groupContent); @@ -370,10 +376,13 @@ void WrapperWebconfig::initHelperVars(void) { ConfigStruct *cfg = Config::getConfig(); _idleModes = new LinkedList(); + _udpProtocols = new LinkedList(); getIdleModes(cfg->led.idleMode, _idleModes); + getIdleModes(cfg->misc.udpProtocol, _udpProtocols); } void WrapperWebconfig::clearHelperVars(void) { clearLinkedList(_idleModes); + clearLinkedList(_udpProtocols); } void WrapperWebconfig::clearLinkedList(LinkedList* target) { Log.debug("Clearing LinkedList HEAP=%i", ESP.getFreeHeap()); @@ -409,3 +418,9 @@ void WrapperWebconfig::getIdleModes(uint8_t active, LinkedList target->add((SelectEntryBase*) new SelectEntry("Rainbow", "Rainbow", active == RAINBOW, RAINBOW)); target->add((SelectEntryBase*) new SelectEntry("Fire2012", "Fire2012", active == FIRE2012, FIRE2012)); } + +void WrapperWebconfig::getUdpProtocols(uint8_t active, LinkedList* target) { + target->add((SelectEntryBase*) new SelectEntry("0", "Protocol 0 (Raw)", active == 0, 0)); + target->add((SelectEntryBase*) new SelectEntry("0", "Protocol 2 (Fragment)", active == 2, 2)); + target->add((SelectEntryBase*) new SelectEntry("0", "Protocol 3 (TPM2 Fragments)", active == 3, 3)); +} diff --git a/HyperionRGB/WrapperWebconfig.h b/HyperionRGB/WrapperWebconfig.h index 0664882..232d617 100644 --- a/HyperionRGB/WrapperWebconfig.h +++ b/HyperionRGB/WrapperWebconfig.h @@ -79,7 +79,8 @@ class WrapperWebconfig { T getSelectedEntry(String selectedEntryValue, LinkedList* target); LinkedList* _idleModes; - + LinkedList* _udpProtocols; + #if defined(ESP8266) ESP8266WebServer* _server = new ESP8266WebServer(80); #elif defined(ESP32)