diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 2f8d5515fd..91316a84d0 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -13,6 +13,10 @@ #include "FXparticleSystem.h" // TODO: better define the required function (mem service) in FX.h? #include "palettes.h" +#ifndef DEFAULT_LED_COLOR_ORDER + #define DEFAULT_LED_COLOR_ORDER COL_ORDER_GRB //default to GRB +#endif + /* Custom per-LED mapping has moved! @@ -1173,12 +1177,22 @@ void WS2812FX::finalizeInit() { // create buses/outputs unsigned mem = 0; - for (const auto &bus : busConfigs) { - mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer - if (mem <= MAX_LED_MEMORY) { - if (BusManager::add(bus) == -1) break; - } else DEBUG_PRINTF_P(PSTR("Out of LED memory! Bus %d (%d) #%u not created."), (int)bus.type, (int)bus.count, digitalCount); + for (auto bus : busConfigs) { + // Calculate what this bus would use with its current configuration + unsigned busMemUsage = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount : 0); + + // If memory exceeds limit, set count to minimum of current count and default length + if (mem + busMemUsage > MAX_LED_MEMORY) { + bus.count = min(bus.count, DEFAULT_LED_COUNT); + DEBUG_PRINTF_P(PSTR("Bus %d memory usage exceeds limit, setting count to %d\n"), (int)bus.type, bus.count); + } + + if (BusManager::add(bus) != -1) { + mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount : 0); + if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) digitalCount++; + } else break; } + busConfigs.clear(); busConfigs.shrink_to_fit(); diff --git a/wled00/data/index.js b/wled00/data/index.js index fe154783d0..61ac4ed00c 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -668,9 +668,20 @@ function parseInfo(i) { if (loc) name = "(L) " + name; d.title = name; simplifiedUI = i.simplifiedui; - ledCount = i.leds.count; + // Add safety checks for LED count data to prevent UI crashes + if (i.leds && typeof i.leds.count !== 'undefined') { + ledCount = i.leds.count; + } else { + console.warn('LED count data missing, using fallback value'); + ledCount = 30; // Fallback value matching firmware default + } //syncTglRecv = i.str; - maxSeg = i.leds.maxseg; + if (i.leds && typeof i.leds.maxseg !== 'undefined') { + maxSeg = i.leds.maxseg; + } else { + console.warn('Max segment data missing, using fallback value'); + maxSeg = 16; // Reasonable fallback for max segments + } pmt = i.fs.pmt; if (pcMode && !i.wifi.ap) gId('edit').classList.remove("hide"); else gId('edit').classList.add("hide"); gId('buttonNodes').style.display = lastinfo.ndc > 0 ? null:"none"; @@ -912,12 +923,24 @@ function populateSegments(s) gId(`segr${i}`).classList.add("hide"); } if (segCount < 2) { - gId(`segd${lSeg}`).classList.add("hide"); // hide delete if only one segment - if (parseInt(gId("seg0bri").value)==255) gId(`segp0`).classList.add("hide"); + // Add safety check for segment elements to prevent UI crashes + const segdElement = gId(`segd${lSeg}`); + if (segdElement) segdElement.classList.add("hide"); // hide delete if only one segment + const seg0briElement = gId("seg0bri"); + const segp0Element = gId(`segp0`); + if (seg0briElement && segp0Element && parseInt(seg0briElement.value)==255) segp0Element.classList.add("hide"); // hide segment controls if there is only one segment in simplified UI if (simplifiedUI) gId("segcont").classList.add("hide"); } - if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value) 1) ? "block":"none"; // rsbtn parent if (Array.isArray(li.maps) && li.maps.length>1) { @@ -2253,7 +2276,9 @@ function rptSeg(s) var rev = gId(`seg${s}rev`).checked; var mi = gId(`seg${s}mi`).checked; var sel = gId(`seg${s}sel`).checked; - var pwr = gId(`seg${s}pwr`).classList.contains('act'); + // Add safety check for segment power element to prevent UI crashes + const segPwrElement = gId(`seg${s}pwr`); + var pwr = segPwrElement ? segPwrElement.classList.contains('act') : false; var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop, "rev": rev, "mi": mi, "on": pwr, "bri": parseInt(gId(`seg${s}bri`).value), "sel": sel}}; if (gId(`seg${s}grp`)) { var grp = parseInt(gId(`seg${s}grp`).value); @@ -2380,7 +2405,13 @@ function setGrp(s, g) function setSegPwr(s) { - var pwr = gId(`seg${s}pwr`).classList.contains('act'); + // Add safety check for segment power element to prevent UI crashes + const segPwrElement = gId(`seg${s}pwr`); + if (!segPwrElement) { + console.warn('Segment power element not found, skipping power toggle'); + return; + } + var pwr = segPwrElement.classList.contains('act'); var obj = {"seg": {"id": s, "on": !pwr}}; requestJson(obj); }