From fec8343f45dd19c83d9ec1b213afa4b19e0a4713 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 18 May 2020 16:36:31 +0200 Subject: [PATCH] Added TPM2.NET protocol support --- platformio.ini | 2 +- wled00/const.h | 1 + wled00/json.cpp | 11 +- wled00/led.cpp | 5 +- wled00/set.cpp | 2 +- wled00/udp.cpp | 242 ++++++++++++++++++++++++----------------- wled00/wled.h | 5 +- wled00/wled_eeprom.cpp | 4 +- wled00/xml.cpp | 2 +- 9 files changed, 158 insertions(+), 116 deletions(-) diff --git a/platformio.ini b/platformio.ini index 4d404c7d..a637c5b3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -212,7 +212,7 @@ build_flags = ${common.build_flags_esp8266} [env:d1_mini] board = d1_mini platform = ${common.platform_latest} -upload_speed = 921500 +upload_speed = 921600 board_build.ldscript = ${common.ldscript_4m1m} build_flags = ${common.build_flags_esp8266} diff --git a/wled00/const.h b/wled00/const.h index 8a4a59dc..1e62ccfa 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -44,6 +44,7 @@ #define REALTIME_MODE_E131 4 #define REALTIME_MODE_ADALIGHT 5 #define REALTIME_MODE_ARTNET 6 +#define REALTIME_MODE_TPM2NET 7 //realtime override modes #define REALTIME_OVERRIDE_NONE 0 diff --git a/wled00/json.cpp b/wled00/json.cpp index 61e76a65..86a875ab 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -110,11 +110,7 @@ bool deserializeState(JsonObject root) presetCycleMin = ccnf["min"] | presetCycleMin; presetCycleMax = ccnf["max"] | presetCycleMax; tr = ccnf["time"] | -1; - if (tr >= 2) - { - presetCycleTime = tr; - presetCycleTime *= 100; - } + if (tr >= 2) presetCycleTime = tr; JsonObject nl = root["nl"]; nightlightActive = nl["on"] | nightlightActive; @@ -237,11 +233,11 @@ void serializeState(JsonObject root) root["pss"] = savedPresets; root["pl"] = (presetCyclingEnabled) ? 0: -1; - //temporary for preser cycle + //temporary for preset cycle JsonObject ccnf = root.createNestedObject("ccnf"); ccnf["min"] = presetCycleMin; ccnf["max"] = presetCycleMax; - ccnf["time"] = presetCycleTime/100; + ccnf["time"] = presetCycleTime; JsonObject nl = root.createNestedObject("nl"); nl["on"] = nightlightActive; @@ -321,6 +317,7 @@ void serializeInfo(JsonObject root) case REALTIME_MODE_E131: root["lm"] = "E1.31"; break; case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight"); case REALTIME_MODE_ARTNET: root["lm"] = "Art-Net"; break; + case REALTIME_MODE_TPM2NET: root["lm"] = F("tpm2.net"); break; } if (realtimeIP[0] == 0) diff --git a/wled00/led.cpp b/wled00/led.cpp index c3f50cc2..846b3ac5 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -251,11 +251,12 @@ void handleNightlight() } //also handle preset cycle here - if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime)) + if (presetCyclingEnabled && (millis() - presetCycledTime > (100*presetCycleTime))) { + if (presetCycCurr < presetCycleMin) presetCycCurr = presetCycleMin; applyPreset(presetCycCurr,presetApplyBri); presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin; - if (presetCycCurr > 25) presetCycCurr = 1; + if (presetCycCurr > 16) presetCycCurr = 1; colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE); presetCycledTime = millis(); } diff --git a/wled00/set.cpp b/wled00/set.cpp index 54581d01..18658521 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -468,7 +468,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req) pos = req.indexOf("PT="); //sets cycle time in ms if (pos > 0) { int v = getNumVal(&req, pos); - if (v > 49) presetCycleTime = v; + if (v > 100) presetCycleTime = v/100; } pos = req.indexOf("PA="); //apply brightness from preset diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 2b35054f..91426e91 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -1,7 +1,7 @@ #include "wled.h" /* - * UDP sync notifier + * UDP sync notifier / Realtime / Hyperion / TPM2.NET */ #define WLEDPACKETSIZE 29 @@ -89,6 +89,16 @@ void realtimeLock(uint32_t timeoutMs, byte md) } +#define TMP2NET_OUT_PORT 65442 + +void sendTPM2Ack() { + notifierUdp.beginPacket(notifierUdp.remoteIP(), TMP2NET_OUT_PORT); + uint8_t response_ack = 0xac; + notifierUdp.write(&response_ack, 1); + notifierUdp.endPacket(); +} + + void handleNotifications() { //send second notification if enabled @@ -139,122 +149,152 @@ void handleNotifications() } //notifier and UDP realtime - if (packetSize > UDP_IN_MAXSIZE) return; - if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves - { - uint8_t udpIn[packetSize]; - notifierUdp.read(udpIn, packetSize); + if (!packetSize || packetSize > UDP_IN_MAXSIZE) return; + if (notifierUdp.remoteIP() == WiFi.localIP()) return; //don't process broadcasts we send ourselves - //wled notifier, block if realtime packets active - if (udpIn[0] == 0 && !realtimeMode && receiveNotifications) + uint8_t udpIn[packetSize]; + notifierUdp.read(udpIn, packetSize); + + //wled notifier, block if realtime packets active + if (udpIn[0] == 0 && !realtimeMode && receiveNotifications) + { + //ignore notification if received within a second after sending a notification ourselves + if (millis() - notificationSentTime < 1000) return; + if (udpIn[1] > 199) return; //do not receive custom versions + + bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); + //apply colors from notification + if (receiveNotificationColor || !someSel) { - //ignore notification if received within a second after sending a notification ourselves - if (millis() - notificationSentTime < 1000) return; - if (udpIn[1] > 199) return; //do not receive custom versions - - bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects); - //apply colors from notification - if (receiveNotificationColor || !someSel) + col[0] = udpIn[3]; + col[1] = udpIn[4]; + col[2] = udpIn[5]; + if (udpIn[11] > 0) //sending module's white val is intended { - col[0] = udpIn[3]; - col[1] = udpIn[4]; - col[2] = udpIn[5]; - if (udpIn[11] > 0) //sending module's white val is intended + col[3] = udpIn[10]; + if (udpIn[11] > 1) { - col[3] = udpIn[10]; - if (udpIn[11] > 1) - { - colSec[0] = udpIn[12]; - colSec[1] = udpIn[13]; - colSec[2] = udpIn[14]; - colSec[3] = udpIn[15]; - } - if (udpIn[11] > 5) - { - uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]); - t += 2; - t -= millis(); - strip.timebase = t; - } - if (udpIn[11] > 6) - { - strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color - } + colSec[0] = udpIn[12]; + colSec[1] = udpIn[13]; + colSec[2] = udpIn[14]; + colSec[3] = udpIn[15]; + } + if (udpIn[11] > 5) + { + uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]); + t += 2; + t -= millis(); + strip.timebase = t; + } + if (udpIn[11] > 6) + { + strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color } } + } - //apply effects from notification - if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel)) - { - if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8]; - effectSpeed = udpIn[9]; - if (udpIn[11] > 2) effectIntensity = udpIn[16]; - if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19]; - } - - if (udpIn[11] > 3) - { - transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00); - } - - nightlightActive = udpIn[6]; - if (nightlightActive) nightlightDelayMins = udpIn[7]; - - if (receiveNotificationBrightness || !someSel) bri = udpIn[2]; - colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); - - } else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw + //apply effects from notification + if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel)) { - realtimeIP = notifierUdp.remoteIP(); - DEBUG_PRINTLN(notifierUdp.remoteIP()); - if (packetSize < 2) return; + if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8]; + effectSpeed = udpIn[9]; + if (udpIn[11] > 2) effectIntensity = udpIn[16]; + if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19]; + } + + if (udpIn[11] > 3) + { + transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00); + } - if (udpIn[1] == 0) - { - realtimeTimeout = 0; - return; - } else { - realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP); - } + nightlightActive = udpIn[6]; + if (nightlightActive) nightlightDelayMins = udpIn[7]; + + if (receiveNotificationBrightness || !someSel) bri = udpIn[2]; + colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); + + } + if (!receiveDirect) return; + + //TPM2.NET + if (udpIn[0] == 0x9c) + { + byte tpmType = udpIn[1]; + if (tpmType == 0xaa) { //TPM2.NET polling, expect answer + sendTPM2Ack(); return; + } + if (tpmType == 0xda) { //TPM2.NET data + realtimeIP = notifierUdp.remoteIP(); + realtimeLock(realtimeTimeoutMs, REALTIME_MODE_TPM2NET); if (realtimeOverride) return; - if (udpIn[0] == 1) //warls - { - for (uint16_t i = 2; i < packetSize -3; i += 4) - { - setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0); - } - } else if (udpIn[0] == 2) //drgb - { - uint16_t id = 0; - for (uint16_t i = 2; i < packetSize -2; i += 3) - { - setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0); + uint16_t frameSize = (udpIn[2] << 8) + udpIn[3]; + byte packetNum = udpIn[4]; //starts with 1! + byte numPackets = udpIn[5]; - id++; if (id >= ledCount) break; - } - } else if (udpIn[0] == 3) //drgbw + uint16_t id = tpmDataReceived / 3; //start LED + for (uint16_t i = 6; i < frameSize + 4; i += 3) { - uint16_t id = 0; - for (uint16_t i = 2; i < packetSize -3; i += 4) - { - setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]); - - id++; if (id >= ledCount) break; - } - } else if (udpIn[0] == 4) //dnrgb - { - uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00); - for (uint16_t i = 4; i < packetSize -2; i += 3) - { - if (id >= ledCount) break; - setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0); - id++; - } + setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0); + id++; if (id >= ledCount) break; } - strip.show(); + tpmDataReceived += frameSize; + if (packetNum == numPackets) {strip.show(); tpmDataReceived = 0;} //show if last packet } } + + //UDP realtime: 1 warls 2 drgb 3 drgbw + if (udpIn[0] > 0 && udpIn[0] < 5) + { + realtimeIP = notifierUdp.remoteIP(); + DEBUG_PRINTLN(notifierUdp.remoteIP()); + if (packetSize < 2) return; + + if (udpIn[1] == 0) + { + realtimeTimeout = 0; + return; + } else { + realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP); + } + if (realtimeOverride) return; + + if (udpIn[0] == 1) //warls + { + for (uint16_t i = 2; i < packetSize -3; i += 4) + { + setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0); + } + } else if (udpIn[0] == 2) //drgb + { + uint16_t id = 0; + for (uint16_t i = 2; i < packetSize -2; i += 3) + { + setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0); + + id++; if (id >= ledCount) break; + } + } else if (udpIn[0] == 3) //drgbw + { + uint16_t id = 0; + for (uint16_t i = 2; i < packetSize -3; i += 4) + { + setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]); + + id++; if (id >= ledCount) break; + } + } else if (udpIn[0] == 4) //dnrgb + { + uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00); + for (uint16_t i = 4; i < packetSize -2; i += 3) + { + if (id >= ledCount) break; + setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0); + id++; + } + } + strip.show(); + } } diff --git a/wled00/wled.h b/wled00/wled.h index f0021148..a98b2bd5 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2005100 +#define VERSION 2005180 // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS). @@ -415,7 +415,7 @@ WLED_GLOBAL bool blynkEnabled _INIT(false); // preset cycling WLED_GLOBAL bool presetCyclingEnabled _INIT(false); WLED_GLOBAL byte presetCycleMin _INIT(1), presetCycleMax _INIT(5); -WLED_GLOBAL uint16_t presetCycleTime _INIT(1250); +WLED_GLOBAL uint16_t presetCycleTime _INIT(12); WLED_GLOBAL unsigned long presetCycledTime _INIT(0); WLED_GLOBAL byte presetCycCurr _INIT(presetCycleMin); WLED_GLOBAL bool presetApplyBri _INIT(true); @@ -426,6 +426,7 @@ WLED_GLOBAL byte realtimeMode _INIT(REALTIME_MODE_INACTIVE); WLED_GLOBAL byte realtimeOverride _INIT(REALTIME_OVERRIDE_NONE); WLED_GLOBAL IPAddress realtimeIP _INIT((0, 0, 0, 0)); WLED_GLOBAL unsigned long realtimeTimeout _INIT(0); +WLED_GLOBAL uint16_t tpmDataReceived _INIT(0); // mqtt WLED_GLOBAL long lastMqttReconnectAttempt _INIT(0); diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp index 9a5b4bb7..a7afffe1 100644 --- a/wled00/wled_eeprom.cpp +++ b/wled00/wled_eeprom.cpp @@ -7,7 +7,7 @@ */ //eeprom Version code, enables default settings instead of 0 init on update -#define EEPVER 20 +#define EEPVER 21 //0 -> old version, default //1 -> 0.4p 1711272 and up //2 -> 0.4p 1711302 and up @@ -29,6 +29,7 @@ //18-> 0.9.1-e131 //19-> 0.9.1n //20-> 0.9.1p +//21-> 0.10.1p void commit() { @@ -547,6 +548,7 @@ void loadSettingsFromEEPROM(bool first) { presetCyclingEnabled = EEPROM.read(2205); presetCycleTime = EEPROM.read(2206) + ((EEPROM.read(2207) << 8) & 0xFF00); + if (lastEEPROMversion < 21) presetCycleTime /= 100; //was stored in ms, now is in tenths of a second presetCycleMin = EEPROM.read(2208); presetCycleMax = EEPROM.read(2209); presetApplyBri = EEPROM.read(2210); diff --git a/wled00/xml.cpp b/wled00/xml.cpp index c03240e0..a2c2d7db 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -77,7 +77,7 @@ char* XML_response(AsyncWebServerRequest *request, char* dest) mesg += "."; mesg += realtimeIP[i]; } - } else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION) { + } else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION || realtimeMode == REALTIME_MODE_TPM2NET) { mesg += "UDP from "; mesg += realtimeIP[0]; for (int i = 1; i < 4; i++)