Merge branch 'mdev' into gif-MM

This commit is contained in:
netmindz
2025-06-15 12:05:18 +01:00
committed by GitHub
9 changed files with 93 additions and 53 deletions

View File

@@ -260,7 +260,7 @@ lib_deps =
;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6
IRremoteESP8266 @ 2.8.2 IRremoteESP8266 @ 2.8.2
;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 ;; newer with bugfixes and stability improvements https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.0
bitbank2/AnimatedGIF@^1.4.7 bitbank2/AnimatedGIF@^1.4.7
https://github.com/Aircoookie/GifDecoder#bc3af18 https://github.com/Aircoookie/GifDecoder#bc3af18
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line #For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
@@ -340,7 +340,7 @@ lib_deps_compat =
fastled/FastLED @ 3.6.0 fastled/FastLED @ 3.6.0
IRremoteESP8266 @ 2.8.2 IRremoteESP8266 @ 2.8.2
makuna/NeoPixelBus @ 2.7.9 makuna/NeoPixelBus @ 2.7.9
https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.2.1 https://github.com/Aircoookie/ESPAsyncWebServer.git#v2.4.0
[esp32] [esp32]

View File

@@ -1836,54 +1836,62 @@ class AudioReactive : public Usermod {
agcSensitivity = 128.0f; // substitute - V1 format does not include this value agcSensitivity = 128.0f; // substitute - V1 format does not include this value
} }
bool receiveAudioData() // check & process new data. return TRUE in case that new audio data was received. bool receiveAudioData() {
{
if (!udpSyncConnected) return false; if (!udpSyncConnected) return false;
bool haveFreshData = false; bool haveFreshData = false;
size_t packetSize = 0; size_t packetSize = 0;
// WLEDMM use exception handler to catch out-of-memory errors static uint8_t fftUdpBuffer[UDPSOUND_MAX_PACKET + 1] = {0};
#if __cpp_exceptions size_t lastValidPacketSize = 0;
try{
// Loop to read all available packets
while (true) {
#if __cpp_exceptions
try {
packetSize = fftUdp.parsePacket(); packetSize = fftUdp.parsePacket();
} catch(...) { } catch (...) {
packetSize = 0; // low heap memory -> discard packet. packetSize = 0;
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
fftUdp.flush(); // this does not work on 8266 fftUdp.flush();
#endif #endif
DEBUG_PRINTLN(F("receiveAudioData: parsePacket out of memory exception caught!")); DEBUG_PRINTLN(F("receiveAudioData: parsePacket out of memory exception caught!"));
USER_FLUSH(); USER_FLUSH();
continue; // Skip to next iteration
} }
#else #else
packetSize = fftUdp.parsePacket(); packetSize = fftUdp.parsePacket();
#endif #endif
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
if ((packetSize > 0) && ((packetSize < 5) || (packetSize > UDPSOUND_MAX_PACKET))) fftUdp.flush(); // discard invalid packets (too small or too big) if ((packetSize > 0) && ((packetSize < 5) || (packetSize > UDPSOUND_MAX_PACKET))) {
#endif fftUdp.flush();
if ((packetSize > 5) && (packetSize <= UDPSOUND_MAX_PACKET)) { continue; // Skip invalid packets
static uint8_t fftUdpBuffer[UDPSOUND_MAX_PACKET+1] = { 0 }; // static buffer for receiving, to reuse the same memory and avoid heap fragmentation }
//DEBUGSR_PRINTLN("Received UDP Sync Packet"); #endif
fftUdp.read(fftUdpBuffer, packetSize);
// VERIFY THAT THIS IS A COMPATIBLE PACKET if (packetSize == 0) break; // No more packets available
if (packetSize == sizeof(audioSyncPacket) && (isValidUdpSyncVersion((const char *)fftUdpBuffer))) {
if ((packetSize > 5) && (packetSize <= UDPSOUND_MAX_PACKET)) {
fftUdp.read(fftUdpBuffer, packetSize);
lastValidPacketSize = packetSize;
}
}
// Process only the last valid packet
if (lastValidPacketSize > 0) {
if (lastValidPacketSize == sizeof(audioSyncPacket) && (isValidUdpSyncVersion((const char *)fftUdpBuffer))) {
receivedFormat = 2; receivedFormat = 2;
haveFreshData = decodeAudioData(packetSize, fftUdpBuffer); haveFreshData = decodeAudioData(lastValidPacketSize, fftUdpBuffer);
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet v2"); } else if (lastValidPacketSize == sizeof(audioSyncPacket_v1) && (isValidUdpSyncVersion_v1((const char *)fftUdpBuffer))) {
decodeAudioData_v1(lastValidPacketSize, fftUdpBuffer);
receivedFormat = 1;
haveFreshData = true;
} else { } else {
if (packetSize == sizeof(audioSyncPacket_v1) && (isValidUdpSyncVersion_v1((const char *)fftUdpBuffer))) { receivedFormat = 0; // unknown format
decodeAudioData_v1(packetSize, fftUdpBuffer);
receivedFormat = 1;
//DEBUGSR_PRINTLN("Finished parsing UDP Sync Packet v1");
haveFreshData = true;
} else receivedFormat = 0; // unknown format
} }
} }
return haveFreshData; return haveFreshData;
} }
////////////////////// //////////////////////
// usermod functions// // usermod functions//
////////////////////// //////////////////////
@@ -2319,6 +2327,7 @@ class AudioReactive : public Usermod {
static float syncVolumeSmth = 0; static float syncVolumeSmth = 0;
bool have_new_sample = false; bool have_new_sample = false;
if (millis() - lastTime > delayMs) { if (millis() - lastTime > delayMs) {
// DEBUG_PRINTF(F("AR reading at %d compared to %d max\n"), millis() - lastTime, delayMs); // TroyHacks
have_new_sample = receiveAudioData(); have_new_sample = receiveAudioData();
if (have_new_sample) { if (have_new_sample) {
last_UDPTime = millis(); last_UDPTime = millis();

View File

@@ -246,11 +246,12 @@
gId("dig"+n+"W").innerHTML = "<br />You need at least 1 output!"; gId("dig"+n+"W").innerHTML = "<br />You need at least 1 output!";
} }
if (outputs > 1 && fps_limit > 33333/leds_per_output) gId("dig"+n+"W").innerHTML += "<br />FPS limit may be too high for WS281x pixels."; if (outputs > 1 && fps_limit > 33333/leds_per_output) gId("dig"+n+"W").innerHTML += "<br />FPS limit may be too high for WS281x pixels.";
if (outputs*leds_per_output != total_leds) gId("dig"+n+"W").innerHTML += "<br />Total LEDs doesn't match outputs * LEDs per output."; if (outputs*leds_per_output != total_leds) gId("dig"+n+"W").innerHTML += "<br />Length ("+total_leds+") doesn't match Number of Outputs * LEDs Per Output ("+outputs*leds_per_output+").";
if (last_octet == 255) { if (last_octet == 255) {
if (total_leds <= 1024) gId("dig"+n+"W").innerHTML += "<br />Art-Net is in broadcast mode."; if (total_leds <= 1024) gId("dig"+n+"W").innerHTML += "<br />Art-Net is in broadcast mode.";
if (total_leds > 1024) gId("dig"+n+"W").innerHTML += "<br />You are sending a lot of broadcast data. Be cautious."; if (total_leds > 1024) gId("dig"+n+"W").innerHTML += "<br />You are sending a lot of broadcast data. Be cautious.";
} }
gId("dig"+n+"W").innerHTML += "<br />Art-Net starting universe is "+d.e131Universe+". Change this in <a href='/settings/sync'>Sync Interfaces</a>.";
} }
if (!(t > 28 && t < 32)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping if (!(t > 28 && t < 32)) d.getElementsByName("WO"+n)[0].value = 0; // reset swapping
gId("dig"+n+"c").style.display = ((t >= 40 && t < 48)||(t >= 100 && t < 110)) ? "none":"inline"; // hide count for analog and HUB75 gId("dig"+n+"c").style.display = ((t >= 40 && t < 48)||(t >= 100 && t < 110)) ? "none":"inline"; // hide count for analog and HUB75
@@ -422,6 +423,7 @@ ${i+1}:
<option value="80">DDP RGB (network)</option> <option value="80">DDP RGB (network)</option>
<!--option value="81">E1.31 RGB (network)</option--> <!--option value="81">E1.31 RGB (network)</option-->
<option value="82">Art-Net RGB (network)</option> <option value="82">Art-Net RGB (network)</option>
<option value="83">Art-Net RGBW (network)</option>
<option value="88">DDP RGBW (network)</option> <option value="88">DDP RGBW (network)</option>
<option value="101">Hub75Matrix 32x32</option> <option value="101">Hub75Matrix 32x32</option>
<option value="102">Hub75Matrix 64x32</option> <option value="102">Hub75Matrix 64x32</option>

View File

@@ -80,7 +80,7 @@
<div class="helpB"><button type="button" onclick="H()">?</button></div> <div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr> <button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
</div> </div>
<h2>Sync setup</h2> <h2>Sync Interfaces</h2>
<h3>WLED Broadcast</h3> <h3>WLED Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br> UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br> 2nd Port: <input name="U2" type="number" min="1" max="65535" class="d5" required><br>
@@ -139,7 +139,7 @@ Make this instance discoverable: <input type="checkbox" name="NB">
<h3>Realtime</h3> <h3>Realtime</h3>
Receive UDP realtime: <input type="checkbox" name="RD"><br> Receive UDP realtime: <input type="checkbox" name="RD"><br>
Use main segment only: <input type="checkbox" name="MO"><br><br> Use main segment only: <input type="checkbox" name="MO"><br><br>
<i>Network DMX input</i><br> <i>Network DMX</i><br>
Type: Type:
<select name=DI onchange="SP(); adj();"> <select name=DI onchange="SP(); adj();">
<option value=5568>E1.31 (sACN)</option> <option value=5568>E1.31 (sACN)</option>
@@ -148,7 +148,7 @@ Type:
</select><br> </select><br>
<div id=xp>Port: <input name="EP" type="number" min="1" max="65535" value="5568" class="d5" required><br></div> <div id=xp>Port: <input name="EP" type="number" min="1" max="65535" value="5568" class="d5" required><br></div>
Multicast: <input type="checkbox" name="EM"><br> Multicast: <input type="checkbox" name="EM"><br>
Start universe: <input name="EU" type="number" min="0" max="63999" required><br> Start universe: <input name="EU" type="number" min="0" max="63999" required> (Also used for sending Art-Net)<br>
<i>Reboot required.</i> Check out <a href="https://github.com/LedFx/LedFx" target="_blank">LedFx</a>!<br> <i>Reboot required.</i> Check out <a href="https://github.com/LedFx/LedFx" target="_blank">LedFx</a>!<br>
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br> Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
DMX start address: <input name="DA" type="number" min="1" max="510" required><br> DMX start address: <input name="DA" type="number" min="1" max="510" required><br>

View File

@@ -66,6 +66,9 @@ static bool bufferedFind(const char *target, bool fromStart = true) {
size_t index = 0; size_t index = 0;
byte buf[FS_BUFSIZE]; byte buf[FS_BUFSIZE];
#if ESP_IDF_VERSION_MAJOR >= 4
f.setBufferSize(FS_BUFSIZE);
#endif
if (fromStart) f.seek(0); if (fromStart) f.seek(0);
while (f.position() < f.size() -1) { while (f.position() < f.size() -1) {
@@ -107,6 +110,9 @@ static bool bufferedFindSpace(size_t targetLen, bool fromStart = true) {
size_t index = 0; // better to use size_t instead if uint16_t size_t index = 0; // better to use size_t instead if uint16_t
byte buf[FS_BUFSIZE]; byte buf[FS_BUFSIZE];
#if ESP_IDF_VERSION_MAJOR >= 4
f.setBufferSize(FS_BUFSIZE);
#endif
if (fromStart) f.seek(0); if (fromStart) f.seek(0);
while (f.position() < f.size() -1) { while (f.position() < f.size() -1) {
@@ -150,7 +156,9 @@ static bool bufferedFindObjectEnd() {
uint16_t objDepth = 0; //num of '{' minus num of '}'. return once 0 uint16_t objDepth = 0; //num of '{' minus num of '}'. return once 0
//size_t start = f.position(); //size_t start = f.position();
byte buf[FS_BUFSIZE]; byte buf[FS_BUFSIZE];
#if ESP_IDF_VERSION_MAJOR >= 4
f.setBufferSize(FS_BUFSIZE);
#endif
while (f.position() < f.size() -1) { while (f.position() < f.size() -1) {
size_t bufsize = f.read(buf, FS_BUFSIZE); // better to use size_t instead of uint16_t size_t bufsize = f.read(buf, FS_BUFSIZE); // better to use size_t instead of uint16_t
size_t count = 0; size_t count = 0;
@@ -175,7 +183,9 @@ static void writeSpace(size_t l)
{ {
byte buf[FS_BUFSIZE]; byte buf[FS_BUFSIZE];
memset(buf, ' ', FS_BUFSIZE); memset(buf, ' ', FS_BUFSIZE);
#if ESP_IDF_VERSION_MAJOR >= 4
f.setBufferSize(FS_BUFSIZE);
#endif
while (l > 0) { while (l > 0) {
size_t block = (l>FS_BUFSIZE) ? FS_BUFSIZE : l; size_t block = (l>FS_BUFSIZE) ? FS_BUFSIZE : l;
f.write(buf, block); f.write(buf, block);

View File

@@ -161,6 +161,12 @@ int getSignalQuality(int rssi)
return quality; return quality;
} }
#if ESP_IDF_VERSION_MAJOR >= 4
#define SYSTEM_EVENT_ETH_CONNECTED ARDUINO_EVENT_ETH_CONNECTED
#define SYSTEM_EVENT_ETH_DISCONNECTED ARDUINO_EVENT_ETH_DISCONNECTED
#define SYSTEM_EVENT_ETH_START ARDUINO_EVENT_ETH_START
#define SYSTEM_EVENT_ETH_GOT_IP ARDUINO_EVENT_ETH_GOT_IP
#endif
//handle Ethernet connection event //handle Ethernet connection event
void WiFiEvent(WiFiEvent_t event) void WiFiEvent(WiFiEvent_t event)
@@ -170,12 +176,21 @@ void WiFiEvent(WiFiEvent_t event)
case SYSTEM_EVENT_ETH_START: case SYSTEM_EVENT_ETH_START:
DEBUG_PRINTLN(F("ETH Started")); DEBUG_PRINTLN(F("ETH Started"));
break; break;
case SYSTEM_EVENT_ETH_GOT_IP:
if (Network.isEthernet()) {
if (!apActive) {
DEBUG_PRINTLN(F("WiFi Connected *and* ETH Connected. Disabling WIFi"));
WiFi.disconnect(true);
} else {
DEBUG_PRINTLN(F("WiFi Connected *and* ETH Connected. Leaving AP WiFi active"));
}
} else {
DEBUG_PRINTLN(F("WiFi Connected. No ETH"));
}
break;
case SYSTEM_EVENT_ETH_CONNECTED: case SYSTEM_EVENT_ETH_CONNECTED:
{ {
DEBUG_PRINTLN(F("ETH Connected")); DEBUG_PRINTLN(F("ETH Connected"));
if (!apActive) {
WiFi.disconnect(true);
}
if (staticIP != (uint32_t)0x00000000 && staticGateway != (uint32_t)0x00000000) { if (staticIP != (uint32_t)0x00000000 && staticGateway != (uint32_t)0x00000000) {
ETH.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8)); ETH.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
} else { } else {

View File

@@ -911,7 +911,7 @@ uint8_t IRAM_ATTR_YN realtimeBroadcast(uint8_t type, IPAddress client, uint16_t
const uint_fast16_t ARTNET_CHANNELS_PER_PACKET = isRGBW?512:510; // 512/4=128 RGBW LEDs, 510/3=170 RGB LEDs const uint_fast16_t ARTNET_CHANNELS_PER_PACKET = isRGBW?512:510; // 512/4=128 RGBW LEDs, 510/3=170 RGB LEDs
uint_fast16_t bufferOffset = 0; uint_fast16_t bufferOffset = 0;
uint_fast16_t hardware_output_universe = 0; uint_fast16_t hardware_output_universe = e131Universe; // start at the universe defined in Sync Setup
sequenceNumber++; sequenceNumber++;

View File

@@ -1370,16 +1370,15 @@ void WLED::handleConnection()
} else if (!interfacesInited) { //newly connected } else if (!interfacesInited) { //newly connected
USER_PRINTLN(""); USER_PRINTLN("");
USER_PRINT(F("Connected! IP address: http://")); USER_PRINT(F("Connected! IP address: http://"));
USER_PRINTLN(Network.localIP()); USER_PRINT(Network.localIP());
//if (Network.isEthernet()) { if (Network.isEthernet()) {
// #if ESP32 #if ESP32
// USER_PRINT(ETH.localIP()); USER_PRINTLN(" via Ethernet (disabling WiFi)");
// USER_PRINTLN(" via Ethernet"); WiFi.disconnect(true);
// #endif #endif
//} else { } else {
// USER_PRINT(Network.localIP()); USER_PRINTLN(" via WiFi");
// USER_PRINTLN(" via WiFi"); }
//}
if (improvActive) { if (improvActive) {
if (improvError == 3) sendImprovStateResponse(0x00, true); if (improvError == 3) sendImprovStateResponse(0x00, true);

View File

@@ -487,6 +487,11 @@ void getSettingsJS(AsyncWebServerRequest* request, byte subPage, char* dest) //W
oappendi(bus->getMaxPixels()); oappend(SET_F(");")); oappendi(bus->getMaxPixels()); oappend(SET_F(");"));
} }
oappend(SET_F("d.e131Universe="));
oappendi(e131Universe); // Art-Net start universe
oappend(SET_F(";"));
sappend('v',SET_F("MA"),strip.ablMilliampsMax); sappend('v',SET_F("MA"),strip.ablMilliampsMax);
sappend('v',SET_F("LA"),strip.milliampsPerLed); sappend('v',SET_F("LA"),strip.milliampsPerLed);
if (strip.currentMilliamps) if (strip.currentMilliamps)