Added TPM2.NET protocol support

This commit is contained in:
cschwinne 2020-05-18 16:36:31 +02:00
parent 579f355852
commit fec8343f45
9 changed files with 158 additions and 116 deletions

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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++)