Merge branch 'dev' into virtual-bus
This commit is contained in:
commit
22be8e2e9d
13
CHANGELOG.md
13
CHANGELOG.md
@ -2,6 +2,19 @@
|
||||
|
||||
### Builds after release 0.12.0
|
||||
|
||||
#### Build 2109220
|
||||
|
||||
- Version bump to 0.13.0-b3 "Toki"
|
||||
- Added segment names (PR #2184)
|
||||
- Improved Police and other effects (PR #2184)
|
||||
- Reverted PR #1902 (Live color correction - will be implemented as usermod) (PR #2175)
|
||||
- Added transitions for segment on/off
|
||||
- Improved number of sparks/stars in Fireworks effect with low number of segments
|
||||
- Fixed segment name edit pencil disappearing with request
|
||||
- Fixed color transition active even if the segment is off
|
||||
- Disallowed file upload with OTA lock active
|
||||
- Fixed analog invert option missing (PR #2219)
|
||||
|
||||
#### Build 2109100
|
||||
|
||||
- Added an auto create segments per bus setting
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.13.0-bl2",
|
||||
"version": "0.13.0-bl3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -2629,7 +2629,7 @@ typedef struct Spark {
|
||||
*/
|
||||
uint16_t WS2812FX::mode_popcorn(void) {
|
||||
//allocate segment data
|
||||
uint16_t maxNumPopcorn = 22; // max 22 on 16 segment ESP8266
|
||||
uint16_t maxNumPopcorn = 21; // max 21 on 16 segment ESP8266
|
||||
uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
|
||||
@ -2688,7 +2688,7 @@ uint16_t WS2812FX::candle(bool multi)
|
||||
if (multi)
|
||||
{
|
||||
//allocate segment data
|
||||
uint16_t dataSize = (SEGLEN -1) *3; // max length of segment on 16 segment ESP8266 is 75 pixels
|
||||
uint16_t dataSize = (SEGLEN -1) *3; //max. 1365 pixels (ESP8266)
|
||||
if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed
|
||||
}
|
||||
|
||||
@ -2776,13 +2776,11 @@ uint16_t WS2812FX::mode_candle_multi()
|
||||
/ Speed sets frequency of new starbursts, intensity is the intensity of the burst
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
#define STARBURST_MAX_FRAG 4
|
||||
#define STARBURST_MAX_STARS 6
|
||||
#define STARBURST_MAX_FRAG 8 //52 bytes / star
|
||||
#else
|
||||
#define STARBURST_MAX_FRAG 10
|
||||
#define STARBURST_MAX_STARS 11
|
||||
#define STARBURST_MAX_FRAG 10 //60 bytes / star
|
||||
#endif
|
||||
//each needs 18+STARBURST_MAX_FRAG*4 bytes
|
||||
//each needs 20+STARBURST_MAX_FRAG*4 bytes
|
||||
typedef struct particle {
|
||||
CRGB color;
|
||||
uint32_t birth =0;
|
||||
@ -2793,7 +2791,14 @@ typedef struct particle {
|
||||
} star;
|
||||
|
||||
uint16_t WS2812FX::mode_starburst(void) {
|
||||
uint8_t numStars = min(1 + (SEGLEN >> 3), STARBURST_MAX_STARS); // 11 * 58 * 32 = 19k (ESP32), 6 * 34 * 16 = 3.2k (ESP8266)
|
||||
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
|
||||
uint8_t segs = getActiveSegmentsNum();
|
||||
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
|
||||
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
|
||||
uint16_t maxStars = maxData / sizeof(star); //ESP8266: max. 4/9/19 stars/seg, ESP32: max. 10/21/42 stars/seg
|
||||
|
||||
uint8_t numStars = 1 + (SEGLEN >> 3);
|
||||
if (numStars > maxStars) numStars = maxStars;
|
||||
uint16_t dataSize = sizeof(star) * numStars;
|
||||
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
@ -2895,24 +2900,29 @@ uint16_t WS2812FX::mode_starburst(void) {
|
||||
return FRAMETIME;
|
||||
}
|
||||
#undef STARBURST_MAX_FRAG
|
||||
#undef STARBURST_MAX_STARS
|
||||
|
||||
/*
|
||||
* Exploding fireworks effect
|
||||
* adapted from: http://www.anirama.com/1000leds/1d-fireworks/
|
||||
*/
|
||||
#ifdef ESP8266
|
||||
#define MAX_SPARKS 20 // number of fragments (11 bytes per fragment)
|
||||
#else
|
||||
#define MAX_SPARKS 58 // number of fragments
|
||||
#endif
|
||||
uint16_t WS2812FX::mode_exploding_fireworks(void)
|
||||
{
|
||||
//allocate segment data
|
||||
uint16_t numSparks = min(2 + (SEGLEN >> 1), MAX_SPARKS); // max 58 for 32 segment ESP32, 20 for 16 segment ESP8266
|
||||
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
|
||||
uint8_t segs = getActiveSegmentsNum();
|
||||
if (segs <= (MAX_NUM_SEGMENTS /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
|
||||
if (segs <= (MAX_NUM_SEGMENTS /4)) maxData *= 2; //ESP8266: 1024 if <= 4 segs ESP32: 2560 if <= 8 segs
|
||||
int maxSparks = maxData / sizeof(spark); //ESP8266: max. 21/42/85 sparks/seg, ESP32: max. 53/106/213 sparks/seg
|
||||
|
||||
uint16_t numSparks = min(2 + (SEGLEN >> 1), maxSparks);
|
||||
uint16_t dataSize = sizeof(spark) * numSparks;
|
||||
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
|
||||
|
||||
if (dataSize != SEGENV.aux1) { //reset to flare if sparks were reallocated
|
||||
SEGENV.aux0 = 0;
|
||||
SEGENV.aux1 = dataSize;
|
||||
}
|
||||
|
||||
fill(BLACK);
|
||||
|
||||
bool actuallyReverse = SEGMENT.getOption(SEG_OPTION_REVERSED);
|
||||
|
34
wled00/FX.h
34
wled00/FX.h
@ -57,7 +57,7 @@
|
||||
/* How many color transitions can run at once */
|
||||
#define MAX_NUM_TRANSITIONS 8
|
||||
/* How much data bytes all segments combined may allocate */
|
||||
#define MAX_SEGMENT_DATA 3584
|
||||
#define MAX_SEGMENT_DATA 4096
|
||||
#else
|
||||
#ifndef MAX_NUM_SEGMENTS
|
||||
#define MAX_NUM_SEGMENTS 32
|
||||
@ -66,6 +66,10 @@
|
||||
#define MAX_SEGMENT_DATA 20480
|
||||
#endif
|
||||
|
||||
/* How much data bytes each segment should max allocate to leave enough space for other segments,
|
||||
assuming each segment uses the same amount of data. 256 for ESP8266, 640 for ESP32. */
|
||||
#define FAIR_DATA_PER_SEG (MAX_SEGMENT_DATA / MAX_NUM_SEGMENTS)
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
#define MIN_SHOW_DELAY 15
|
||||
|
||||
@ -243,7 +247,7 @@ class WS2812FX {
|
||||
|
||||
// segment parameters
|
||||
public:
|
||||
typedef struct Segment { // 25 (28 in memory?) bytes
|
||||
typedef struct Segment { // 29 (32 in memory?) bytes
|
||||
uint16_t start;
|
||||
uint16_t stop; //segment invalid if stop == 0
|
||||
uint16_t offset;
|
||||
@ -274,22 +278,24 @@ class WS2812FX {
|
||||
}*/
|
||||
void setOption(uint8_t n, bool val, uint8_t segn = 255)
|
||||
{
|
||||
//bool prevOn = false;
|
||||
//if (n == SEG_OPTION_ON) prevOn = getOption(SEG_OPTION_ON);
|
||||
bool prevOn = false;
|
||||
if (n == SEG_OPTION_ON) {
|
||||
prevOn = getOption(SEG_OPTION_ON);
|
||||
if (!val && prevOn) { //fade off
|
||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (val) {
|
||||
options |= 0x01 << n;
|
||||
} else
|
||||
{
|
||||
options &= ~(0x01 << n);
|
||||
}
|
||||
//transitions on segment on/off don't work correctly at this point
|
||||
/*if (n == SEG_OPTION_ON && segn < MAX_NUM_SEGMENTS && getOption(SEG_OPTION_ON) != prevOn) {
|
||||
if (getOption(SEG_OPTION_ON)) {
|
||||
|
||||
if (n == SEG_OPTION_ON && val && !prevOn) { //fade on
|
||||
ColorTransition::startTransition(0, colors[0], instance->_transitionDur, segn, 0);
|
||||
} else {
|
||||
ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
bool getOption(uint8_t n)
|
||||
{
|
||||
@ -409,6 +415,7 @@ class WS2812FX {
|
||||
static void startTransition(uint8_t oldBri, uint32_t oldCol, uint16_t dur, uint8_t segn, uint8_t slot) {
|
||||
if (segn >= MAX_NUM_SEGMENTS || slot >= NUM_COLORS || dur == 0) return;
|
||||
if (instance->_brightness == 0) return; //do not need transitions if master bri is off
|
||||
if (!instance->_segments[segn].getOption(SEG_OPTION_ON)) return; //not if segment is off either
|
||||
uint8_t tIndex = 0xFF; //none found
|
||||
uint16_t tProgression = 0;
|
||||
uint8_t s = segn + (slot << 6); //merge slot and segment into one byte
|
||||
@ -437,7 +444,8 @@ class WS2812FX {
|
||||
ColorTransition& t = instance->transitions[tIndex];
|
||||
if (t.segment == s) //this is an active transition on the same segment+color
|
||||
{
|
||||
t.briOld = t.currentBri();
|
||||
bool wasTurningOff = (oldBri == 0);
|
||||
t.briOld = t.currentBri(wasTurningOff);
|
||||
t.colorOld = t.currentColor(oldCol);
|
||||
} else {
|
||||
t.briOld = oldBri;
|
||||
@ -469,10 +477,11 @@ class WS2812FX {
|
||||
uint32_t currentColor(uint32_t colorNew) {
|
||||
return instance->color_blend(colorOld, colorNew, progress(true), true);
|
||||
}
|
||||
uint8_t currentBri() {
|
||||
uint8_t currentBri(bool turningOff = false) {
|
||||
uint8_t segn = segment & 0x3F;
|
||||
if (segn >= MAX_NUM_SEGMENTS) return 0;
|
||||
uint8_t briNew = instance->_segments[segn].opacity;
|
||||
if (!instance->_segments[segn].getOption(SEG_OPTION_ON) || turningOff) briNew = 0;
|
||||
uint32_t prog = progress() + 1;
|
||||
return ((briNew * prog) + (briOld * (0x10000 - prog))) >> 16;
|
||||
}
|
||||
@ -656,6 +665,7 @@ class WS2812FX {
|
||||
getModeCount(void),
|
||||
getPaletteCount(void),
|
||||
getMaxSegments(void),
|
||||
getActiveSegmentsNum(void),
|
||||
//getFirstSelectedSegment(void),
|
||||
getMainSegmentId(void),
|
||||
gamma8(uint8_t),
|
||||
|
@ -510,6 +510,15 @@ uint8_t WS2812FX::getMainSegmentId(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
||||
uint8_t c = 0;
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isActive()) c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getColor(void) {
|
||||
return _segments[getMainSegmentId()].colors[0];
|
||||
}
|
||||
@ -548,15 +557,6 @@ uint32_t WS2812FX::getLastShow(void) {
|
||||
return _lastShow;
|
||||
}
|
||||
|
||||
// there is no longer any need for these two
|
||||
//uint8_t WS2812FX::getColorOrder(void) {
|
||||
// return COL_ORDER_GRB;
|
||||
//}
|
||||
//
|
||||
//void WS2812FX::setColorOrder(uint8_t co) {
|
||||
// //bus->SetColorOrder(co);
|
||||
//}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
|
||||
if (n >= MAX_NUM_SEGMENTS) return;
|
||||
Segment& seg = _segments[n];
|
||||
@ -1035,9 +1035,10 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
|
||||
|
||||
//load custom mapping table from JSON file
|
||||
void WS2812FX::deserializeMap(uint8_t n) {
|
||||
String fileName = String(F("/ledmap"));
|
||||
if (n) fileName += String(n);
|
||||
fileName += String(F(".json"));
|
||||
char fileName[32];
|
||||
strcpy_P(fileName, PSTR("/ledmap"));
|
||||
if (n) sprintf(fileName +7, "%d", n);
|
||||
strcat(fileName, ".json");
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
|
||||
if (!isFile) {
|
||||
@ -1054,7 +1055,7 @@ void WS2812FX::deserializeMap(uint8_t n) {
|
||||
DEBUG_PRINT(F("Reading LED map from "));
|
||||
DEBUG_PRINTLN(fileName);
|
||||
|
||||
if (!readObjectFromFile(fileName.c_str(), nullptr, &doc)) return; //if file does not exist just exit
|
||||
if (!readObjectFromFile(fileName, nullptr, &doc)) return; //if file does not exist just exit
|
||||
|
||||
// erase old custom ledmap
|
||||
if (customMappingTable != nullptr) {
|
||||
|
@ -110,7 +110,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (length==0 || length+lC > MAX_LEDS) continue; // zero length or we reached max. number of LEDs, just stop
|
||||
uint8_t colorOrder = (int)elm[F("order")];
|
||||
uint8_t skipFirst = elm[F("skip")];
|
||||
uint16_t start = elm[F("start")] | 0;
|
||||
uint16_t start = elm["start"] | 0;
|
||||
if (start > lC+length) continue; // something is very wrong :)
|
||||
uint8_t ledType = elm["type"] | TYPE_WS2812_RGB;
|
||||
bool reversed = elm["rev"];
|
||||
@ -411,7 +411,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonObject dmx = doc["dmx"];
|
||||
CJSON(DMXChannels, dmx[F("chan")]);
|
||||
CJSON(DMXGap,dmx[F("gap")]);
|
||||
CJSON(DMXStart, dmx[F("start")]);
|
||||
CJSON(DMXStart, dmx["start"]);
|
||||
CJSON(DMXStartLED,dmx[F("start-led")]);
|
||||
|
||||
JsonArray dmx_fixmap = dmx[F("fixmap")];
|
||||
@ -549,7 +549,7 @@ void serializeConfig() {
|
||||
Bus *bus = busses.getBus(s);
|
||||
if (!bus || bus->getLength()==0) break;
|
||||
JsonObject ins = hw_led_ins.createNestedObject();
|
||||
ins[F("start")] = bus->getStart();
|
||||
ins["start"] = bus->getStart();
|
||||
ins[F("len")] = bus->getLength();
|
||||
JsonArray ins_pin = ins.createNestedArray("pin");
|
||||
uint8_t pins[5];
|
||||
@ -753,7 +753,7 @@ void serializeConfig() {
|
||||
JsonObject dmx = doc.createNestedObject("dmx");
|
||||
dmx[F("chan")] = DMXChannels;
|
||||
dmx[F("gap")] = DMXGap;
|
||||
dmx[F("start")] = DMXStart;
|
||||
dmx["start"] = DMXStart;
|
||||
dmx[F("start-led")] = DMXStartLED;
|
||||
|
||||
JsonArray dmx_fixmap = dmx.createNestedArray(F("fixmap"));
|
||||
|
File diff suppressed because one or more lines are too long
@ -1568,6 +1568,12 @@ function tglSegn(s)
|
||||
(window.getComputedStyle(d.gId(`seg${s}t`)).display === "none") ? "inline":"none";
|
||||
}
|
||||
|
||||
function tglSegn(s)
|
||||
{
|
||||
d.getElementById(`seg${s}t`).style.display =
|
||||
(window.getComputedStyle(d.getElementById(`seg${s}t`)).display === "none") ? "inline":"none";
|
||||
}
|
||||
|
||||
function selSegEx(s)
|
||||
{
|
||||
var obj = {"seg":[]};
|
||||
|
@ -37,7 +37,7 @@
|
||||
}
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText)});
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
|
@ -202,7 +202,7 @@
|
||||
}
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText)});
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
|
@ -193,7 +193,7 @@ const char PAGE_settings_dmx[] PROGMEM = R"=====()=====";
|
||||
// Autogenerated from wled00/data/settings_ui.htm, do not edit!!
|
||||
const char PAGE_settings_ui[] PROGMEM = R"=====(<!DOCTYPE html><html><head lang="en"><meta charset="utf-8"><meta
|
||||
name="viewport" content="width=500"><title>UI Settings</title><script>
|
||||
var initial_ds,initial_st,initial_su,timeout,d=document,sett=null,l={comp:{labels:"Show button labels",colors:{LABEL:"Color selection methods",picker:"Color Wheel",rgb:"RGB sliders",quick:"Quick color selectors",hex:"HEX color input"},pcmbot:"Show bottom tab bar in PC mode",pid:"Show preset IDs",seglen:"Set segment length instead of stop LED",css:"Enable custom CSS",hdays:"Enable custom Holidays list"},theme:{alpha:{bg:"Background opacity",tab:"Button opacity"},bg:{url:"BG image URL",random:"Random BG image"},color:{bg:"BG HEX color"}}};function gId(e){return d.getElementById(e)}function isObject(e){return e&&"object"==typeof e&&!Array.isArray(e)}function set(e,t,i){for(var n=t,o=e.split("_"),s=o.length,a=0;a<s-1;a++){var l=o[a];n[l]||(n[l]={}),n=n[l]}n[o[s-1]]=i}function showToast(e,t=!1){var i=gId("toast");i.innerHTML=e,i.className=t?"error":"show",clearTimeout(timeout),i.style.animation="none",timeout=setTimeout((function(){i.className=i.className.replace("show","")}),2900)}function addRec(e,t="",n=null){var o="";for(i in e){var s=t+(t?"_":"")+i;if(isObject(e[i]))n&&n[i]&&n[i].LABEL&&(o+=`<h3>${n[i].LABEL}</h3>`),o+=addRec(e[i],s,n?n[i]:null);else{var a=s;if(n&&n[i]?a=n[i]:e[i+"LABEL"]&&(a=e[i+"LABEL"]),i.indexOf("LABEL")>0)continue;var l=typeof e[i];gId(s)?("boolean"===l?gId(s).checked=e[i]:gId(s).value=e[i],gId(s).previousElementSibling.matches(".l")&&(gId(s).previousElementSibling.innerHTML=a)):"boolean"===l?o+=`${a}: <input class="agi cb" type="checkbox" id=${s} ${e[i]?"checked":""}><br>`:"number"===l?o+=`${a}: <input class="agi" type="number" id=${s} value=${e[i]}><br>`:"string"===l&&(o+=`${a}:<br><input class="agi" id=${s} value=${e[i]}><br>`)}}return o}function genForm(e){var t;t=addRec(e,"",l),gId("gen").innerHTML=t}function GetLS(){(sett=localStorage.getItem("wledUiCfg"))||(gId("lserr").style.display="inline");try{sett=JSON.parse(sett)}catch(e){sett={},gId("lserr").style.display="inline",gId("lserr").innerHTML="⚠ Settings JSON parsing failed. ("+e+")"}genForm(sett),gId("dm").checked="light"===gId("theme_base").value}function SetLS(){for(var e=d.querySelectorAll(".agi"),t=0;t<e.length;t++){var i=e[t],n=i.classList.contains("cb")?i.checked:i.value;set(i.id,sett,n),console.log(`${i.id} set to ${n}`)}try{localStorage.setItem("wledUiCfg",JSON.stringify(sett)),gId("lssuc").style.display="inline"}catch(i){gId("lssuc").style.display="none",gId("lserr").style.display="inline",gId("lserr").innerHTML="⚠ Settings JSON saving failed. ("+i+")"}}function cLS(){localStorage.removeItem("wledP"),localStorage.removeItem("wledPmt"),localStorage.removeItem("wledPalx"),showToast("Cleared.")}function Save(){SetLS(),d.Sf.DS.value==initial_ds&&d.Sf.ST.checked==initial_st&&d.Sf.SU.checked==initial_su||d.Sf.submit()}function S(){GetV(),initial_ds=d.Sf.DS.value,initial_st=d.Sf.ST.checked,initial_su=d.Sf.SU.checked,GetLS()}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings")}function B(){window.open("/settings","_self")}function UI(){gId("idonthateyou").style.display=gId("dm").checked?"inline":"none";var e=gId("theme_base");e&&(e.value=gId("dm").checked?"light":"dark")}function setRandomBg(){gId("theme_bg_random").checked?gId("theme_bg_url").value="https://picsum.photos/1920/1080":gId("theme_bg_url").value=""}function checkRandomBg(){"https://picsum.photos/1920/1080"===gId("theme_bg_url").value?gId("theme_bg_random").checked=!0:gId("theme_bg_random").checked=!1}function uploadFile(e,t){var i=new XMLHttpRequest;i.addEventListener("load",(function(){showToast(this.responseText)})),i.addEventListener("error",(function(e){showToast(e.stack,!0)})),i.open("POST","/upload");var n=new FormData;return n.append("data",e.files[0],t),i.send(n),e.value="",!1}function GetV() {var d=document;
|
||||
var initial_ds,initial_st,initial_su,timeout,d=document,sett=null,l={comp:{labels:"Show button labels",colors:{LABEL:"Color selection methods",picker:"Color Wheel",rgb:"RGB sliders",quick:"Quick color selectors",hex:"HEX color input"},pcmbot:"Show bottom tab bar in PC mode",pid:"Show preset IDs",seglen:"Set segment length instead of stop LED",css:"Enable custom CSS",hdays:"Enable custom Holidays list"},theme:{alpha:{bg:"Background opacity",tab:"Button opacity"},bg:{url:"BG image URL",random:"Random BG image"},color:{bg:"BG HEX color"}}};function gId(e){return d.getElementById(e)}function isObject(e){return e&&"object"==typeof e&&!Array.isArray(e)}function set(e,t,i){for(var n=t,o=e.split("_"),s=o.length,a=0;a<s-1;a++){var l=o[a];n[l]||(n[l]={}),n=n[l]}n[o[s-1]]=i}function showToast(e,t=!1){var i=gId("toast");i.innerHTML=e,i.className=t?"error":"show",clearTimeout(timeout),i.style.animation="none",timeout=setTimeout((function(){i.className=i.className.replace("show","")}),2900)}function addRec(e,t="",n=null){var o="";for(i in e){var s=t+(t?"_":"")+i;if(isObject(e[i]))n&&n[i]&&n[i].LABEL&&(o+=`<h3>${n[i].LABEL}</h3>`),o+=addRec(e[i],s,n?n[i]:null);else{var a=s;if(n&&n[i]?a=n[i]:e[i+"LABEL"]&&(a=e[i+"LABEL"]),i.indexOf("LABEL")>0)continue;var l=typeof e[i];gId(s)?("boolean"===l?gId(s).checked=e[i]:gId(s).value=e[i],gId(s).previousElementSibling.matches(".l")&&(gId(s).previousElementSibling.innerHTML=a)):"boolean"===l?o+=`${a}: <input class="agi cb" type="checkbox" id=${s} ${e[i]?"checked":""}><br>`:"number"===l?o+=`${a}: <input class="agi" type="number" id=${s} value=${e[i]}><br>`:"string"===l&&(o+=`${a}:<br><input class="agi" id=${s} value=${e[i]}><br>`)}}return o}function genForm(e){var t;t=addRec(e,"",l),gId("gen").innerHTML=t}function GetLS(){(sett=localStorage.getItem("wledUiCfg"))||(gId("lserr").style.display="inline");try{sett=JSON.parse(sett)}catch(e){sett={},gId("lserr").style.display="inline",gId("lserr").innerHTML="⚠ Settings JSON parsing failed. ("+e+")"}genForm(sett),gId("dm").checked="light"===gId("theme_base").value}function SetLS(){for(var e=d.querySelectorAll(".agi"),t=0;t<e.length;t++){var i=e[t],n=i.classList.contains("cb")?i.checked:i.value;set(i.id,sett,n),console.log(`${i.id} set to ${n}`)}try{localStorage.setItem("wledUiCfg",JSON.stringify(sett)),gId("lssuc").style.display="inline"}catch(i){gId("lssuc").style.display="none",gId("lserr").style.display="inline",gId("lserr").innerHTML="⚠ Settings JSON saving failed. ("+i+")"}}function cLS(){localStorage.removeItem("wledP"),localStorage.removeItem("wledPmt"),localStorage.removeItem("wledPalx"),showToast("Cleared.")}function Save(){SetLS(),d.Sf.DS.value==initial_ds&&d.Sf.ST.checked==initial_st&&d.Sf.SU.checked==initial_su||d.Sf.submit()}function S(){GetV(),initial_ds=d.Sf.DS.value,initial_st=d.Sf.ST.checked,initial_su=d.Sf.SU.checked,GetLS()}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings")}function B(){window.open("/settings","_self")}function UI(){gId("idonthateyou").style.display=gId("dm").checked?"inline":"none";var e=gId("theme_base");e&&(e.value=gId("dm").checked?"light":"dark")}function setRandomBg(){gId("theme_bg_random").checked?gId("theme_bg_url").value="https://picsum.photos/1920/1080":gId("theme_bg_url").value=""}function checkRandomBg(){"https://picsum.photos/1920/1080"===gId("theme_bg_url").value?gId("theme_bg_random").checked=!0:gId("theme_bg_random").checked=!1}function uploadFile(e,t){var i=new XMLHttpRequest;i.addEventListener("load",(function(){showToast(this.responseText,this.status>=400)})),i.addEventListener("error",(function(e){showToast(e.stack,!0)})),i.open("POST","/upload");var n=new FormData;return n.append("data",e.files[0],t),i.send(n),e.value="",!1}function GetV() {var d=document;
|
||||
%CSS%%SCSS%</head><body onload="S()"><form
|
||||
id="form_s" name="Sf" method="post"><div class="toprow"><div class="helpB">
|
||||
<button type="button" onclick="H()">?</button></div><button type="button"
|
||||
@ -396,7 +396,7 @@ type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
// Autogenerated from wled00/data/settings_sec.htm, do not edit!!
|
||||
const char PAGE_settings_sec[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=500">
|
||||
<meta charset="utf-8"><title>Misc Settings</title><script>
|
||||
var timeout,d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings")}function B(){window.open("/settings","_self")}function U(){window.open("/update","_self")}function gId(t){return d.getElementById(t)}function isObject(t){return t&&"object"==typeof t&&!Array.isArray(t)}function showToast(t,e=!1){var n=gId("toast");n.innerHTML=t,n.className=e?"error":"show",clearTimeout(timeout),n.style.animation="none",timeout=setTimeout((function(){n.className=n.className.replace("show","")}),2900)}function uploadFile(t,e){var n=new XMLHttpRequest;n.addEventListener("load",(function(){showToast(this.responseText)})),n.addEventListener("error",(function(t){showToast(t.stack,!0)})),n.open("POST","/upload");var o=new FormData;return o.append("data",t.files[0],e),n.send(o),t.value="",!1}function GetV() {var d=document;
|
||||
var timeout,d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings")}function B(){window.open("/settings","_self")}function U(){window.open("/update","_self")}function gId(t){return d.getElementById(t)}function isObject(t){return t&&"object"==typeof t&&!Array.isArray(t)}function showToast(t,e=!1){var n=gId("toast");n.innerHTML=t,n.className=e?"error":"show",clearTimeout(timeout),n.style.animation="none",timeout=setTimeout((function(){n.className=n.className.replace("show","")}),2900)}function uploadFile(t,e){var n=new XMLHttpRequest;n.addEventListener("load",(function(){showToast(this.responseText,this.status>=400)})),n.addEventListener("error",(function(t){showToast(t.stack,!0)})),n.open("POST","/upload");var o=new FormData;return o.append("data",t.files[0],e),n.send(o),t.value="",!1}function GetV() {var d=document;
|
||||
%CSS%%SCSS%</head><body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post"><div class="toprow"><div
|
||||
class="helpB"><button type="button" onclick="H()">?</button></div><button
|
||||
|
1574
wled00/html_ui.h
1574
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
//WS2812FX::Segment prev;
|
||||
//prev = seg; //make a backup so we can tell if something changed
|
||||
|
||||
uint16_t start = elem[F("start")] | seg.start;
|
||||
uint16_t start = elem["start"] | seg.start;
|
||||
int stop = elem["stop"] | -1;
|
||||
if (stop < 0) {
|
||||
uint16_t len = elem[F("len")];
|
||||
@ -70,7 +70,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
seg.setOption(SEG_OPTION_ON, 1, id);
|
||||
}
|
||||
|
||||
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON), id);
|
||||
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
|
||||
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
|
||||
seg.setOption(SEG_OPTION_ON, on, id);
|
||||
|
||||
JsonArray colarr = elem["col"];
|
||||
if (!colarr.isNull())
|
||||
@ -358,7 +360,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
||||
{
|
||||
root["id"] = id;
|
||||
if (segmentBounds) {
|
||||
root[F("start")] = seg.start;
|
||||
root["start"] = seg.start;
|
||||
root["stop"] = seg.stop;
|
||||
}
|
||||
if (!forPreset) root[F("len")] = seg.stop - seg.start;
|
||||
|
@ -2,14 +2,18 @@
|
||||
|
||||
IPAddress NetworkClass::localIP()
|
||||
{
|
||||
IPAddress localIP;
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET)
|
||||
if (ETH.localIP()[0] != 0) {
|
||||
return ETH.localIP();
|
||||
localIP = ETH.localIP();
|
||||
if (localIP[0] != 0) {
|
||||
return localIP;
|
||||
}
|
||||
#endif
|
||||
if (WiFi.localIP()[0] != 0) {
|
||||
return WiFi.localIP();
|
||||
localIP = WiFi.localIP();
|
||||
if (localIP[0] != 0) {
|
||||
return localIP;
|
||||
}
|
||||
|
||||
return INADDR_NONE;
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,8 @@ void sendTPM2Ack() {
|
||||
|
||||
void handleNotifications()
|
||||
{
|
||||
IPAddress localIP;
|
||||
|
||||
//send second notification if enabled
|
||||
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
|
||||
notify(notificationSentCallMode,true);
|
||||
@ -179,9 +181,10 @@ void handleNotifications()
|
||||
|
||||
if (!(receiveNotifications || receiveDirect)) return;
|
||||
|
||||
localIP = Network.localIP();
|
||||
//notifier and UDP realtime
|
||||
if (!packetSize || packetSize > UDP_IN_MAXSIZE) return;
|
||||
if (!isSupp && notifierUdp.remoteIP() == Network.localIP()) return; //don't process broadcasts we send ourselves
|
||||
if (!isSupp && notifierUdp.remoteIP() == localIP) return; //don't process broadcasts we send ourselves
|
||||
|
||||
uint8_t udpIn[packetSize +1];
|
||||
uint16_t len;
|
||||
@ -190,7 +193,7 @@ void handleNotifications()
|
||||
|
||||
// WLED nodes info notifications
|
||||
if (isSupp && udpIn[0] == 255 && udpIn[1] == 1 && len >= 40) {
|
||||
if (!nodeListEnabled || notifier2Udp.remoteIP() == Network.localIP()) return;
|
||||
if (!nodeListEnabled || notifier2Udp.remoteIP() == localIP) return;
|
||||
|
||||
uint8_t unit = udpIn[39];
|
||||
NodesMap::iterator it = Nodes.find(unit);
|
||||
|
@ -686,13 +686,14 @@ void WLED::initConnection()
|
||||
|
||||
void WLED::initInterfaces()
|
||||
{
|
||||
IPAddress ipAddress = Network.localIP();
|
||||
DEBUG_PRINTLN(F("Init STA interfaces"));
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
if (hueIP[0] == 0) {
|
||||
hueIP[0] = Network.localIP()[0];
|
||||
hueIP[1] = Network.localIP()[1];
|
||||
hueIP[2] = Network.localIP()[2];
|
||||
hueIP[0] = ipAddress[0];
|
||||
hueIP[1] = ipAddress[1];
|
||||
hueIP[2] = ipAddress[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3,12 +3,12 @@
|
||||
/*
|
||||
Main sketch, global variable declarations
|
||||
@title WLED project sketch
|
||||
@version 0.13.0-bl2
|
||||
@version 0.13.0-bl3
|
||||
@author Christian Schwinne
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2109191
|
||||
#define VERSION 2109220
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
|
@ -19,6 +19,10 @@ bool isIp(String str) {
|
||||
}
|
||||
|
||||
void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
|
||||
if (otaLock) {
|
||||
if (final) request->send(500, "text/plain", F("Please unlock OTA in security settings!"));
|
||||
return;
|
||||
}
|
||||
if (!index) {
|
||||
request->_tempFile = WLED_FS.open(filename, "w");
|
||||
DEBUG_PRINT("Uploading ");
|
||||
|
Loading…
Reference in New Issue
Block a user