Merge branch 'master' into merge-master

This commit is contained in:
Blaž Kristan 2022-02-22 10:42:00 +01:00
commit 8af445e72b
16 changed files with 1791 additions and 1790 deletions

View File

@ -2,6 +2,11 @@
### Builds after release 0.12.0
#### Build 2202210
- Fixed HTTP API commands not applying to all selected segments if called from JSON
- Improved Stream effects, no longer rely on LED state and won't fade out at low brightness
#### Build 2202200
- Added `info.leds.seglc` per-segment light capability info (PR #2552)

View File

@ -53,39 +53,18 @@ See the [documentation on our official site](https://kno.wled.ge)!
[On this page](https://kno.wled.ge/basics/tutorials/) you can find excellent tutorials made by the community and helpful tools to help you get your new lamp up and running!
## 🖼️ Images
## 🖼️ User interface
<img src="/images/macbook-pro-space-gray-on-the-wooden-table.jpg" width="50%"><img src="/images/walking-with-iphone-x.jpg" width="50%">
## 💾 Compatible LED Strips
Type | Voltage | Comments
|---|---|---|
WS2812B | 5v |
WS2813 | 5v |
SK6812 | 5v | RGBW
APA102 | 5v | C/D
WS2801 | 5v | C/D
LPD8806 | 5v | C/D
TM1814 | 12v | RGBW
WS2811 | 12v | 3-LED segments
WS2815 | 12v |
GS8208 | 12v |
Analog/non-addressable | any | Requires additional circuitry
## 🧊 Compatible PC RGB Fans and ARGB accessories
Brand | Model | Comments
|---|---|---|
Corsair | HD120 Fan | Uses WS2812B, data-in only
PCCOOLER | Moonlight 5-pack Fans | Uses WS2812B, includes Data-out connector to keep each fan uniquely addressable if wired in series like traditional LED strips
Any | 5v 3-pin ARGB for PC | Any PC RGB device that supports the 5v 3-pin ARGB motherboard header should work fine with WLED. All the major motherboard vendors support the Corsair HD120 and PCCOOLER fans listed, so we can safely assume any device that supports motherboard ARGB 5V 3-Pin standard will work with WLED.
## 💾 Compatible hardware
See [here](https://kno.wled.ge/basics/compatible-hardware)!
## ✌️ Other
Licensed under the MIT license
Credits [here](https://kno.wled.ge/about/contributors/)!
Uses Linearicons by Perxis!
Join the Discord server to discuss everything about WLED!
<a href="https://discord.gg/KuqP7NE"><img src="https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2" width="25%"></a>

View File

@ -494,7 +494,7 @@ public:
#endif
effectCurrentIndex = max(min((increase ? effectCurrentIndex+1 : effectCurrentIndex-1), strip.getModeCount()-1), 0);
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
effectChanged = true;
stateChanged = true;
if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
@ -522,7 +522,7 @@ public:
display->updateRedrawTime();
#endif
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
effectChanged = true;
stateChanged = true;
if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
@ -550,7 +550,7 @@ public:
display->updateRedrawTime();
#endif
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
effectChanged = true;
stateChanged = true;
if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
@ -579,7 +579,7 @@ public:
#endif
effectPaletteIndex = max(min((increase ? effectPaletteIndex+1 : effectPaletteIndex-1), strip.getPaletteCount()-1), 0);
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
effectChanged = true;
stateChanged = true;
if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
@ -608,7 +608,7 @@ public:
#endif
currentHue1 = max(min((increase ? currentHue1+fadeAmount : currentHue1-fadeAmount), 255), 0);
colorHStoRGB(currentHue1*256, currentSat1, col);
colorChanged = true;
stateChanged = true;
if (applyToAll) {
for (byte i=0; i<strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);

View File

@ -25,6 +25,7 @@
*/
#include "FX.h"
#include "wled.h"
#define IBN 5100
#define PALETTE_SOLID_WRAP (paletteBlend == 1 || paletteBlend == 3)
@ -936,7 +937,7 @@ uint16_t WS2812FX::mode_chase_flash_random(void) {
} else {
SEGENV.step = (SEGENV.step + 1) % SEGLEN;
if(SEGENV.step == 0) {
if (SEGENV.step == 0) {
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0);
}
}
@ -965,8 +966,7 @@ uint16_t WS2812FX::running(uint32_t color1, uint32_t color2, bool theatre) {
setPixelColor(i,col);
}
if (it != SEGENV.step )
{
if (it != SEGENV.step) {
SEGENV.aux0 = (SEGENV.aux0 +1) % (theatre ? width : (width<<1));
SEGENV.step = it;
}
@ -996,26 +996,34 @@ uint16_t WS2812FX::mode_halloween(void) {
/*
* Random colored pixels running.
* Random colored pixels running. ("Stream")
*/
uint16_t WS2812FX::mode_running_random(void) {
uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed));
uint32_t it = now / cycleTime;
if (SEGENV.aux1 == it) return FRAMETIME;
if (SEGENV.call == 0) SEGENV.aux0 = random16(); // random seed for PRNG on start
for(uint16_t i=SEGLEN-1; i > 0; i--) {
setPixelColor( i, getPixelColor( i - 1));
}
uint8_t zoneSize = ((255-SEGMENT.intensity) >> 4) +1;
uint16_t PRNG16 = SEGENV.aux0;
if(SEGENV.step == 0) {
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0);
setPixelColor(0, color_wheel(SEGENV.aux0));
}
SEGENV.step++;
if (SEGENV.step > (uint8_t)((255-SEGMENT.intensity) >> 4))
{
SEGENV.step = 0;
uint8_t z = it % zoneSize;
bool nzone = (!z && it != SEGENV.aux1);
for (uint16_t i=SEGLEN-1; i > 0; i--) {
if (nzone || z >= zoneSize) {
uint8_t lastrand = PRNG16 >> 8;
int16_t diff = 0;
while (abs(diff) < 42) { // make sure the difference between adjacent colors is big enough
PRNG16 = (uint16_t)(PRNG16 * 2053) + 13849; // next zone, next 'random' number
diff = (PRNG16 >> 8) - lastrand;
}
if (nzone) {
SEGENV.aux0 = PRNG16; // save next starting seed
nzone = false;
}
z = 0;
}
setPixelColor(i, color_wheel(PRNG16 >> 8));
z++;
}
SEGENV.aux1 = it;
@ -1589,26 +1597,36 @@ uint16_t WS2812FX::mode_dual_larson_scanner(void){
/*
* Running random pixels
* Running random pixels ("Stream 2")
* Custom mode by Keith Lord: https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/RandomChase.h
*/
uint16_t WS2812FX::mode_random_chase(void)
{
if (SEGENV.call == 0) {
SEGENV.step = RGBW32(random8(), random8(), random8(), 0);
SEGENV.aux0 = random16();
}
uint16_t prevSeed = random16_get_seed(); // save seed so we can restore it at the end of the function
uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed));
uint32_t it = now / cycleTime;
if (SEGENV.step == it) return FRAMETIME;
uint32_t color = SEGENV.step;
random16_set_seed(SEGENV.aux0);
for(uint16_t i = SEGLEN -1; i > 0; i--) {
setPixelColor(i, getPixelColor(i-1));
uint8_t r = random8(6) != 0 ? (color >> 16 & 0xFF) : random8();
uint8_t g = random8(6) != 0 ? (color >> 8 & 0xFF) : random8();
uint8_t b = random8(6) != 0 ? (color & 0xFF) : random8();
color = RGBW32(r, g, b, 0);
setPixelColor(i, r, g, b);
if (i == SEGLEN -1 && SEGENV.aux1 != (it & 0xFFFF)) { //new first color in next frame
SEGENV.step = color;
SEGENV.aux0 = random16_get_seed();
}
}
uint32_t color = getPixelColor(0);
if (SEGLEN > 1) color = getPixelColor( 1);
uint8_t r = random8(6) != 0 ? (color >> 16 & 0xFF) : random8();
uint8_t g = random8(6) != 0 ? (color >> 8 & 0xFF) : random8();
uint8_t b = random8(6) != 0 ? (color & 0xFF) : random8();
setPixelColor(0, r, g, b);
SEGENV.step = it;
SEGENV.aux1 = it & 0xFFFF;
random16_set_seed(prevSeed); // restore original seed so other effects can use "random" PRNG
return FRAMETIME;
}

View File

@ -17,7 +17,7 @@ void shortPressAction(uint8_t b)
if (!macroButton[b]) {
switch (b) {
case 0: toggleOnOff(); stateUpdated(CALL_MODE_BUTTON); break;
case 1: ++effectCurrent %= strip.getModeCount(); effectChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
case 1: ++effectCurrent %= strip.getModeCount(); stateChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
}
} else {
applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);

View File

@ -17,7 +17,7 @@ void relativeChangeWhite(int8_t amount, byte lowerBoundary)
if (new_val > 0xFF) new_val = 0xFF;
else if (new_val < lowerBoundary) new_val = lowerBoundary;
col[3] = new_val;
colorChanged = true;
stateChanged = true;
}
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb

View File

@ -157,7 +157,7 @@
</div>
<p class="labels h" id="cslLabel"></p>
<div id="hexw">
<input id="hexc" type="text" class="noslide" onkeydown="hexEnter(this)" autocomplete="off" maxlength="8" />
<input id="hexc" type="text" class="noslide" onkeydown="hexEnter()" autocomplete="off" maxlength="8" />
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon">&#xe390;</i></button>
</div>
<div id="palw" class="il">

View File

@ -665,8 +665,8 @@ function populateSegments(s)
<td>Offset</td>
</tr>
<tr>
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${ledCount-1}" value="${inst.start}" oninput="updateLen(${i})"></td>
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})"></td>
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${ledCount-1}" value="${inst.start}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${ledCount-(cfg.comp.seglen?inst.start:0)}" value="${inst.stop-(cfg.comp.seglen?inst.start:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
</tr>
<tr>
@ -675,8 +675,8 @@ function populateSegments(s)
<td>Apply</td>
</tr>
<tr>
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})"></td>
<td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})"></td>
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
<td><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}">&#xe390;</i></button></td>
</tr>
</table>
@ -1481,8 +1481,8 @@ function makeSeg()
<td width="38%">${cfg.comp.seglen?"LED count":"Stop LED"}</td>
</tr>
<tr>
<td><input class="noslide segn" id="seg${lu}s" type="number" min="0" max="${ledCount-1}" value="${ns}" oninput="updateLen(${lu})"></td>
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})"></td>
<td><input class="noslide segn" id="seg${lu}s" type="number" min="0" max="${ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
<td><button class="btn btn-xs" onclick="setSeg(${lu});resetUtil();"><i class="icons bth-icon" id="segc${lu}">&#xe390;</i></button></td>
</tr>
</table>
@ -2047,6 +2047,10 @@ function hexEnter()
if(event.keyCode == 13) fromHex();
}
function segEnter(s) {
if(event.keyCode == 13) setSeg(s);
}
function fromHex()
{
var str = gId('hexc').value;

File diff suppressed because it is too large Load Diff

View File

@ -98,7 +98,7 @@ void changeEffect(uint8_t fx)
strip.setMode(strip.getMainSegmentId(), fx);
}
effectCurrent = fx;
effectChanged = true;
stateChanged = true;
}
void changePalette(uint8_t pal)
@ -113,7 +113,7 @@ void changePalette(uint8_t pal)
strip.getSegment(strip.getMainSegmentId()).palette = pal;
}
effectPalette = pal;
effectChanged = true;
stateChanged = true;
}
void changeEffectSpeed(int8_t amount)
@ -130,7 +130,6 @@ void changeEffectSpeed(int8_t amount)
} else {
strip.getSegment(strip.getMainSegmentId()).speed = effectSpeed;
}
effectChanged = true;
} else { // if Effect == "solid Color", change the hue of the primary color
CRGB fastled_col;
fastled_col.red = col[0];
@ -154,8 +153,8 @@ void changeEffectSpeed(int8_t amount)
} else {
strip.getSegment(strip.getMainSegmentId()).colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
}
colorChanged = true;
}
stateChanged = true;
if(amount > 0) lastRepeatableAction = ACTION_SPEED_UP;
if(amount < 0) lastRepeatableAction = ACTION_SPEED_DOWN;
@ -176,7 +175,6 @@ void changeEffectIntensity(int8_t amount)
} else {
strip.getSegment(strip.getMainSegmentId()).speed = effectIntensity;
}
effectChanged = true;
} else { // if Effect == "solid Color", change the saturation of the primary color
CRGB fastled_col;
fastled_col.red = col[0];
@ -198,8 +196,8 @@ void changeEffectIntensity(int8_t amount)
} else {
strip.getSegment(strip.getMainSegmentId()).colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
}
colorChanged = true;
}
stateChanged = true;
if(amount > 0) lastRepeatableAction = ACTION_INTENSITY_UP;
if(amount < 0) lastRepeatableAction = ACTION_INTENSITY_DOWN;
@ -241,7 +239,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
if (isCCT && cct >= 0) seg.setCCT(cct, i);
}
setValuesFromMainSeg(); //make transitions graceful
colorChanged = true;
stateChanged = true;
}
void decodeIR(uint32_t code)
@ -257,7 +255,7 @@ void decodeIR(uint32_t code)
lastRepeatableAction = ACTION_NONE;
if (irEnabled == 8) { // any remote configurable with ir.json file
decodeIRJson(code);
colorUpdated(CALL_MODE_BUTTON);
stateUpdated(CALL_MODE_BUTTON);
return;
}
if (code > 0xFFFFFF) return; //invalid code
@ -666,7 +664,7 @@ void decodeIRJson(uint32_t code)
cmdStr += tmp;
}
fdo.clear(); // clear JSON buffer (it is no longer needed)
handleSet(nullptr, cmdStr, false); // no colorUpdated() call here
handleSet(nullptr, cmdStr, false); // no stateUpdated() call here
}
} else {
// command is JSON object (TODO: currently will not handle irApplyToAllSelected correctly)

View File

@ -120,17 +120,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
byte sz = colX.size();
if (sz == 0) continue; //do nothing on empty array
byte cp = copyArray(colX, rgbw, 4);
if (cp == 1 && rgbw[0] == 0)
seg.setColor(i, 0, id);
byte cp = copyArray(colX, rgbw, 4);
colValid = true;
}
if (!colValid) continue;
uint32_t color = RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]);
colorChanged |= (seg.colors[i] != color);
seg.setColor(i, color, id);
seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]), id);
if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh
}
}
@ -216,7 +212,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
seg.setOption(SEG_OPTION_FREEZE, false);
}
//send UDP if not in preset and something changed that is not just selection
if (!presetId && (seg.differs(prev) & 0x7F)) effectChanged = true;
if (!presetId && (seg.differs(prev) & 0x7F)) stateChanged = true;
return;
}

View File

@ -30,20 +30,14 @@ void applyValuesToSelectedSegs()
WS2812FX::Segment& seg = strip.getSegment(i);
if (i != strip.getMainSegmentId() && (!seg.isActive() || !seg.isSelected())) continue;
if (effectSpeed != mainsegPrev.speed) {
seg.speed = effectSpeed; effectChanged = true;}
if (effectIntensity != mainsegPrev.intensity) {
seg.intensity = effectIntensity; effectChanged = true;}
if (effectPalette != mainsegPrev.palette) {
seg.palette = effectPalette; effectChanged = true;}
if (effectCurrent != mainsegPrev.mode) {
strip.setMode(i, effectCurrent); effectChanged = true;}
uint32_t col0 = RGBW32(col[0], col[1], col[2], col[3]);
if (effectSpeed != mainsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
if (effectIntensity != mainsegPrev.intensity) {seg.intensity = effectIntensity; stateChanged = true;}
if (effectPalette != mainsegPrev.palette) {seg.palette = effectPalette; stateChanged = true;}
if (effectCurrent != mainsegPrev.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
if (col0 != mainsegPrev.colors[0]) {
seg.setColor(0, col0, i); colorChanged = true;}
if (col1 != mainsegPrev.colors[1]) {
seg.setColor(1, col1, i); colorChanged = true;}
if (col0 != mainsegPrev.colors[0]) {seg.setColor(0, col0, i); stateChanged = true;}
if (col1 != mainsegPrev.colors[1]) {seg.setColor(1, col1, i); stateChanged = true;}
}
}
@ -100,16 +94,15 @@ void stateUpdated(byte callMode) {
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa 11: ws send only 12: button preset
setValuesFromMainSeg();
if (bri != briOld || effectChanged || colorChanged) {
if (bri != briOld || stateChanged) {
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (effectChanged) currentPreset = 0; //something changed, so we are no longer in the preset
if (stateChanged) currentPreset = 0; //something changed, so we are no longer in the preset
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
//set flag to update blynk, ws and mqtt
interfaceUpdateCallMode = callMode;
effectChanged = false;
colorChanged = false;
stateChanged = false;
} else {
if (nightlightActive && !nightlightActiveOld && callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) {
notify(CALL_MODE_NIGHTLIGHT);

View File

@ -550,14 +550,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
byte selectedSeg = strip.getMainSegmentId();
if (selectedSeg != prevMain) setValuesFromMainSeg();
//temporary values, do not write direcly to global values if only setting a single segment
byte colIn[4] = {col[0], col[1], col[2], col[3]};
byte colInSec[4] = {colSec[0], colSec[1], colSec[2], colSec[3]};
byte effectIn = effectCurrent;
byte speedIn = effectSpeed;
byte intensityIn = effectIntensity;
byte paletteIn = effectPalette;
bool singleSegment = false;
pos = req.indexOf(F("SS="));
@ -577,6 +569,16 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
selseg.setOption(SEG_OPTION_SELECTED, t);
}
// temporary values, write directly to segments, globals are updated by setValuesFromMainSeg()
uint32_t col0 = selseg.colors[0];
uint32_t col1 = selseg.colors[1];
byte colIn[4] = {R(col0), G(col0), B(col0), W(col0)};
byte colInSec[4] = {R(col1), G(col1), B(col1), W(col1)};
byte effectIn = selseg.mode;
byte speedIn = selseg.speed;
byte intensityIn = selseg.intensity;
byte paletteIn = selseg.palette;
uint16_t startI = selseg.start;
uint16_t stopI = selseg.stop;
uint8_t grpI = selseg.grouping;
@ -642,20 +644,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
//set brightness
updateVal(&req, "&A=", &bri);
bool col0Changed = false, col1Changed = false, col2Changed = false;
bool col0Changed = false, col1Changed = false;
//set colors
updateVal(&req, "&R=", &colIn[0]);
updateVal(&req, "&G=", &colIn[1]);
updateVal(&req, "&B=", &colIn[2]);
updateVal(&req, "&W=", &colIn[3]);
for (byte i=0; i<4; i++) if (colIn[i]!=col[i]) col0Changed = colorChanged = true;
if (col0Changed) selseg.setColor(0, RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]), selectedSeg); // use transitions
updateVal(&req, "R2=", &colInSec[0]);
updateVal(&req, "G2=", &colInSec[1]);
updateVal(&req, "B2=", &colInSec[2]);
updateVal(&req, "W2=", &colInSec[3]);
for (byte i=0; i<4; i++) if (colInSec[i]!=colSec[i]) col1Changed = colorChanged = true;
if (col1Changed) selseg.setColor(1, RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]), selectedSeg); // use transitions
col0Changed |= updateVal(&req, "&R=", &colIn[0]);
col0Changed |= updateVal(&req, "&G=", &colIn[1]);
col0Changed |= updateVal(&req, "&B=", &colIn[2]);
col0Changed |= updateVal(&req, "&W=", &colIn[3]);
col1Changed |= updateVal(&req, "R2=", &colInSec[0]);
col1Changed |= updateVal(&req, "G2=", &colInSec[1]);
col1Changed |= updateVal(&req, "B2=", &colInSec[2]);
col1Changed |= updateVal(&req, "W2=", &colInSec[3]);
#ifdef WLED_ENABLE_LOXONE
//lox parser
@ -665,6 +664,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (parseLx(lxValue, colIn)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
col0Changed = true;
}
}
pos = req.indexOf(F("LY=")); // Lox secondary color
@ -673,6 +673,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if(parseLx(lxValue, colInSec)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
col1Changed = true;
}
}
#endif
@ -688,9 +689,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
byte sec = req.indexOf(F("H2"));
colorHStoRGB(temphue, tempsat, (sec>0) ? colInSec : colIn);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
col0Changed |= (!sec); col1Changed |= sec;
}
//set white spectrum (kelvin)
@ -698,9 +697,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (pos > 0) {
byte sec = req.indexOf(F("K2"));
colorKtoRGB(getNumVal(&req, pos), (sec>0) ? colInSec : colIn);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
col0Changed |= (!sec); col1Changed |= sec;
}
//set color from HEX or 32bit DEC
@ -708,20 +705,20 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("CL="));
if (pos > 0) {
colorFromDecOrHexString(colIn, (char*)req.substring(pos + 3).c_str());
selseg.setColor(0, RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]), selectedSeg); // defined above (SS= or main)
col0Changed = colorChanged = true;
col0Changed = true;
}
pos = req.indexOf(F("C2="));
if (pos > 0) {
colorFromDecOrHexString(colInSec, (char*)req.substring(pos + 3).c_str());
selseg.setColor(1, RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]), selectedSeg); // defined above (SS= or main)
col1Changed = colorChanged = true;
col1Changed = true;
}
pos = req.indexOf(F("C3="));
if (pos > 0) {
colorFromDecOrHexString(tmpCol, (char*)req.substring(pos + 3).c_str());
selseg.setColor(2, RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]), selectedSeg); // defined above (SS= or main)
col2Changed = colorChanged = true;
uint32_t col2 = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
selseg.setColor(2, col2, selectedSeg); // defined above (SS= or main)
stateChanged = true;
if (!singleSegment) strip.setColor(2, col2); // will set color to all active & selected segments
}
//set to random hue SR=0->1st SR=1->2nd
@ -729,9 +726,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (pos > 0) {
byte sec = getNumVal(&req, pos);
setRandomColor(sec? colInSec : colIn);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
col0Changed |= (!sec); col1Changed |= sec;
}
//swap 2nd & 1st
@ -743,33 +738,44 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
colIn[i] = colInSec[i];
colInSec[i] = temp;
}
col0Changed = col1Changed = colorChanged = true;
col0Changed = col1Changed = true;
}
//set effect parameters
if (updateVal(&req, "FX=", &effectIn, 0, strip.getModeCount()-1) && request != nullptr) unloadPlaylist(); //unload playlist if changing FX using web request
updateVal(&req, "SX=", &speedIn);
updateVal(&req, "IX=", &intensityIn);
updateVal(&req, "FP=", &paletteIn, 0, strip.getPaletteCount()-1);
strip.setMode(selectedSeg, effectIn);
selseg.speed = speedIn;
selseg.intensity = intensityIn;
selseg.palette = paletteIn;
if (effectIn != effectCurrent || speedIn != effectSpeed || intensityIn != effectIntensity || paletteIn != effectPalette) effectChanged = true;
// apply colors to selected segment, and all selected segments if applicable
if (col0Changed) {
stateChanged = true;
uint32_t colIn0 = RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]);
selseg.setColor(0, colIn0, selectedSeg);
if (!singleSegment) strip.setColor(0, colIn0); // will set color to all active & selected segments
}
//apply to all selected manually to prevent #1618.
if (!singleSegment) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected() || i == selectedSeg) continue;
if (effectCurrent != effectIn) strip.setMode(i, effectIn);
if (effectSpeed != speedIn) seg.speed = speedIn;
if (effectIntensity != intensityIn) seg.intensity = intensityIn;
if (effectPalette != paletteIn) seg.palette = paletteIn;
if (col0Changed) seg.setColor(0, RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]), i); // use transitions
if (col1Changed) seg.setColor(1, RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]), i); // use transitions
if (col2Changed) seg.colors[2] = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
}
if (col1Changed) {
stateChanged = true;
uint32_t colIn1 = RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]);
selseg.setColor(1, colIn1, selectedSeg);
if (!singleSegment) strip.setColor(1, colIn1); // will set color to all active & selected segments
}
bool fxModeChanged = false, speedChanged = false, intensityChanged = false, paletteChanged = false;
// set effect parameters
if (updateVal(&req, "FX=", &effectIn, 0, strip.getModeCount()-1)) {
if (request != nullptr) unloadPlaylist(); // unload playlist if changing FX using web request
fxModeChanged = true;
}
speedChanged = updateVal(&req, "SX=", &speedIn);
intensityChanged = updateVal(&req, "IX=", &intensityIn);
paletteChanged = updateVal(&req, "FP=", &paletteIn, 0, strip.getPaletteCount()-1);
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
//apply to main and all selected segments to prevent #1618.
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
if (fxModeChanged) strip.setMode(i, effectIn);
if (speedChanged) seg.speed = speedIn;
if (intensityChanged) seg.intensity = intensityIn;
if (paletteChanged) seg.palette = paletteIn;
}
setValuesFromMainSeg(); // will fill col[] and cloSec[] as well as effectCurrent, ...
@ -899,16 +905,16 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (pos > 0) {
userVar1 = getNumVal(&req, pos);
}
//you can add more if you need
// you can add more if you need
if (!apply) return true; //when called by JSON API, do not call colorUpdated() here
if (!apply) return true; // when called by JSON API, do not call stateUpdated() here
//internal call, does not send XML response
pos = req.indexOf(F("IN"));
if (pos < 1) XML_response(request);
pos = req.indexOf(F("&NN")); //do not send UDP notifications this time
colorUpdated((pos > 0) ? CALL_MODE_NO_NOTIFY : CALL_MODE_DIRECT_CHANGE);
stateUpdated((pos > 0) ? CALL_MODE_NO_NOTIFY : CALL_MODE_DIRECT_CHANGE);
return true;
}

View File

@ -359,8 +359,7 @@ void handleNotifications()
strip.setSegment(id, selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], selseg.offset);
}
}
effectChanged = true;
colorChanged = true;
stateChanged = true;
}
if (applyEffects && (version < 11 || !receiveSegmentOptions)) { //simple effect sync, applies to all selected

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2202201
#define VERSION 2202211
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -488,8 +488,7 @@ WLED_GLOBAL byte effectCurrent _INIT(0);
WLED_GLOBAL byte effectSpeed _INIT(128);
WLED_GLOBAL byte effectIntensity _INIT(128);
WLED_GLOBAL byte effectPalette _INIT(0);
WLED_GLOBAL bool effectChanged _INIT(false);
WLED_GLOBAL bool colorChanged _INIT(false);
WLED_GLOBAL bool stateChanged _INIT(false);
// network
WLED_GLOBAL bool udpConnected _INIT(false), udp2Connected _INIT(false), udpRgbConnected _INIT(false);

View File

@ -240,7 +240,7 @@ void initServer()
{
serveMessage(request, 500, F("Failed updating firmware!"), F("Please check your file and retry!"), 254); return;
}
serveMessage(request, 200, F("Successfully updated firmware!"), F("Please wait while the module reboots..."), 131);
serveMessage(request, 200, F("Successfully updated firmware!"), F("Rebooting..."), 131);
doReboot = true;
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index){