diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31c22f52..1277b32e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
### Development versions after 0.9.1 release
+#### Build 2004120
+
+- Added Art-Net support
+- Added OTA platform to platformio.ini
#### Build 2004100
@@ -23,7 +27,7 @@
#### Build 2003262
-- Fixed compilation for Analog LEDs
+- Fixed compilation for Analog LEDs
- Fixed sync settings network port fields too small
#### Build 2003261
diff --git a/platformio.ini b/platformio.ini
index 91bdd867..49517613 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -30,6 +30,7 @@ default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev
; default_envs = d1_mini
; default_envs = heltec_wifi_kit_8
; default_envs = d1_mini_debug
+; default_envs = d1_mini_ota
; default_envs = esp32dev
; default_envs = esp8285_4CH_MagicHome
; default_envs = esp8285_4CH_H801
@@ -241,6 +242,15 @@ platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
+[env:d1_mini_ota]
+board = d1_mini
+upload_protocol = espota
+# exchange for your WLED IP
+upload_port = "10.10.1.27"
+platform = ${common.platform_latest}
+board_build.ldscript = ${common.ldscript_4m1m}
+build_flags = ${common.build_flags_esp8266}
+
# ------------------------------------------------------------------------------
# custom board configurations
# ------------------------------------------------------------------------------
diff --git a/wled00/const.h b/wled00/const.h
index 173d7e7d..5cd4b02f 100644
--- a/wled00/const.h
+++ b/wled00/const.h
@@ -43,6 +43,7 @@
#define REALTIME_MODE_HYPERION 3
#define REALTIME_MODE_E131 4
#define REALTIME_MODE_ADALIGHT 5
+#define REALTIME_MODE_ARTNET 6
//E1.31 DMX modes
#define DMX_MODE_DISABLED 0 //not used
diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm
index 5cf4b608..91fe8992 100644
--- a/wled00/data/settings_sync.htm
+++ b/wled00/data/settings_sync.htm
@@ -1,141 +1,105 @@
-
-
-
- Sync Settings
-
-
-
-
-
+Sync Settings
+
+
+
+
\ No newline at end of file
diff --git a/wled00/e131.cpp b/wled00/e131.cpp
index 2034f84d..6e774194 100644
--- a/wled00/e131.cpp
+++ b/wled00/e131.cpp
@@ -4,29 +4,45 @@
* E1.31 handler
*/
-void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
+void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
//E1.31 protocol support
- uint16_t uni = htons(p->universe);
- uint8_t previousUniverses = uni - e131Universe;
- uint16_t possibleLEDsInCurrentUniverse;
- uint16_t dmxChannels = htons(p->property_value_count) -1;
+ uint16_t uni = 0, dmxChannels = 0;
+ uint8_t* e131_data = nullptr;
+ uint8_t seq = 0, mde = REALTIME_MODE_E131;
+
+ if (isArtnet)
+ {
+ uni = p->art_universe;
+ dmxChannels = htons(p->art_length);
+ e131_data = p->art_data;
+ seq = p->art_sequence_number;
+ mde = REALTIME_MODE_ARTNET;
+ } else {
+ uni = htons(p->universe);
+ dmxChannels = htons(p->property_value_count) -1;
+ e131_data = p->property_values;
+ seq = p->sequence_number;
+ }
// only listen for universes we're handling & allocated memory
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
+ uint8_t previousUniverses = uni - e131Universe;
+ uint16_t possibleLEDsInCurrentUniverse;
+
if (e131SkipOutOfSequence)
- if (p->sequence_number < e131LastSequenceNumber[uni-e131Universe] && p->sequence_number > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
+ if (seq < e131LastSequenceNumber[uni-e131Universe] && seq > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
DEBUG_PRINT("skipping E1.31 frame (last seq=");
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
DEBUG_PRINT(", current seq=");
- DEBUG_PRINT(p->sequence_number);
+ DEBUG_PRINT(seq);
DEBUG_PRINT(", universe=");
DEBUG_PRINT(uni);
DEBUG_PRINTLN(")");
return;
}
- e131LastSequenceNumber[uni-e131Universe] = p->sequence_number;
+ e131LastSequenceNumber[uni-e131Universe] = seq;
// update status info
realtimeIP = clientIP;
@@ -39,46 +55,46 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
case DMX_MODE_SINGLE_RGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 3) return;
- arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
+ realtimeLock(realtimeTimeoutMs, mde);
for (uint16_t i = 0; i < ledCount; i++)
- setRealtimePixel(i, p->property_values[DMXAddress+0], p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], 0);
+ setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], 0);
break;
case DMX_MODE_SINGLE_DRGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 4) return;
- arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
- if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
- DMXOldDimmer = p->property_values[DMXAddress+0];
- bri = p->property_values[DMXAddress+0];
+ realtimeLock(realtimeTimeoutMs, mde);
+ if (DMXOldDimmer != e131_data[DMXAddress+0]) {
+ DMXOldDimmer = e131_data[DMXAddress+0];
+ bri = e131_data[DMXAddress+0];
strip.setBrightness(bri);
}
for (uint16_t i = 0; i < ledCount; i++)
- setRealtimePixel(i, p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], p->property_values[DMXAddress+3], 0);
+ setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], 0);
break;
case DMX_MODE_EFFECT:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 11) return;
- if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
- DMXOldDimmer = p->property_values[DMXAddress+0];
- bri = p->property_values[DMXAddress+0];
+ if (DMXOldDimmer != e131_data[DMXAddress+0]) {
+ DMXOldDimmer = e131_data[DMXAddress+0];
+ bri = e131_data[DMXAddress+0];
}
- if (p->property_values[DMXAddress+1] < MODE_COUNT)
- effectCurrent = p->property_values[DMXAddress+ 1];
- effectSpeed = p->property_values[DMXAddress+ 2]; // flickers
- effectIntensity = p->property_values[DMXAddress+ 3];
- effectPalette = p->property_values[DMXAddress+ 4];
- col[0] = p->property_values[DMXAddress+ 5];
- col[1] = p->property_values[DMXAddress+ 6];
- col[2] = p->property_values[DMXAddress+ 7];
- colSec[0] = p->property_values[DMXAddress+ 8];
- colSec[1] = p->property_values[DMXAddress+ 9];
- colSec[2] = p->property_values[DMXAddress+10];
+ if (e131_data[DMXAddress+1] < MODE_COUNT)
+ effectCurrent = e131_data[DMXAddress+ 1];
+ effectSpeed = e131_data[DMXAddress+ 2]; // flickers
+ effectIntensity = e131_data[DMXAddress+ 3];
+ effectPalette = e131_data[DMXAddress+ 4];
+ col[0] = e131_data[DMXAddress+ 5];
+ col[1] = e131_data[DMXAddress+ 6];
+ col[2] = e131_data[DMXAddress+ 7];
+ colSec[0] = e131_data[DMXAddress+ 8];
+ colSec[1] = e131_data[DMXAddress+ 9];
+ colSec[2] = e131_data[DMXAddress+10];
if (dmxChannels-DMXAddress+1 > 11)
{
- col[3] = p->property_values[DMXAddress+11]; //white
- colSec[3] = p->property_values[DMXAddress+12];
+ col[3] = e131_data[DMXAddress+11]; //white
+ colSec[3] = e131_data[DMXAddress+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
@@ -86,13 +102,13 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
break;
case DMX_MODE_MULTIPLE_RGB:
- arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
+ realtimeLock(realtimeTimeoutMs, mde);
if (previousUniverses == 0) {
// first universe of this fixture
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
- setRealtimePixel(i, p->property_values[DMXAddress+i*3+0], p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], 0);
+ setRealtimePixel(i, e131_data[DMXAddress+i*3+0], e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
@@ -102,24 +118,24 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
- setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
+ setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
}
}
break;
case DMX_MODE_MULTIPLE_DRGB:
- arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
+ realtimeLock(realtimeTimeoutMs, mde);
if (previousUniverses == 0) {
// first universe of this fixture
- if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
- DMXOldDimmer = p->property_values[DMXAddress+0];
- bri = p->property_values[DMXAddress+0];
+ if (DMXOldDimmer != e131_data[DMXAddress+0]) {
+ DMXOldDimmer = e131_data[DMXAddress+0];
+ bri = e131_data[DMXAddress+0];
strip.setBrightness(bri);
}
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
- setRealtimePixel(i, p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], p->property_values[DMXAddress+i*3+3], 0);
+ setRealtimePixel(i, e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], e131_data[DMXAddress+i*3+3], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
@@ -129,7 +145,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
- setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
+ setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
}
}
break;
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h
index 7261efcb..2d8401bc 100644
--- a/wled00/fcn_declare.h
+++ b/wled00/fcn_declare.h
@@ -42,7 +42,7 @@ void initDMX();
void handleDMX();
//e131.cpp
-void handleE131Packet(e131_packet_t* p, IPAddress clientIP);
+void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet);
//file.cpp
bool handleFileRead(AsyncWebServerRequest*, String path);
@@ -103,12 +103,6 @@ void handleNightlight();
bool initMqtt();
void publishMqtt();
-//notify.cpp
-void notify(byte callMode, bool followUp=false);
-void arlsLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
-void handleNotifications();
-void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
-
//ntp.cpp
void handleNetworkTime();
void sendNTPPacket();
@@ -140,6 +134,12 @@ bool handleSet(AsyncWebServerRequest *request, const String& req);
int getNumVal(const String* req, uint16_t pos);
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
+//udp.cpp
+void notify(byte callMode, bool followUp=false);
+void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
+void handleNotifications();
+void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
+
//usermod.cpp
void userSetup();
void userConnected();
diff --git a/wled00/html_settings.h b/wled00/html_settings.h
index fa019533..009dda50 100644
--- a/wled00/html_settings.h
+++ b/wled00/html_settings.h
@@ -252,16 +252,16 @@ Sync button toggles both send and receive:
//sync settings
const char PAGE_settings_sync[] PROGMEM = R"=====(
-Sync Settings
-