Compare commits
11 Commits
copilot/fi
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8590538272 | ||
|
|
f75b13a29a | ||
|
|
1b19c35625 | ||
|
|
2dfea5c1e2 | ||
|
|
a441ee81b6 | ||
|
|
6c0c875fe6 | ||
|
|
9d706010f5 | ||
|
|
97b20438fd | ||
|
|
65913f990d | ||
|
|
56d00357d3 | ||
|
|
1864e550e6 |
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -1,2 +1,3 @@
|
||||
github: [Aircoookie,blazoncek]
|
||||
github: [Aircoookie,blazoncek,DedeHai,lost-hope,willmmiles]
|
||||
custom: ['https://paypal.me/Aircoookie','https://paypal.me/blazoncek']
|
||||
thanks_dev: u/gh/netmindz
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
|
||||
</p>
|
||||
|
||||
# Welcome to my project WLED! ✨
|
||||
# Welcome to WLED! ✨
|
||||
|
||||
A fast and feature-rich implementation of an ESP32 and ESP8266 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!
|
||||
|
||||
Originally created by [Aircoookie](https://github.com/Aircoookie)
|
||||
|
||||
## ⚙️ Features
|
||||
- WS2812FX library with more than 100 special effects
|
||||
- FastLED noise effects and 50 palettes
|
||||
@@ -32,7 +34,7 @@ A fast and feature-rich implementation of an ESP32 and ESP8266 webserver to cont
|
||||
- Filesystem-based config for easier backup of presets and settings
|
||||
|
||||
## 💡 Supported light control interfaces
|
||||
- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033)
|
||||
- WLED app for [Android](https://play.google.com/store/apps/details?id=ca.cgagnier.wlednativeandroid) and [iOS](https://apps.apple.com/gb/app/wled-native/id6446207239)
|
||||
- JSON and HTTP request APIs
|
||||
- MQTT
|
||||
- E1.31, Art-Net, DDP and TPM2.net
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)<ledCount) gId(`segr${lSeg}`).classList.remove("hide");
|
||||
// Add safety checks for segment control elements
|
||||
const segSElement = gId(`seg${lSeg}s`);
|
||||
const segEElement = gId(`seg${lSeg}e`);
|
||||
const segrElement = gId(`segr${lSeg}`);
|
||||
if (!isM && !noNewSegs && segSElement && segEElement && segrElement) {
|
||||
const segLen = cfg.comp.seglen ? parseInt(segSElement.value) : 0;
|
||||
const segEnd = parseInt(segEElement.value);
|
||||
if (segLen + segEnd < ledCount) segrElement.classList.remove("hide");
|
||||
}
|
||||
gId('segutil2').style.display = (segCount > 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user