Skip to content

Commit db310c6

Browse files
committed
Safety Checks for UI, fix for cfg exceeding LED limit
- added some safety checks for UI to not throw errors if JSCON parameters are missing - add all buses in config even if they exceed RAM limit, truncates long buses
1 parent 9d70601 commit db310c6

File tree

2 files changed

+49
-12
lines changed

2 files changed

+49
-12
lines changed

wled00/FX_fcn.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,11 +1173,17 @@ void WS2812FX::finalizeInit() {
11731173

11741174
// create buses/outputs
11751175
unsigned mem = 0;
1176-
for (const auto &bus : busConfigs) {
1177-
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount++ : 0); // includes global buffer
1178-
if (mem <= MAX_LED_MEMORY) {
1179-
if (BusManager::add(bus) == -1) break;
1180-
} else DEBUG_PRINTF_P(PSTR("Out of LED memory! Bus %d (%d) #%u not created."), (int)bus.type, (int)bus.count, digitalCount);
1176+
for (auto bus : busConfigs) {
1177+
unsigned busMemUsage = bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount : 0);
1178+
// if memory exceeds limit, add it anyway but reduce LED count to default if it is larger (a bit dangerous, but prevents no buses being created at all)
1179+
if (mem + busMemUsage > MAX_LED_MEMORY) {
1180+
bus.count = min((int)bus.count, DEFAULT_LED_COUNT);
1181+
DEBUG_PRINTF_P(PSTR("Bus %d memory usage exceeds limit, setting count to %d\n"), (int)bus.type, bus.count);
1182+
}
1183+
if (BusManager::add(bus) != -1) {
1184+
mem += bus.memUsage(Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type) ? digitalCount : 0);
1185+
if (Bus::isDigital(bus.type) && !Bus::is2Pin(bus.type)) digitalCount++;
1186+
} else break;
11811187
}
11821188
busConfigs.clear();
11831189
busConfigs.shrink_to_fit();

wled00/data/index.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -668,9 +668,20 @@ function parseInfo(i) {
668668
if (loc) name = "(L) " + name;
669669
d.title = name;
670670
simplifiedUI = i.simplifiedui;
671-
ledCount = i.leds.count;
671+
// safety checks for LED count data to prevent UI crashes
672+
if (i.leds && typeof i.leds.count !== 'undefined') {
673+
ledCount = i.leds.count;
674+
} else {
675+
console.warn('No LED count');
676+
ledCount = 30; // fallback value
677+
}
672678
//syncTglRecv = i.str;
673-
maxSeg = i.leds.maxseg;
679+
if (i.leds && typeof i.leds.maxseg !== 'undefined') {
680+
maxSeg = i.leds.maxseg;
681+
} else {
682+
console.warn('No max segment data');
683+
maxSeg = 16; // Reasonable fallback for max segments
684+
}
674685
pmt = i.fs.pmt;
675686
if (pcMode && !i.wifi.ap) gId('edit').classList.remove("hide"); else gId('edit').classList.add("hide");
676687
gId('buttonNodes').style.display = lastinfo.ndc > 0 ? null:"none";
@@ -912,12 +923,24 @@ function populateSegments(s)
912923
gId(`segr${i}`).classList.add("hide");
913924
}
914925
if (segCount < 2) {
915-
gId(`segd${lSeg}`).classList.add("hide"); // hide delete if only one segment
916-
if (parseInt(gId("seg0bri").value)==255) gId(`segp0`).classList.add("hide");
926+
// safety check for segment elements to prevent UI crashes
927+
const segdElement = gId(`segd${lSeg}`);
928+
if (segdElement) segdElement.classList.add("hide"); // hide delete if only one segment
929+
const seg0briElement = gId("seg0bri");
930+
const segp0Element = gId(`segp0`);
931+
if (seg0briElement && segp0Element && parseInt(seg0briElement.value)==255) segp0Element.classList.add("hide");
917932
// hide segment controls if there is only one segment in simplified UI
918933
if (simplifiedUI) gId("segcont").classList.add("hide");
919934
}
920-
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).classList.remove("hide");
935+
// safety checks for segment control elements
936+
const segSElement = gId(`seg${lSeg}s`);
937+
const segEElement = gId(`seg${lSeg}e`);
938+
const segrElement = gId(`segr${lSeg}`);
939+
if (!isM && !noNewSegs && segSElement && segEElement && segrElement) {
940+
const segLen = cfg.comp.seglen ? parseInt(segSElement.value) : 0;
941+
const segEnd = parseInt(segEElement.value);
942+
if (segLen + segEnd < ledCount) segrElement.classList.remove("hide");
943+
}
921944
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
922945

923946
if (Array.isArray(li.maps) && li.maps.length>1) {
@@ -2253,7 +2276,9 @@ function rptSeg(s)
22532276
var rev = gId(`seg${s}rev`).checked;
22542277
var mi = gId(`seg${s}mi`).checked;
22552278
var sel = gId(`seg${s}sel`).checked;
2256-
var pwr = gId(`seg${s}pwr`).classList.contains('act');
2279+
// safety check for segment power element to prevent UI crashes
2280+
const segPwrElement = gId(`seg${s}pwr`);
2281+
var pwr = segPwrElement ? segPwrElement.classList.contains('act') : false;
22572282
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}};
22582283
if (gId(`seg${s}grp`)) {
22592284
var grp = parseInt(gId(`seg${s}grp`).value);
@@ -2380,7 +2405,13 @@ function setGrp(s, g)
23802405

23812406
function setSegPwr(s)
23822407
{
2383-
var pwr = gId(`seg${s}pwr`).classList.contains('act');
2408+
// safety check for segment power element to prevent UI crashes
2409+
const segPwrElement = gId(`seg${s}pwr`);
2410+
if (!segPwrElement) {
2411+
console.warn('No power elemen');
2412+
return;
2413+
}
2414+
var pwr = segPwrElement.classList.contains('act');
23842415
var obj = {"seg": {"id": s, "on": !pwr}};
23852416
requestJson(obj);
23862417
}

0 commit comments

Comments
 (0)