Merge branch 'master' into merge-master

This commit is contained in:
Blaz Kristan 2022-02-20 22:24:11 +01:00
parent c895b76864
commit 41b6f3ffa7
45 changed files with 2184 additions and 2213 deletions

View File

@ -2,6 +2,17 @@
### Builds after release 0.12.0
#### Build 2202200
- Added `info.leds.seglc` per-segment light capability info (PR #2552)
- Fixed `info.leds.rgbw` behavior
- Segment bounds sync (PR #2547)
- WebSockets auto reconnection and error handling
- Disable relay pin by default (PR #2531)
- Various fixes (ESP32 touch pin 33, floats, PR #2530, #2534, #2538)
- Deprecated `info.leds.cct`, `info.leds.wv` and `info.leds.rgbw`
- Deprecated `/url` endpoint
#### Build 2202030
- Switched to binary format for WebSockets peek (PR #2516)
@ -19,26 +30,26 @@
#### Build 2112080
- Version bump to 0.13.0-b6 "Toki"
- Added "ESP02" (ESP8266 with 2M of flash) to PIO/release binaries
- Version bump to 0.13.0-b6 "Toki"
- Added "ESP02" (ESP8266 with 2M of flash) to PIO/release binaries
#### Build 2112070
- Added new effect "Fairy", replacing "Police All"
- Added new effect "Fairytwinkle", replacing "Two Areas"
- Static single JSON buffer (performance and stability improvement) (PR #2336)
- Added new effect "Fairy", replacing "Police All"
- Added new effect "Fairytwinkle", replacing "Two Areas"
- Static single JSON buffer (performance and stability improvement) (PR #2336)
#### Build 2112030
- Fixed ESP32 crash on Colortwinkles brightness change
- Fixed setting picker to black resetting hue and saturation
- Fixed auto white mode not saved to config
- Fixed ESP32 crash on Colortwinkles brightness change
- Fixed setting picker to black resetting hue and saturation
- Fixed auto white mode not saved to config
#### Build 2111300
- Added CCT and white balance correction support (PR #2285)
- Unified UI slider style
- Added LED settings config template upload
- Added CCT and white balance correction support (PR #2285)
- Unified UI slider style
- Added LED settings config template upload
#### Build 2111220

6
package-lock.json generated
View File

@ -28,9 +28,9 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"ajv": {
"version": "6.12.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
"integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",

View File

@ -104,7 +104,6 @@ build_flags =
-DBEARSSL_SSL_BASIC
-D CORE_DEBUG_LEVEL=0
-D NDEBUG
;-Dregister=
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
-D _IR_ENABLE_DEFAULT_=false
-D DECODE_HASH=true

View File

@ -100,9 +100,9 @@ void userLoop() {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
} else if (knownMode != strip.getMainSegment().mode) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
} else if (knownPalette != strip.getMainSegment().palette) {
needRedraw = true;
}
@ -126,8 +126,8 @@ void userLoop() {
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);

View File

@ -143,9 +143,9 @@ void userLoop() {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
} else if (knownMode != strip.getMainSegment().mode) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
} else if (knownPalette != strip.getMainSegment().palette) {
needRedraw = true;
}
@ -169,8 +169,8 @@ void userLoop() {
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);

View File

@ -61,7 +61,7 @@ class PIRsensorSwitch : public Usermod {
private:
// PIR sensor pin
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
// notification mode for colorUpdated()
// notification mode for stateUpdated()
const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE
// 1 min delay before switch off after the sensor state goes LOW
uint32_t m_switchOffDelay = 60000;
@ -127,7 +127,7 @@ class PIRsensorSwitch : public Usermod {
if (bri != briHighlight) {
bri = briHighlight; // set current highlight brightness to last set highlight brightness
}
colorUpdated(NotifyUpdateMode);
stateUpdated(NotifyUpdateMode);
highlightActive = true; // flag highlight is on
}
else { // **pir timer has elapsed**
@ -157,7 +157,7 @@ class PIRsensorSwitch : public Usermod {
}
applyMacro(macroLongPress); // apply standby lighting without brightness
}
colorUpdated(NotifyUpdateMode);
stateUpdated(NotifyUpdateMode);
highlightActive = false; // flag highlight is off
}
}

View File

@ -60,7 +60,7 @@ private:
byte prevPlaylist = 0;
uint32_t offTimerStart = 0; // off timer start time
byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // notification mode for colorUpdated(): CALL_MODE_NO_NOTIFY or CALL_MODE_DIRECT_CHANGE
byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // notification mode for stateUpdated(): CALL_MODE_NO_NOTIFY or CALL_MODE_DIRECT_CHANGE
byte sensorPinState = LOW; // current PIR sensor pin state
bool initDone = false; // status of initialization
bool PIRtriggered = false;
@ -139,7 +139,7 @@ private:
// preset not assigned
if (bri == 0) {
bri = briLast;
colorUpdated(NotifyUpdateMode);
stateUpdated(NotifyUpdateMode);
}
} else {
if (m_offPreset) {
@ -159,7 +159,7 @@ private:
if (bri != 0) {
briLast = bri;
bri = 0;
colorUpdated(NotifyUpdateMode);
stateUpdated(NotifyUpdateMode);
}
}
}

View File

@ -110,9 +110,9 @@ void userLoop() {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
} else if (knownMode != strip.getMainSegment().mode) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
} else if (knownPalette != strip.getMainSegment().palette) {
needRedraw = true;
}
@ -136,8 +136,8 @@ void userLoop() {
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
tft.fillScreen(TFT_BLACK);
tft.setTextSize(2);

View File

@ -106,7 +106,7 @@ class UsermodVL53L0XGestures : public Usermod {
// set brightness according to range
bri = (VL53L0X_MAX_RANGE_MM - max(range, VL53L0X_MIN_RANGE_OFFSET)) * 255 / (VL53L0X_MAX_RANGE_MM - VL53L0X_MIN_RANGE_OFFSET);
DEBUG_PRINTF(F("new brightness: %d"), bri);
colorUpdated(1);
stateUpdated(1);
}
} else if (wasMotionBefore) { //released
long dur = millis() - motionStartTime;

View File

@ -137,9 +137,9 @@ void userLoop() {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
} else if (knownMode != strip.getMainSegment().mode) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
} else if (knownPalette != strip.getMainSegment().palette) {
needRedraw = true;
}
@ -163,8 +163,8 @@ void userLoop() {
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);

View File

@ -143,9 +143,9 @@ void userLoop() {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
} else if (knownMode != strip.getMainSegment().mode) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
} else if (knownPalette != strip.getMainSegment().palette) {
needRedraw = true;
}
@ -169,8 +169,8 @@ void userLoop() {
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);

View File

@ -54,35 +54,27 @@ void userLoop()
switch (myKey) {
case '1':
applyPreset(1);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '2':
applyPreset(2);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '3':
applyPreset(3);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '4':
applyPreset(4);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '5':
applyPreset(5);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '6':
applyPreset(6);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case 'A':
applyPreset(7);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case 'B':
applyPreset(8);
colorUpdated(CALL_MODE_FX_CHANGED);
break;
case '7':

View File

@ -86,7 +86,7 @@ private:
static const char _str_minBrightness[];
static const char _str_maxBrightness[];
#ifdef USERMOD_ID_SN_PHOTORESISTOR
#ifdef USERMOD_SN_PHOTORESISTOR
Usermod_SN_Photoresistor *ptr;
#else
void* ptr = nullptr;
@ -371,7 +371,7 @@ public:
}
_setAllFalse();
#ifdef USERMOD_ID_SN_PHOTORESISTOR
#ifdef USERMOD_SN_PHOTORESISTOR
ptr = (Usermod_SN_Photoresistor*) usermods.lookup(USERMOD_ID_SN_PHOTORESISTOR);
#endif
DEBUG_PRINTLN(F("Setup done"));
@ -391,7 +391,7 @@ public:
uint16_t brightness = map(lux, 0, 1000, umSSDRBrightnessMin, umSSDRBrightnessMax);
if (bri != brightness) {
bri = brightness;
colorUpdated(1);
stateUpdated(1);
}
}
umSSDRLastRefresh = millis();

View File

@ -111,7 +111,7 @@ class StairwayWipeUsermod : public Usermod {
transitionDelayTemp = 4000; //fade out slowly
#endif
bri = 0;
colorUpdated(CALL_MODE_NOTIFICATION);
stateUpdated(CALL_MODE_NOTIFICATION);
wipeState = 0;
userVar0 = 0;
previousUserVar0 = 0;

View File

@ -104,7 +104,7 @@ void turnOff()
transitionDelayTemp = 4000; //fade out slowly
#endif
bri = 0;
colorUpdated(CALL_MODE_NOTIFICATION);
stateUpdated(CALL_MODE_NOTIFICATION);
wipeState = 0;
userVar0 = 0;
previousUserVar0 = 0;

View File

@ -92,8 +92,8 @@ class AutoSaveUsermod : public Usermod {
knownBrightness = bri;
knownEffectSpeed = effectSpeed;
knownEffectIntensity = effectIntensity;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
}
// gets called every time WiFi is (re-)connected. Initialize own network
@ -107,8 +107,8 @@ class AutoSaveUsermod : public Usermod {
if (!autoSaveAfterSec || !enabled || strip.isUpdating() || currentPreset>0) return; // setting 0 as autosave seconds disables autosave
unsigned long now = millis();
uint8_t currentMode = strip.getMode();
uint8_t currentPalette = strip.getSegment(0).palette;
uint8_t currentMode = strip.getMainSegment().mode;
uint8_t currentPalette = strip.getMainSegment().palette;
unsigned long wouldAutoSaveAfter = now + autoSaveAfterSec*1000;
if (knownBrightness != bri) {

View File

@ -349,8 +349,8 @@ class FourLineDisplayUsermod : public Usermod {
(knownBrightness != bri) ||
(knownEffectSpeed != effectSpeed) ||
(knownEffectIntensity != effectIntensity) ||
(knownMode != strip.getMode()) ||
(knownPalette != strip.getSegment(0).palette)) {
(knownMode != strip.getMainSegment().mode) ||
(knownPalette != strip.getMainSegment().palette)) {
knownHour = 99; // force time update
lastRedraw = now; // update lastRedraw marker
} else if (sleepMode && !displayTurnedOff && ((now - lastRedraw)/1000)%5 == 0) {
@ -398,8 +398,8 @@ class FourLineDisplayUsermod : public Usermod {
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
knownIp = apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
knownMode = strip.getMainSegment().mode;
knownPalette = strip.getMainSegment().palette;
knownEffectSpeed = effectSpeed;
knownEffectIntensity = effectIntensity;

View File

@ -291,12 +291,8 @@ public:
}
void lampUdated() {
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
colorUpdated(CALL_MODE_DIRECT_CHANGE);
updateInterfaces(CALL_MODE_DIRECT_CHANGE);
colorUpdated(CALL_MODE_BUTTON);
updateInterfaces(CALL_MODE_BUTTON);
}
void changeBrightness(bool increase) {

View File

@ -459,12 +459,11 @@ public:
}
void lampUdated() {
//bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
setValuesFromMainSeg(); //to make transition work on main segment
colorUpdated(CALL_MODE_DIRECT_CHANGE);
updateInterfaces(CALL_MODE_DIRECT_CHANGE);
//setValuesFromMainSeg(); //to make transition work on main segment (should no longer be required)
stateUpdated(CALL_MODE_BUTTON);
updateInterfaces(CALL_MODE_BUTTON);
}
void changeBrightness(bool increase) {

View File

@ -630,6 +630,7 @@ class WS2812FX {
calcGammaTable(float),
trigger(void),
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0, uint16_t offset = UINT16_MAX),
setMainSegmentId(uint8_t n),
restartRuntime(),
resetSegments(),
makeAutoSegments(bool forceReset = false),
@ -643,29 +644,25 @@ class WS2812FX {
bool
gammaCorrectBri = false,
gammaCorrectCol = true,
applyToAllSelected = true,
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p),
checkSegmentAlignment(void),
hasCCTBus(void),
hasRGBWBus(void),
hasCCTBus(void),
// return true if the strip is being sent pixel updates
isUpdating(void);
uint8_t
mainSegment = 0,
paletteFade = 0,
paletteBlend = 0,
milliampsPerLed = 55,
cctBlending = 0,
getBrightness(void),
getMode(void),
getSpeed(void),
getModeCount(void),
getPaletteCount(void),
getMaxSegments(void),
getActiveSegmentsNum(void),
//getFirstSelectedSegment(void),
getMainSegmentId(void),
getTargetFps(void),
getLastActiveSegmentId(void),
getTargetFps(void),
setPixelSegment(uint8_t n),
gamma8(uint8_t),
gamma8_cal(uint8_t, float),
@ -695,11 +692,9 @@ class WS2812FX {
getPixelColor(uint16_t),
getColor(void);
WS2812FX::Segment&
getSegment(uint8_t n);
WS2812FX::Segment_runtime
getSegmentRuntime(void);
WS2812FX::Segment
&getSegment(uint8_t n),
&getMainSegment(void);
WS2812FX::Segment*
getSegments(void);
@ -893,6 +888,8 @@ class WS2812FX {
uint8_t _segment_index = 0;
uint8_t _segment_index_palette_last = 99;
uint8_t _mainSegment;
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element
// start, stop, offset, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[]
{0, 7, 0, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}}

View File

@ -392,64 +392,21 @@ uint8_t WS2812FX::getPaletteCount()
{
return 13 + GRADIENT_PALETTE_COUNT;
}
//TODO effect transitions
/*
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
Segment& seg = _segments[getMainSegmentId()];
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
bool applied = false;
if (applyToAllSelected) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected())
{
_segments[i].speed = s;
_segments[i].intensity = in;
_segments[i].palette = p;
setMode(i, m);
applied = true;
}
}
}
if (!applyToAllSelected || !applied) {
seg.speed = s;
seg.intensity = in;
seg.palette = p;
setMode(mainSegment, m);
}
if (seg.mode != modePrev || seg.speed != speedPrev || seg.intensity != intensityPrev || seg.palette != palettePrev) return true;
return false;
}
void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
setColor(slot, RGBW32(r, g, b, w));
}
*/
//applies to all active and selected segments
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS) return;
bool applied = false;
if (applyToAllSelected) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) {
_segments[i].setColor(slot, c, i);
applied = true;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) {
_segments[i].setColor(slot, c, i);
}
}
if (!applyToAllSelected || !applied) {
uint8_t mainseg = getMainSegmentId();
_segments[mainseg].setColor(slot, c, mainseg);
}
}
void WS2812FX::setBrightness(uint8_t b) {
@ -466,14 +423,6 @@ void WS2812FX::setBrightness(uint8_t b) {
if (_segment_runtimes[0].next_time > t + 22 && t - _lastShow > MIN_SHOW_DELAY) show(); //apply brightness change immediately if no refresh soon
}
uint8_t WS2812FX::getMode(void) {
return _segments[getMainSegmentId()].mode;
}
uint8_t WS2812FX::getSpeed(void) {
return _segments[getMainSegmentId()].speed;
}
uint8_t WS2812FX::getBrightness(void) {
return _brightness;
}
@ -482,24 +431,37 @@ uint8_t WS2812FX::getMaxSegments(void) {
return MAX_NUM_SEGMENTS;
}
/*uint8_t WS2812FX::getFirstSelectedSegment(void)
{
void WS2812FX::setMainSegmentId(uint8_t n) {
if (n >= MAX_NUM_SEGMENTS) return;
if (_segments[n].isActive() && _segments[n].isSelected()) {
_mainSegment = n; return;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive() && _segments[i].isSelected()) return i;
if (_segments[i].isActive() && _segments[i].isSelected()) {
_mainSegment = i; return;
}
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //if none selected, get first active
//if none selected, use supplied n if active, or first active
if (_segments[n].isActive()) {
_mainSegment = n; return;
}
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) return i;
if (_segments[i].isActive()) {
_mainSegment = i; return;
}
}
return 0;
}*/
_mainSegment = 0;
return;
}
uint8_t WS2812FX::getMainSegmentId(void) {
if (mainSegment >= MAX_NUM_SEGMENTS) return 0;
if (_segments[mainSegment].isActive()) return mainSegment;
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //get first active
{
return _mainSegment;
}
uint8_t WS2812FX::getLastActiveSegmentId(void) {
for (uint8_t i = MAX_NUM_SEGMENTS -1; i > 0; i--) {
if (_segments[i].isActive()) return i;
}
return 0;
@ -539,8 +501,8 @@ WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
return _segments[id];
}
WS2812FX::Segment_runtime WS2812FX::getSegmentRuntime(void) {
return SEGENV;
WS2812FX::Segment& WS2812FX::getMainSegment(void) {
return _segments[getMainSegmentId()];
}
WS2812FX::Segment* WS2812FX::getSegments(void) {
@ -578,7 +540,9 @@ uint8_t WS2812FX::Segment::differs(Segment& b) {
if (intensity != b.intensity) d |= SEG_DIFFERS_FX;
if (palette != b.palette) d |= SEG_DIFFERS_FX;
if ((options & 0b00101111) != (b.options & 0b00101111)) d |= SEG_DIFFERS_OPT;
if ((options & 0b00101110) != (b.options & 0b00101110)) d |= SEG_DIFFERS_OPT;
if ((options & 0x01) != (b.options & 0x01)) d |= SEG_DIFFERS_SEL;
for (uint8_t i = 0; i < NUM_COLORS; i++)
{
if (colors[i] != b.colors[i]) d |= SEG_DIFFERS_COL;
@ -618,6 +582,23 @@ uint8_t WS2812FX::Segment::getLightCapabilities() {
return capabilities;
}
//used for JSON API info.leds.rgbw. Little practical use, deprecate with info.leds.rgbw.
//returns if there is an RGBW bus (supports RGB and White, not only white)
//not influenced by auto-white mode, also true if white slider does not affect output white channel
bool WS2812FX::hasRGBWBus(void) {
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
Bus *bus = busses.getBus(b);
if (bus == nullptr || bus->getLength()==0) break;
switch (bus->getType()) {
case TYPE_SK6812_RGBW:
case TYPE_TM1814:
case TYPE_ANALOG_4CH:
return true;
}
}
return false;
}
bool WS2812FX::hasCCTBus(void) {
if (cctFromRgb && !correctWB) return false;
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
@ -649,17 +630,8 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping,
delete[] seg.name;
seg.name = nullptr;
}
if (n == mainSegment) //if main segment is deleted, set first active as main segment
{
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isActive()) {
mainSegment = i;
return;
}
}
mainSegment = 0; //should not happen (always at least one active segment)
}
//if main segment is deleted, set first selected/active as main segment
if (n == _mainSegment) setMainSegmentId(0);
return;
}
if (i1 < _length) seg.start = i1;
@ -681,7 +653,7 @@ void WS2812FX::restartRuntime() {
void WS2812FX::resetSegments() {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) if (_segments[i].name) delete[] _segments[i].name;
mainSegment = 0;
_mainSegment = 0;
memset(_segments, 0, sizeof(_segments));
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
_segment_index = 0;
@ -746,6 +718,12 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
}
}
if (forceReset) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) {
setSegment(i, 0, 0);
}
}
if (getActiveSegmentsNum() < 2) {
setSegment(mainSeg, 0, _length);
}

View File

@ -44,7 +44,7 @@ void onAlexaChange(EspalexaDevice* dev)
if (bri == 0)
{
bri = briLast;
colorUpdated(CALL_MODE_ALEXA);
stateUpdated(CALL_MODE_ALEXA);
}
} else {
applyPreset(macroAlexaOn, CALL_MODE_ALEXA);
@ -58,7 +58,7 @@ void onAlexaChange(EspalexaDevice* dev)
{
briLast = bri;
bri = 0;
colorUpdated(CALL_MODE_ALEXA);
stateUpdated(CALL_MODE_ALEXA);
}
} else {
applyPreset(macroAlexaOff, CALL_MODE_ALEXA);
@ -67,7 +67,7 @@ void onAlexaChange(EspalexaDevice* dev)
} else if (m == EspalexaDeviceProperty::bri)
{
bri = espalexaDevice->getValue();
colorUpdated(CALL_MODE_ALEXA);
stateUpdated(CALL_MODE_ALEXA);
} else //color
{
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
@ -79,9 +79,7 @@ void onAlexaChange(EspalexaDevice* dev)
if (strip.hasCCTBus()) {
uint8_t segid = strip.getMainSegmentId();
WS2812FX::Segment& seg = strip.getSegment(segid);
uint8_t cctPrev = seg.cct;
seg.setCCT(k, segid);
if (seg.cct != cctPrev) effectChanged = true; //send UDP
col[0]= 0; col[1]= 0; col[2]= 0; col[3]= 255;
} else if (strip.hasWhiteChannel()) {
switch (ct) { //these values empirically look good on RGBW

View File

@ -46,27 +46,27 @@ void updateBlynk()
BLYNK_WRITE(V0)
{
bri = param.asInt();//bri
colorUpdated(CALL_MODE_BLYNK);
stateUpdated(CALL_MODE_BLYNK);
}
BLYNK_WRITE(V1)
{
blHue = param.asInt();//hue
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
colorHStoRGB(blHue*10,blSat,col);
colorUpdated(CALL_MODE_BLYNK);
}
BLYNK_WRITE(V2)
{
blSat = param.asInt();//sat
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
colorHStoRGB(blHue*10,blSat,col);
colorUpdated(CALL_MODE_BLYNK);
}
BLYNK_WRITE(V3)
{
bool on = (param.asInt()>0);
if (!on != !bri) {toggleOnOff(); colorUpdated(CALL_MODE_BLYNK);}
if (!on != !bri) {toggleOnOff(); stateUpdated(CALL_MODE_BLYNK);}
}
BLYNK_WRITE(V4)

View File

@ -16,7 +16,7 @@ void shortPressAction(uint8_t b)
{
if (!macroButton[b]) {
switch (b) {
case 0: toggleOnOff(); colorUpdated(CALL_MODE_BUTTON); break;
case 0: toggleOnOff(); stateUpdated(CALL_MODE_BUTTON); break;
case 1: ++effectCurrent %= strip.getModeCount(); effectChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
}
} else {
@ -35,8 +35,8 @@ void longPressAction(uint8_t b)
{
if (!macroLongPress[b]) {
switch (b) {
case 0: _setRandomColor(false,true); break;
case 1: bri += 8; colorUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
case 0: setRandomColor(col); colorUpdated(CALL_MODE_BUTTON); break;
case 1: bri += 8; stateUpdated(CALL_MODE_BUTTON); buttonPressedTime[b] = millis(); break; // repeatable action
}
} else {
applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
@ -55,7 +55,7 @@ void doublePressAction(uint8_t b)
if (!macroDoublePress[b]) {
switch (b) {
//case 0: toggleOnOff(); colorUpdated(CALL_MODE_BUTTON); break; //instant short press on button 0 if no macro set
case 1: ++effectPalette %= strip.getPaletteCount(); effectChanged = true; colorUpdated(CALL_MODE_BUTTON); break;
case 1: ++effectPalette %= strip.getPaletteCount(); colorUpdated(CALL_MODE_BUTTON); break;
}
} else {
applyPreset(macroDoublePress[b], CALL_MODE_BUTTON_PRESET);
@ -109,12 +109,12 @@ void handleSwitch(uint8_t b)
if (!buttonPressedBefore[b]) { // on -> off
if (macroButton[b]) applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET);
else { //turn on
if (!bri) {toggleOnOff(); colorUpdated(CALL_MODE_BUTTON);}
if (!bri) {toggleOnOff(); stateUpdated(CALL_MODE_BUTTON);}
}
} else { // off -> on
if (macroLongPress[b]) applyPreset(macroLongPress[b], CALL_MODE_BUTTON_PRESET);
else { //turn off
if (bri) {toggleOnOff(); colorUpdated(CALL_MODE_BUTTON);}
if (bri) {toggleOnOff(); stateUpdated(CALL_MODE_BUTTON);}
}
}
@ -161,36 +161,17 @@ void handleAnalog(uint8_t b)
} else if (macroDoublePress[b] == 249) {
// effect speed
effectSpeed = aRead;
effectChanged = true;
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isSelected()) continue;
seg.speed = effectSpeed;
}
} else if (macroDoublePress[b] == 248) {
// effect intensity
effectIntensity = aRead;
effectChanged = true;
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isSelected()) continue;
seg.intensity = effectIntensity;
}
} else if (macroDoublePress[b] == 247) {
// selected palette
effectPalette = map(aRead, 0, 252, 0, strip.getPaletteCount()-1);
effectChanged = true;
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isSelected()) continue;
seg.palette = effectPalette;
}
} else if (macroDoublePress[b] == 200) {
// primary color, hue, full saturation
colorHStoRGB(aRead*256,255,col);
} else {
// otherwise use "double press" for segment selection
//uint8_t mainSeg = strip.getMainSegmentId();
WS2812FX::Segment& seg = strip.getSegment(macroDoublePress[b]);
if (aRead == 0) {
seg.setOption(SEG_OPTION_ON, 0); // off
@ -263,8 +244,8 @@ void handleButton()
} else if (b == 0 && dur > WLED_LONG_AP) { //long press on button 0 (when released)
WLED::instance().initAP(true);
} else if (!buttonLongPressed[b]) { //short press
//NOTE: this interferes with double click handling in usermods so it is commented out
if (b == 0 && !macroDoublePress[b]) { //don't wait for double press on button 0 if no double press macro set
//NOTE: this interferes with double click handling in usermods so usermod needs to implement full button handling
if (b != 1 && !macroDoublePress[b]) { //don't wait for double press on buttons without a default action if no double press macro set
shortPressAction(b);
} else { //double press if less than 350 ms between current press and previous short press release (buttonWaitTime!=0)
if (doublePress) {

View File

@ -265,6 +265,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
CJSON(receiveNotificationEffects, if_sync_recv["fx"]);
CJSON(receiveGroups, if_sync_recv["grp"]);
CJSON(receiveSegmentOptions, if_sync_recv["seg"]);
CJSON(receiveSegmentBounds, if_sync_recv["sb"]);
//! following line might be a problem if called after boot
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects || receiveSegmentOptions);
@ -671,9 +672,10 @@ void serializeConfig() {
JsonObject if_sync_recv = if_sync.createNestedObject("recv");
if_sync_recv["bri"] = receiveNotificationBrightness;
if_sync_recv["col"] = receiveNotificationColor;
if_sync_recv["fx"] = receiveNotificationEffects;
if_sync_recv["fx"] = receiveNotificationEffects;
if_sync_recv["grp"] = receiveGroups;
if_sync_recv["seg"] = receiveSegmentOptions;
if_sync_recv["sb"] = receiveSegmentBounds;
JsonObject if_sync_send = if_sync.createNestedObject("send");
if_sync_send[F("dir")] = notifyDirect;

View File

@ -4,6 +4,12 @@
* Color conversion methods
*/
void setRandomColor(byte* rgb)
{
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
colorHStoRGB(lastRandomIndex*256,255,rgb);
}
//relatively change white brightness, minumum A=5
void relativeChangeWhite(int8_t amount, byte lowerBoundary)
{

View File

@ -226,6 +226,7 @@
#define SEG_DIFFERS_FX 0x08
#define SEG_DIFFERS_BOUNDS 0x10
#define SEG_DIFFERS_GSO 0x20
#define SEG_DIFFERS_SEL 0x80
//Playlist option byte
#define PL_OPTION_SHUFFLE 0x01
@ -340,4 +341,6 @@
#define DEFAULT_LED_COUNT 30
#endif
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
#endif

View File

@ -425,6 +425,10 @@ button {
overflow: auto;
}
.modal button:hover {
background-color: var(--c-4);
}
#info, #nodes {
z-index: 3;
}

View File

@ -188,8 +188,6 @@ function onLoad()
var sett = localStorage.getItem('wledUiCfg');
if (sett) cfg = mergeDeep(cfg, JSON.parse(sett));
makeWS();
resetPUtil();
applyCfg();
@ -206,7 +204,7 @@ function onLoad()
//TODO: do some parsing first
})
.catch((e)=>{
console.log("holidays.json does not contain array of holidays. Defaults loaded.");
console.log("No array of holidays in holidays.json. Defaults loaded.");
})
.finally(()=>{
loadBg(cfg.theme.bg.url);
@ -228,7 +226,7 @@ function onLoad()
loadFXData();
setTimeout(()=>{ //ESP8266 can't handle quick requests
loadPresets(()=>{
requestJson();
requestJson(); // will create WS
});
},100);
});
@ -276,14 +274,9 @@ function showToast(text, error = false)
if (error) console.log(text);
}
function showErrorToast()
{
if (ws && ws.readyState === WebSocket.OPEN) {
// if we received a timeout force WS reconnect
ws.close();
ws = null;
if (lastinfo.ws > -1) setTimeout(makeWS,500);
}
function showErrorToast() {
// if we received a timeout force WS reconnect
setTimeout(makeWS,500);
showToast('Connection to light failed!', true);
}
@ -1081,13 +1074,14 @@ function cmpP(a, b)
}
function makeWS() {
if (ws) return;
if (ws) { ws.close(); ws=null; }
if (lastinfo.ws < 0) return;
ws = new WebSocket('ws://'+(loc?locip:window.location.hostname)+'/ws');
ws.binaryType = "arraybuffer";
ws.onmessage = (e)=>{
if (e.data instanceof ArrayBuffer) return; //liveview packet
var json = JSON.parse(e.data);
if (json.leds) return; //liveview packet
if (json.leds) return; //JSON liveview packet
clearTimeout(jsonTimeout);
jsonTimeout = null;
lastUpdate = new Date();
@ -1108,8 +1102,7 @@ function makeWS() {
};
ws.onclose = (e)=>{
gId('connind').style.backgroundColor = "var(--c-r)";
ws = null;
if (lastinfo.ws > -1) setTimeout(makeWS,500); //retry WS connection
setTimeout(makeWS,500); //retry WS connection
}
ws.onopen = (e)=>{
//ws.send("{'v':true}"); //unnecessary (https://github.com/Aircoookie/WLED/blob/master/wled00/ws.cpp#L18)
@ -1398,6 +1391,7 @@ function requestJson(command=null)
}
var s = json.state ? json.state : json;
readState(s);
makeWS();
reqsLegal = true;
})
.catch((e)=>{

View File

@ -92,7 +92,7 @@ UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required
</tr>
</table><br>
Receive: <nowrap><input type="checkbox" name="RB">Brightness,</nowrap> <nowrap><input type="checkbox" name="RC">Color,</nowrap> <nowrap>and <input type="checkbox" name="RX">Effects</nowrap><br>
<input type="checkbox" name="SO">Segment options<br>
<input type="checkbox" name="SO"> Segment options, <input type="checkbox" name="SG"> bounds<br>
Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press or IR: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>

View File

@ -73,6 +73,8 @@ bool colorFromHexString(byte* rgb, const char* in);
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
uint16_t approximateKelvinFromRGB(uint32_t rgb);
void setRandomColor(byte* rgb);
//dmx.cpp
void initDMX();
void handleDMX();
@ -143,9 +145,10 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient = 0);
void setValuesFromMainSeg();
void resetTimebase();
void toggleOnOff();
void setAllLeds();
void setLedsStandard();
void colorUpdated(int callMode);
void applyBri();
void applyFinalBri();
void colorUpdated(byte callMode);
void stateUpdated(byte callMode);
void updateInterfaces(uint8_t callMode);
void handleTransitions();
void handleNightlight();
@ -276,7 +279,6 @@ bool oappendi(int i); // append new number to temp buffer efficiently
void sappend(char stype, const char* key, int val);
void sappends(char stype, const char* key, char* val);
void prepareHostname(char* hostname);
void _setRandomColor(bool _sec,bool fromButton=false);
bool isAsterisksOnly(const char* str, byte maxLen);
bool requestJSONBufferLock(uint8_t module=255);
void releaseJSONBufferLock();

View File

@ -902,183 +902,184 @@ const uint8_t PAGE_settings_ui[] PROGMEM = {
// Autogenerated from wled00/data/settings_sync.htm, do not edit!!
const uint16_t PAGE_settings_sync_length = 2794;
const uint16_t PAGE_settings_sync_length = 2814;
const uint8_t PAGE_settings_sync[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x1a, 0x5b, 0x77, 0xda, 0x38,
0xf3, 0xdd, 0xbf, 0x42, 0xeb, 0x87, 0xdd, 0xb0, 0x25, 0x60, 0x20, 0xd0, 0x34, 0xc1, 0xee, 0x17,
0x42, 0x9a, 0xe4, 0x6c, 0xd3, 0x52, 0x48, 0xf7, 0xf2, 0xb4, 0x47, 0xd8, 0x02, 0x3b, 0xd8, 0x96,
0xd7, 0x92, 0x73, 0x39, 0x7b, 0xf6, 0xbf, 0x7f, 0x33, 0x92, 0x6d, 0xc0, 0x5c, 0xfb, 0x10, 0x23,
0x4b, 0x33, 0xa3, 0xd1, 0xdc, 0x47, 0x4e, 0xff, 0xa7, 0xe1, 0xd7, 0xeb, 0xc7, 0xbf, 0x46, 0x37,
0xc4, 0x97, 0x51, 0xe8, 0xf4, 0xf1, 0x49, 0x42, 0x1a, 0xcf, 0x6d, 0x93, 0xc5, 0x26, 0xbc, 0x33,
0xea, 0x39, 0xfd, 0x88, 0x49, 0x4a, 0x62, 0x1a, 0x31, 0xdb, 0x7c, 0x0e, 0xd8, 0x4b, 0xc2, 0x53,
0x69, 0x12, 0x97, 0xc7, 0x92, 0xc5, 0xd2, 0x36, 0x5f, 0x02, 0x4f, 0xfa, 0x76, 0xd7, 0xb2, 0x4c,
0xc7, 0xd0, 0xa0, 0x46, 0x65, 0xcd, 0x63, 0xcf, 0x81, 0xcb, 0x4e, 0xd5, 0x4b, 0x3d, 0x88, 0x03,
0x19, 0xd0, 0xf0, 0x54, 0xb8, 0x34, 0x64, 0x76, 0xab, 0x1e, 0xd1, 0xd7, 0x20, 0xca, 0xa2, 0xf2,
0x3d, 0x13, 0x2c, 0x55, 0x2f, 0x74, 0x0a, 0xef, 0x31, 0x37, 0x89, 0x51, 0xd9, 0x3a, 0x67, 0xc8,
0xf5, 0x69, 0x2a, 0x18, 0x6c, 0x92, 0xc9, 0xd9, 0xe9, 0x39, 0xcc, 0xca, 0x40, 0x86, 0xcc, 0x99,
0xbc, 0xc5, 0x2e, 0x99, 0x30, 0x29, 0x83, 0x78, 0x2e, 0xfa, 0x4d, 0x3d, 0xd9, 0x17, 0x6e, 0x1a,
0x24, 0xd2, 0x31, 0x9e, 0x69, 0x4a, 0x3c, 0xdb, 0xe3, 0x6e, 0x16, 0x01, 0x83, 0x97, 0xb3, 0x2c,
0x76, 0x65, 0xc0, 0x63, 0x32, 0xbf, 0xf7, 0x4e, 0x58, 0xed, 0xdf, 0x94, 0xc9, 0x2c, 0x8d, 0x89,
0xd7, 0x98, 0x33, 0x79, 0x13, 0x32, 0x84, 0x19, 0xbc, 0xa9, 0xa5, 0xff, 0x4a, 0xd0, 0xbb, 0x93,
0xda, 0xbf, 0x2f, 0x41, 0xec, 0xf1, 0x97, 0x06, 0x4f, 0x58, 0x7c, 0x62, 0xfa, 0x52, 0x26, 0xe2,
0xa2, 0xd9, 0x5c, 0xc4, 0xbc, 0xf1, 0x12, 0x32, 0x44, 0x6e, 0x06, 0x20, 0x80, 0x74, 0x46, 0x5d,
0x26, 0x9a, 0x99, 0x97, 0x9c, 0xc6, 0x5c, 0x06, 0xb3, 0x80, 0xa5, 0x4d, 0x73, 0x85, 0xd0, 0xa0,
0x4a, 0xa8, 0x29, 0x72, 0xb6, 0xcd, 0xba, 0xf9, 0xb7, 0x60, 0xe1, 0x6c, 0x15, 0x9a, 0x7a, 0x4f,
0x00, 0xdf, 0x3b, 0xeb, 0x9e, 0xd9, 0xb6, 0xd7, 0x98, 0xcc, 0x1a, 0xc3, 0xfb, 0xc6, 0x33, 0x0d,
0x33, 0xf6, 0xf1, 0xa4, 0x55, 0xcc, 0x5c, 0xe9, 0x99, 0x9f, 0x7f, 0x3e, 0x59, 0x7b, 0xb7, 0xad,
0x5a, 0xbd, 0x80, 0xb9, 0xf9, 0xbe, 0x0e, 0x53, 0xbc, 0x03, 0x4c, 0xed, 0xa2, 0xdb, 0xed, 0x9d,
0x57, 0xa8, 0x03, 0x9c, 0x75, 0x88, 0x7c, 0xab, 0x56, 0xb7, 0x0e, 0x91, 0x6f, 0xd5, 0x56, 0xce,
0xf2, 0xe9, 0x1a, 0x8e, 0x32, 0xe3, 0xe9, 0xc9, 0x93, 0x6d, 0x5d, 0x3e, 0xf5, 0xcf, 0x2f, 0x9f,
0xde, 0xbd, 0xab, 0xa1, 0x0a, 0xcc, 0x5b, 0xf3, 0xdd, 0xc9, 0xd3, 0x3b, 0x00, 0x6e, 0xb8, 0x3e,
0x73, 0x17, 0xcc, 0xb3, 0xf5, 0xf4, 0xc4, 0xac, 0x69, 0x42, 0x8e, 0xf3, 0xf4, 0x73, 0xab, 0xae,
0x26, 0xc7, 0x3b, 0x60, 0xc7, 0x6b, 0xb0, 0xcb, 0x5d, 0x6f, 0x71, 0x57, 0x34, 0x00, 0x38, 0x6c,
0xdd, 0x83, 0x3f, 0x6a, 0xb7, 0x2e, 0xab, 0x5c, 0xb0, 0x77, 0xf6, 0x76, 0x46, 0x7e, 0xa5, 0x75,
0x2f, 0x5f, 0x1b, 0x6f, 0x59, 0xa3, 0xbf, 0xda, 0xed, 0xcb, 0x0a, 0xaf, 0x36, 0xab, 0x57, 0x38,
0xb2, 0xbd, 0x25, 0x3b, 0x93, 0x51, 0xc9, 0xce, 0x9a, 0xc4, 0x35, 0x95, 0xd7, 0x04, 0x70, 0x84,
0x7c, 0x0b, 0x59, 0xc3, 0x0b, 0x44, 0x12, 0xd2, 0x37, 0x9b, 0x39, 0xd6, 0x47, 0x33, 0xe6, 0x31,
0x33, 0x2f, 0xcc, 0x69, 0xc8, 0xdd, 0x85, 0x59, 0x87, 0xa9, 0x52, 0xd2, 0xa3, 0x62, 0xd3, 0x15,
0x41, 0x83, 0x1f, 0xfc, 0x4e, 0x43, 0xd8, 0x47, 0xbc, 0x04, 0xd2, 0xf5, 0x4f, 0x12, 0x74, 0x99,
0xfb, 0x58, 0xae, 0xa3, 0xd4, 0x6a, 0xff, 0xba, 0x54, 0x30, 0x82, 0xea, 0xbf, 0x58, 0xe3, 0xc5,
0xc6, 0xa9, 0xcb, 0x69, 0xca, 0xe8, 0xe2, 0x52, 0x81, 0xa0, 0xfd, 0x55, 0x40, 0x70, 0x6a, 0x15,
0xe4, 0xcc, 0x3a, 0xab, 0x52, 0xc1, 0xa9, 0xff, 0xf0, 0xbc, 0x75, 0xd4, 0xfc, 0x0a, 0x7b, 0xc0,
0xd9, 0x2d, 0xb0, 0x08, 0x0b, 0x05, 0xa7, 0xff, 0x19, 0xfd, 0x66, 0xee, 0xac, 0xb9, 0xd3, 0x12,
0x91, 0xba, 0xb6, 0x59, 0xb8, 0x46, 0xe3, 0x49, 0x7c, 0x4c, 0xec, 0x33, 0x70, 0xf7, 0x25, 0x18,
0x4a, 0xc9, 0xf9, 0x5f, 0x10, 0x61, 0x74, 0x20, 0x59, 0x1a, 0x9e, 0x98, 0x5a, 0x70, 0xae, 0x10,
0x66, 0xed, 0x12, 0x09, 0x2a, 0x88, 0x7e, 0x53, 0x87, 0xb3, 0x29, 0xf7, 0xde, 0x08, 0x8f, 0x43,
0x4e, 0x3d, 0xdb, 0x04, 0x16, 0x80, 0x16, 0x58, 0x41, 0x44, 0x02, 0x78, 0xc5, 0xc1, 0xdf, 0xc2,
0xcc, 0xa3, 0xdd, 0x64, 0x66, 0x12, 0x88, 0x35, 0x3e, 0x87, 0x95, 0x84, 0x0b, 0x88, 0x7a, 0x06,
0x8f, 0x45, 0x36, 0x8d, 0x02, 0x08, 0x3b, 0x68, 0x4e, 0x80, 0xea, 0x05, 0xcf, 0xc4, 0x0d, 0xa9,
0x10, 0xb6, 0x29, 0x79, 0x92, 0xf2, 0x97, 0xf5, 0x39, 0x9f, 0x85, 0xc9, 0x00, 0xa6, 0xa6, 0x99,
0x94, 0x70, 0x62, 0xf9, 0x96, 0x00, 0x5d, 0xfd, 0xa2, 0xa8, 0xb9, 0x61, 0xe0, 0x2e, 0x6c, 0xf3,
0x0e, 0x69, 0x7d, 0xec, 0x37, 0xf5, 0x0a, 0xb0, 0x0a, 0x24, 0x76, 0x20, 0x95, 0x38, 0x03, 0xc4,
0x19, 0x50, 0x77, 0x51, 0xa2, 0x19, 0xeb, 0x18, 0x9a, 0x53, 0xd3, 0x99, 0xd0, 0x67, 0xb6, 0x24,
0xed, 0xa7, 0x05, 0x79, 0xbf, 0xad, 0xa3, 0x25, 0xc8, 0x36, 0x4b, 0x40, 0x3a, 0x6d, 0x98, 0xea,
0x38, 0xc6, 0x1f, 0x9f, 0x6f, 0x86, 0x64, 0x90, 0x82, 0x78, 0x40, 0x9f, 0x12, 0xe6, 0x3b, 0xce,
0xf7, 0xe1, 0x88, 0x8c, 0x40, 0xba, 0x17, 0xa4, 0x1f, 0xc4, 0x49, 0x26, 0x73, 0xf9, 0x7c, 0x1f,
0x99, 0xf9, 0x56, 0x71, 0x16, 0x4d, 0x59, 0x0a, 0xd2, 0x0a, 0x62, 0xdb, 0x6c, 0xc1, 0x2f, 0x7d,
0xb5, 0xcd, 0x5e, 0xb7, 0xdb, 0xe9, 0xc2, 0x29, 0x73, 0x51, 0x78, 0x30, 0x4e, 0xd9, 0x3f, 0x59,
0x90, 0x32, 0xd4, 0x42, 0xea, 0xb4, 0x63, 0x6f, 0x2b, 0xd5, 0xf6, 0x2e, 0xaa, 0xc6, 0x2a, 0xd9,
0x5d, 0x54, 0xd5, 0xdf, 0x2a, 0x3d, 0x70, 0x48, 0xa5, 0x5b, 0xfc, 0x5d, 0xa7, 0x6b, 0x28, 0xc3,
0x00, 0x1a, 0xda, 0xc3, 0x2e, 0x94, 0x73, 0x39, 0xeb, 0xdc, 0x80, 0xf3, 0x6a, 0xec, 0xf1, 0x71,
0xd8, 0x7d, 0x89, 0x89, 0x8b, 0xe4, 0x6b, 0x11, 0x4d, 0xe7, 0x41, 0x7c, 0x61, 0x11, 0x9a, 0x49,
0x8e, 0x8b, 0xc0, 0x9b, 0xf4, 0x20, 0x79, 0x86, 0x22, 0xa1, 0x70, 0xa8, 0x0f, 0x4b, 0x32, 0x92,
0xbd, 0xca, 0x53, 0x1a, 0x06, 0xf3, 0xf8, 0xc2, 0x65, 0x98, 0x3e, 0x4c, 0xad, 0x9d, 0x79, 0xca,
0xb3, 0x04, 0x33, 0x19, 0x1c, 0xaf, 0xa9, 0xf0, 0x15, 0x0d, 0x47, 0xcf, 0xc0, 0x5f, 0xab, 0x1c,
0xb5, 0xd5, 0xc8, 0xc0, 0x61, 0xa7, 0x9c, 0x3c, 0x2b, 0x47, 0xdd, 0x72, 0xd4, 0x2b, 0x47, 0xef,
0xcb, 0xd1, 0xf9, 0xe6, 0x16, 0x13, 0x16, 0x7b, 0x17, 0x46, 0x09, 0x91, 0xcb, 0x45, 0x4b, 0x41,
0x85, 0xbe, 0x29, 0x7f, 0xcd, 0xa5, 0xd3, 0x2a, 0x7c, 0x06, 0x46, 0x4e, 0x15, 0xc3, 0xd8, 0x8a,
0xd2, 0x2e, 0x51, 0xda, 0x9b, 0x28, 0x5b, 0x31, 0x3a, 0x65, 0x31, 0x00, 0xc3, 0xe3, 0x50, 0xce,
0xca, 0x4d, 0xce, 0x8e, 0xe5, 0xab, 0x5b, 0xa2, 0x74, 0x8f, 0xdc, 0xa4, 0xb7, 0xe4, 0xab, 0x77,
0x24, 0xca, 0xfb, 0x72, 0x93, 0xf7, 0xc7, 0xf2, 0x75, 0x5e, 0xa2, 0x9c, 0x17, 0x28, 0xab, 0xca,
0x1a, 0x33, 0x97, 0x05, 0xcf, 0xec, 0xe2, 0x28, 0x62, 0xe3, 0x52, 0x5f, 0xe3, 0xd6, 0x71, 0x1c,
0x8f, 0xdb, 0xe5, 0x21, 0xc7, 0x47, 0xea, 0x6b, 0xdc, 0x29, 0x37, 0xe9, 0x1c, 0x79, 0xc8, 0x71,
0xa9, 0xaf, 0xf1, 0xd9, 0x91, 0x9b, 0x74, 0x97, 0x7c, 0x1d, 0xa9, 0xaf, 0x71, 0xaf, 0xdc, 0xa4,
0x77, 0x2c, 0x5f, 0xa5, 0xbe, 0xc6, 0xef, 0x8f, 0xdc, 0xe4, 0x7c, 0xc9, 0xd7, 0xba, 0xbe, 0x9a,
0x2a, 0x42, 0xa8, 0x38, 0x55, 0xea, 0x2c, 0xe6, 0x2f, 0x29, 0x4d, 0x76, 0xd1, 0x2b, 0xe8, 0x40,
0x22, 0x19, 0xa4, 0xc1, 0xdc, 0x97, 0x31, 0x13, 0xa2, 0xde, 0x6f, 0x16, 0x58, 0xfb, 0xb1, 0x73,
0xe4, 0x6b, 0xd3, 0xb9, 0xe6, 0x21, 0x4f, 0xeb, 0xc6, 0x06, 0x22, 0x85, 0x40, 0xbc, 0x1f, 0xf9,
0x4f, 0xd3, 0xb9, 0x99, 0xcd, 0x98, 0x2b, 0xc5, 0x12, 0xb9, 0x8c, 0xb3, 0xc6, 0x0e, 0xac, 0xc9,
0x57, 0x08, 0x61, 0x6c, 0x8e, 0x55, 0x34, 0xe1, 0x09, 0x66, 0x7c, 0x81, 0x48, 0x06, 0x86, 0x15,
0xa2, 0x4b, 0x62, 0x97, 0xaa, 0x69, 0x48, 0x6a, 0xc4, 0x83, 0x08, 0xee, 0x4a, 0x2c, 0xeb, 0xe3,
0x39, 0xbb, 0xd8, 0xcf, 0xcf, 0x64, 0x68, 0x3a, 0x7b, 0x48, 0xe5, 0x59, 0x30, 0x49, 0x41, 0x4c,
0x84, 0xa7, 0xe4, 0x7e, 0x7c, 0x88, 0xde, 0x60, 0x95, 0xde, 0x55, 0xc8, 0x5e, 0xe9, 0x3a, 0xd5,
0x43, 0xf8, 0x57, 0xab, 0xf8, 0x23, 0x3f, 0x08, 0x83, 0x44, 0x90, 0xbb, 0x8c, 0xe5, 0xc7, 0xf9,
0x31, 0x62, 0x77, 0xab, 0xc4, 0x1e, 0xa8, 0x9b, 0xf2, 0x1f, 0xc3, 0x7f, 0xd8, 0x2d, 0x1c, 0xf9,
0x02, 0x9d, 0xd8, 0x21, 0xfc, 0xb6, 0x99, 0x2b, 0xd7, 0x31, 0xc6, 0x6c, 0xca, 0xb9, 0x2c, 0x13,
0x2c, 0x91, 0x9c, 0xd0, 0x24, 0x09, 0xdf, 0xf2, 0x73, 0x89, 0x46, 0xbf, 0x19, 0xa8, 0xaa, 0xe1,
0x3e, 0x16, 0x92, 0xc6, 0x2e, 0x23, 0x9f, 0x83, 0xbc, 0x66, 0x30, 0x6e, 0x62, 0x95, 0x09, 0x83,
0x62, 0x25, 0x84, 0x95, 0x03, 0x5b, 0x7f, 0xf9, 0x9c, 0xb3, 0xfe, 0x40, 0x17, 0x8c, 0x48, 0x3f,
0x10, 0x4b, 0x74, 0x48, 0xb3, 0x2e, 0x7f, 0x66, 0x29, 0x12, 0x3d, 0x44, 0x06, 0xd5, 0x09, 0x2c,
0x8c, 0x19, 0x0d, 0x65, 0x10, 0x31, 0x43, 0x31, 0x94, 0x3b, 0x1b, 0xc1, 0x62, 0x26, 0xcd, 0x57,
0x0e, 0x10, 0x1a, 0xe7, 0x76, 0x56, 0x88, 0xe3, 0x0b, 0x93, 0x2f, 0x3c, 0x5d, 0x90, 0xe1, 0xc3,
0x9f, 0x44, 0xe1, 0xa9, 0xe3, 0xc3, 0xe2, 0x23, 0xa0, 0x03, 0x2d, 0x68, 0xda, 0xd0, 0x86, 0x35,
0xf2, 0xf0, 0x5e, 0x15, 0x6b, 0x4a, 0x50, 0x20, 0x55, 0x2c, 0x7f, 0x55, 0x13, 0x07, 0x24, 0xb5,
0x37, 0x10, 0x43, 0x97, 0xc7, 0x26, 0x56, 0xd9, 0xe0, 0x60, 0xad, 0x46, 0xa7, 0x45, 0x4e, 0xc4,
0xd5, 0xf5, 0x97, 0x5a, 0xbf, 0xa9, 0x41, 0x4a, 0xd0, 0x1c, 0x12, 0x8b, 0x6d, 0xd3, 0xb9, 0x4a,
0xe5, 0x29, 0xb0, 0xb2, 0x01, 0x54, 0xd0, 0xb3, 0x4c, 0xa2, 0x39, 0x81, 0x9e, 0xc8, 0x2c, 0x46,
0xe0, 0xfe, 0x99, 0x90, 0x3c, 0x22, 0x58, 0x26, 0x2f, 0x51, 0x9b, 0x7a, 0x5d, 0x1f, 0x11, 0x0b,
0x57, 0x0c, 0x5e, 0xd0, 0x7d, 0x38, 0xc6, 0x96, 0xd2, 0xec, 0xe6, 0xa8, 0x82, 0x6f, 0xf5, 0x54,
0xbb, 0xab, 0x3f, 0x5d, 0x84, 0x3e, 0x64, 0xa0, 0x07, 0xac, 0x33, 0x0f, 0x68, 0xe2, 0xa6, 0x34,
0x6a, 0x49, 0xb1, 0xca, 0x8f, 0x41, 0x93, 0xd0, 0xcb, 0x54, 0xf9, 0xfb, 0xbe, 0x95, 0x3f, 0xab,
0xe0, 0xaf, 0xf3, 0xe1, 0xc3, 0x87, 0x0a, 0x1b, 0x06, 0xe8, 0xb5, 0x62, 0xe5, 0xca, 0xa8, 0xc9,
0x35, 0x72, 0x40, 0x38, 0xd0, 0xee, 0x53, 0xe2, 0xa7, 0x6c, 0x66, 0x97, 0x9d, 0xfe, 0x3c, 0x90,
0x7e, 0x36, 0x6d, 0xb8, 0x3c, 0x6a, 0x7e, 0x66, 0xde, 0xa7, 0x57, 0xfd, 0x84, 0xb3, 0x02, 0x6f,
0x73, 0xbc, 0x92, 0xf8, 0x7b, 0x1a, 0xd2, 0x78, 0x61, 0x3a, 0x6a, 0xbe, 0xdf, 0xa4, 0xce, 0x4f,
0xb8, 0xd5, 0x64, 0x11, 0x24, 0x48, 0xf0, 0x94, 0xcf, 0x4e, 0x05, 0xec, 0xc5, 0xd0, 0xac, 0x13,
0x28, 0xe0, 0x99, 0x5c, 0xfa, 0xb4, 0xb1, 0xe3, 0xfc, 0x13, 0x7d, 0x7e, 0xb4, 0x3c, 0xa1, 0x44,
0x40, 0x3d, 0x0f, 0xe3, 0x5b, 0x45, 0x02, 0xc3, 0xab, 0x8d, 0x32, 0x75, 0x4d, 0x04, 0xdd, 0x96,
0x55, 0x11, 0x00, 0x52, 0x8c, 0xb8, 0xb7, 0x69, 0xbe, 0x0f, 0x66, 0xd5, 0xfa, 0xf0, 0x8a, 0x67,
0x18, 0x08, 0xf4, 0x40, 0x6f, 0x97, 0x85, 0x42, 0x39, 0x31, 0x81, 0x46, 0x0d, 0x1c, 0x7f, 0x7c,
0x3b, 0xd8, 0x05, 0x04, 0x11, 0xc6, 0xc8, 0xa1, 0x86, 0x7b, 0xc0, 0x3a, 0x45, 0xd6, 0xd9, 0x05,
0x00, 0xbe, 0xa0, 0x0c, 0x08, 0xf7, 0x32, 0x76, 0x01, 0x41, 0x55, 0x30, 0x0c, 0xa2, 0x88, 0xa5,
0xe4, 0x1d, 0x29, 0xa1, 0x77, 0x3a, 0x18, 0x70, 0x56, 0x02, 0xfd, 0xb1, 0xc3, 0x4d, 0x28, 0x31,
0xd6, 0x0d, 0x62, 0xc7, 0xd5, 0x0f, 0x43, 0x8f, 0x3e, 0xf5, 0xa2, 0xd7, 0x26, 0x28, 0xa5, 0x62,
0x1a, 0xda, 0xdb, 0x83, 0x78, 0xc6, 0xd1, 0x3e, 0x0c, 0x15, 0x44, 0x20, 0x20, 0x81, 0x79, 0x54,
0x6d, 0xfa, 0xf1, 0x80, 0xcf, 0x59, 0xd6, 0xaa, 0x4a, 0x49, 0xa4, 0x93, 0xec, 0x27, 0x9e, 0x82,
0x75, 0x01, 0x08, 0x99, 0x96, 0x25, 0xc3, 0x01, 0x1f, 0xfb, 0x54, 0x64, 0xc1, 0x5c, 0xc7, 0x65,
0x94, 0x24, 0x73, 0x1a, 0x45, 0x14, 0xba, 0x96, 0x14, 0x53, 0x34, 0xc8, 0xe3, 0x50, 0xd8, 0xbc,
0xcd, 0x09, 0x15, 0x01, 0x98, 0x60, 0x4b, 0xc9, 0x67, 0x33, 0xe8, 0x34, 0x2b, 0xa7, 0xfb, 0xe3,
0xeb, 0xd6, 0xd3, 0x9d, 0xb6, 0xbb, 0xdd, 0xfc, 0x80, 0x6a, 0x64, 0x2c, 0x4d, 0x16, 0x22, 0xb9,
0x4e, 0xd0, 0xbf, 0x73, 0xc8, 0x65, 0xe4, 0x4a, 0x88, 0x00, 0x33, 0x84, 0x4e, 0x3a, 0x37, 0x51,
0x16, 0x52, 0xc9, 0xf2, 0x14, 0xae, 0x2f, 0x1e, 0x0f, 0xb9, 0xd6, 0x55, 0x9e, 0x74, 0x34, 0x4e,
0x10, 0x3f, 0x73, 0x9d, 0x2d, 0xd5, 0x72, 0xe5, 0xa4, 0xd8, 0xa4, 0x95, 0xf5, 0xd8, 0xd5, 0xbd,
0x62, 0x31, 0x64, 0xf1, 0x5c, 0xfa, 0x60, 0xad, 0x6d, 0x9d, 0x75, 0x06, 0xe1, 0x5b, 0xbc, 0x50,
0xdc, 0xf4, 0xa7, 0x8e, 0xa1, 0xde, 0xea, 0xe4, 0xe1, 0xdb, 0xe3, 0x23, 0xc1, 0x3a, 0x0b, 0x8b,
0x02, 0x81, 0x7d, 0x1d, 0x0d, 0x43, 0xbc, 0x44, 0x8d, 0xd1, 0xe3, 0x20, 0xad, 0x02, 0x61, 0x96,
0xc6, 0x34, 0x24, 0x3e, 0x17, 0x52, 0xa8, 0x78, 0x61, 0x3c, 0x62, 0x02, 0x8c, 0xe8, 0x1b, 0x09,
0x22, 0x08, 0x13, 0x00, 0xe6, 0xa3, 0x4e, 0x44, 0x02, 0x99, 0x1c, 0xc2, 0x5f, 0xac, 0xaa, 0x9b,
0x99, 0x9a, 0xbd, 0x99, 0x8c, 0xce, 0xdb, 0xbd, 0x1e, 0x44, 0xae, 0xa9, 0x53, 0xa8, 0x9f, 0x4c,
0x99, 0xc0, 0xa0, 0x26, 0xc0, 0x9c, 0x45, 0x1d, 0x6f, 0x3c, 0xde, 0x48, 0x26, 0x18, 0x0c, 0x58,
0x8e, 0x06, 0x2f, 0x82, 0xa5, 0x28, 0x23, 0x41, 0x28, 0x44, 0x14, 0x82, 0xba, 0x6a, 0x28, 0xfc,
0x13, 0x50, 0x1c, 0xf2, 0x23, 0x61, 0xa3, 0xf0, 0xad, 0x5e, 0x72, 0x4a, 0x01, 0x03, 0xc6, 0x1e,
0xee, 0x88, 0x6c, 0x03, 0x95, 0x48, 0x9d, 0x0b, 0x29, 0x23, 0x27, 0x98, 0x5d, 0xf1, 0x7c, 0xb5,
0x22, 0x6f, 0xde, 0x71, 0x0c, 0xee, 0xc6, 0x16, 0x31, 0x6a, 0x29, 0x0e, 0xee, 0x36, 0xa4, 0xb8,
0xed, 0x56, 0x60, 0x30, 0x32, 0x0b, 0x05, 0x1e, 0x91, 0x7b, 0xce, 0xad, 0xd5, 0x0b, 0x02, 0x1d,
0xe7, 0x94, 0x31, 0x90, 0xab, 0x4c, 0xfa, 0xc0, 0xf8, 0x82, 0xc5, 0x4b, 0xa6, 0xf2, 0x1d, 0x7e,
0x5b, 0x67, 0xa4, 0x53, 0x96, 0x41, 0xd7, 0x21, 0xa3, 0xa9, 0x3a, 0x9d, 0x42, 0x24, 0xb3, 0x80,
0x85, 0xaa, 0x16, 0xf2, 0xb4, 0xa3, 0x34, 0x88, 0xaa, 0x03, 0x8e, 0x0d, 0x0b, 0x53, 0x34, 0x89,
0x2d, 0x21, 0x61, 0x82, 0xf7, 0x30, 0x65, 0x48, 0x50, 0x77, 0x31, 0x68, 0x36, 0xda, 0xb0, 0x75,
0x31, 0x85, 0xef, 0x07, 0x9c, 0xef, 0xe1, 0x9b, 0xe6, 0x7b, 0x90, 0x02, 0xaf, 0x69, 0xd5, 0xf8,
0x57, 0x25, 0xff, 0x30, 0x39, 0x4a, 0xf2, 0x0f, 0xdf, 0x46, 0x5f, 0xc7, 0x8f, 0xdb, 0xd3, 0x4a,
0x45, 0xfa, 0x15, 0x91, 0xa3, 0xfd, 0x3f, 0xfa, 0x9a, 0x6b, 0xe2, 0x82, 0xf7, 0x42, 0x27, 0x10,
0xd0, 0x10, 0x8c, 0x2d, 0x45, 0xcb, 0xc3, 0xb6, 0x00, 0xb2, 0x38, 0x98, 0x0f, 0xe4, 0x73, 0x30,
0xab, 0x0c, 0x2b, 0xcc, 0xdc, 0xd0, 0xc0, 0xff, 0xb4, 0x21, 0x7e, 0x61, 0x08, 0x52, 0x58, 0x97,
0xa2, 0x94, 0xc0, 0x26, 0x50, 0x86, 0x79, 0x64, 0xc6, 0x11, 0x99, 0xc3, 0x42, 0x5a, 0x18, 0xf2,
0x4f, 0x85, 0x07, 0x7c, 0x17, 0x68, 0xbe, 0x11, 0xdb, 0x2b, 0x80, 0x6f, 0xdf, 0x27, 0x37, 0xe3,
0x35, 0x21, 0x9c, 0x59, 0x9a, 0xf5, 0x51, 0xbe, 0x47, 0x45, 0xd8, 0xc5, 0xd6, 0x65, 0x0c, 0x00,
0xe1, 0x5c, 0x4d, 0xd6, 0xe5, 0xd8, 0x3b, 0xd3, 0x24, 0xae, 0xc3, 0x00, 0x8f, 0x78, 0x3f, 0xdc,
0x1a, 0x43, 0x0a, 0xf4, 0xeb, 0xfb, 0xa1, 0xbe, 0xd8, 0xaa, 0x72, 0x90, 0xdb, 0xeb, 0x23, 0x4f,
0x02, 0x77, 0x1f, 0x85, 0xe1, 0x86, 0x12, 0x55, 0x32, 0xb9, 0xc5, 0x6b, 0xa3, 0xc3, 0xd8, 0xb7,
0x9b, 0x21, 0x0c, 0xa5, 0x3e, 0xca, 0xa6, 0x50, 0xae, 0xfb, 0xd5, 0x66, 0xea, 0x80, 0xe9, 0x0d,
0x1e, 0x7e, 0xa0, 0x73, 0xf8, 0x31, 0x9f, 0x89, 0xfe, 0x91, 0x72, 0x8b, 0xcb, 0x28, 0x7b, 0x58,
0xf3, 0x98, 0x95, 0xe6, 0x4b, 0xc7, 0x60, 0xe0, 0xe5, 0x2f, 0x9e, 0x11, 0x97, 0xa2, 0xdf, 0x42,
0xa0, 0x42, 0x33, 0x82, 0x94, 0xe8, 0x41, 0x57, 0x76, 0x3f, 0x52, 0xa1, 0x0b, 0x67, 0x42, 0xcc,
0x91, 0x44, 0x1b, 0x37, 0x10, 0x54, 0x73, 0xbf, 0x5c, 0x4d, 0x21, 0x1d, 0xff, 0x82, 0x11, 0x4f,
0xe5, 0x83, 0x3c, 0xd6, 0xfa, 0x10, 0xc1, 0xe1, 0x28, 0x0d, 0xa3, 0x28, 0xfe, 0x47, 0x1c, 0x42,
0x39, 0xc6, 0x75, 0x4d, 0x64, 0xcd, 0x79, 0xee, 0x3e, 0xef, 0xcd, 0xde, 0x50, 0x8e, 0x3a, 0x04,
0x2d, 0xfc, 0xad, 0x12, 0x8c, 0xee, 0xee, 0xb7, 0xe3, 0x59, 0xd6, 0x5a, 0xde, 0xc7, 0x74, 0x7f,
0x28, 0xbf, 0xdd, 0x8d, 0xb4, 0x56, 0xc0, 0x13, 0xe3, 0x3a, 0x28, 0x44, 0x77, 0x41, 0x7b, 0x15,
0x79, 0x07, 0x9d, 0xbb, 0x41, 0xbe, 0xc6, 0xcd, 0xaf, 0xb3, 0x59, 0xfd, 0x00, 0x28, 0x14, 0x0d,
0x64, 0xe5, 0x56, 0x82, 0xac, 0x5c, 0x26, 0xec, 0x62, 0xe8, 0x1a, 0x50, 0xd4, 0x5d, 0x84, 0xca,
0x0f, 0x20, 0xb8, 0x41, 0xa1, 0x8f, 0x8b, 0x8d, 0xdb, 0xdb, 0x3b, 0x6b, 0x23, 0xee, 0xe7, 0x51,
0x46, 0x54, 0xaa, 0x7b, 0x2c, 0x14, 0x1c, 0xd2, 0xa8, 0xc8, 0xbf, 0xb5, 0x11, 0xb8, 0x7e, 0x08,
0x7d, 0xe3, 0x2e, 0x7a, 0x13, 0xdb, 0xd8, 0x83, 0xde, 0x39, 0x8c, 0xbe, 0xc4, 0x2e, 0x42, 0xe6,
0x48, 0xdd, 0x5b, 0xa0, 0xa9, 0x25, 0x99, 0xf0, 0xc3, 0x20, 0x5e, 0x14, 0x4e, 0xc8, 0xe3, 0x15,
0xf3, 0x05, 0x51, 0xcf, 0xc0, 0x3f, 0x60, 0x06, 0x72, 0xb7, 0xa0, 0xcf, 0x79, 0xc3, 0x9c, 0xd0,
0xf9, 0x32, 0x0a, 0x1a, 0x27, 0x2f, 0xbe, 0x4a, 0x58, 0x29, 0x94, 0x02, 0x45, 0x68, 0x8d, 0xe7,
0xb5, 0x42, 0xf0, 0x50, 0x39, 0xc9, 0x0c, 0x2d, 0x08, 0xaf, 0xa3, 0x4b, 0xe6, 0x82, 0x04, 0x4b,
0x66, 0x5d, 0xe7, 0x6b, 0x67, 0x00, 0xba, 0xd3, 0x2c, 0x08, 0x3d, 0xfc, 0x98, 0x02, 0x90, 0xca,
0xd5, 0x26, 0x2c, 0x85, 0x60, 0xae, 0x9c, 0x6c, 0x40, 0x33, 0x8f, 0xa4, 0x50, 0x78, 0x55, 0x9b,
0x88, 0xc1, 0x70, 0xa3, 0x89, 0x68, 0xb5, 0xba, 0x10, 0x65, 0xf0, 0x69, 0x59, 0x3b, 0x6b, 0xf6,
0x76, 0xc7, 0x82, 0x28, 0x8a, 0x4f, 0xcb, 0xda, 0x59, 0xfc, 0xf7, 0x2c, 0xe8, 0x9a, 0xf1, 0xb9,
0x87, 0x90, 0xf6, 0x12, 0x7c, 0xee, 0x26, 0xd4, 0x7d, 0xdf, 0x43, 0x18, 0x78, 0xee, 0x21, 0xf4,
0xa1, 0xdd, 0x82, 0xde, 0x00, 0x9f, 0xbb, 0x09, 0xb5, 0x2c, 0xb5, 0x9b, 0xfa, 0xd9, 0x43, 0xaa,
0xa5, 0x99, 0x6a, 0x55, 0xb9, 0x5a, 0xeb, 0x31, 0x20, 0x6c, 0xfd, 0xc6, 0x58, 0x82, 0x75, 0x99,
0x96, 0x15, 0x46, 0x50, 0x4c, 0x83, 0xf7, 0x51, 0x92, 0xf2, 0xe7, 0x06, 0x99, 0x70, 0xa8, 0xab,
0xa7, 0x9c, 0xa6, 0x9e, 0xae, 0x11, 0x21, 0x0f, 0x12, 0x91, 0x25, 0xea, 0x23, 0x98, 0x0f, 0xee,
0xa8, 0xf4, 0x51, 0x5c, 0xd0, 0xa4, 0xd5, 0x6f, 0x43, 0x47, 0x7c, 0x4d, 0xda, 0xfd, 0x31, 0xc9,
0x58, 0xf9, 0x50, 0x85, 0x5f, 0xcc, 0xe0, 0x07, 0x3f, 0xaa, 0xe1, 0x17, 0x36, 0xfc, 0x37, 0x82,
0xff, 0x03, 0x5c, 0xb2, 0xe5, 0xf2, 0x56, 0x20, 0x00, 0x00
0xf3, 0xdd, 0xbf, 0x42, 0xeb, 0x87, 0x6e, 0xd8, 0x12, 0x30, 0x10, 0x68, 0x4a, 0xb0, 0xfb, 0x85,
0x90, 0x26, 0x39, 0xdb, 0x34, 0x14, 0xd2, 0xed, 0xee, 0xd3, 0x1e, 0x61, 0x0b, 0x70, 0xb0, 0x2d,
0xaf, 0x25, 0xe7, 0x72, 0xf6, 0xec, 0x7f, 0xff, 0x66, 0x24, 0xdb, 0x80, 0xb9, 0xf6, 0x21, 0x46,
0x96, 0x66, 0x46, 0xa3, 0xb9, 0x8f, 0x9c, 0xde, 0x2f, 0x83, 0x87, 0xab, 0xc7, 0xbf, 0x86, 0xd7,
0x64, 0x2e, 0xc3, 0xc0, 0xe9, 0xe1, 0x93, 0x04, 0x34, 0x9a, 0xd9, 0x26, 0x8b, 0x4c, 0x78, 0x67,
0xd4, 0x73, 0x7a, 0x21, 0x93, 0x94, 0x44, 0x34, 0x64, 0xb6, 0xf9, 0xec, 0xb3, 0x97, 0x98, 0x27,
0xd2, 0x24, 0x2e, 0x8f, 0x24, 0x8b, 0xa4, 0x6d, 0xbe, 0xf8, 0x9e, 0x9c, 0xdb, 0x6d, 0xcb, 0x32,
0x1d, 0x43, 0x83, 0x1a, 0xa5, 0x35, 0x8f, 0x3d, 0xfb, 0x2e, 0x3b, 0x55, 0x2f, 0x55, 0x3f, 0xf2,
0xa5, 0x4f, 0x83, 0x53, 0xe1, 0xd2, 0x80, 0xd9, 0x8d, 0x6a, 0x48, 0x5f, 0xfd, 0x30, 0x0d, 0x8b,
0xf7, 0x54, 0xb0, 0x44, 0xbd, 0xd0, 0x09, 0xbc, 0x47, 0xdc, 0x24, 0x46, 0x69, 0xeb, 0x8c, 0x21,
0x77, 0x4e, 0x13, 0xc1, 0x60, 0x93, 0x54, 0x4e, 0x4f, 0xcf, 0x61, 0x56, 0xfa, 0x32, 0x60, 0xce,
0xf8, 0x2d, 0x72, 0xc9, 0x98, 0x49, 0xe9, 0x47, 0x33, 0xd1, 0xab, 0xeb, 0xc9, 0x9e, 0x70, 0x13,
0x3f, 0x96, 0x8e, 0xf1, 0x4c, 0x13, 0xe2, 0xd9, 0x1e, 0x77, 0xd3, 0x10, 0x18, 0xbc, 0x98, 0xa6,
0x91, 0x2b, 0x7d, 0x1e, 0x91, 0xd9, 0x9d, 0x77, 0xc2, 0x2a, 0xff, 0x26, 0x4c, 0xa6, 0x49, 0x44,
0xbc, 0xda, 0x8c, 0xc9, 0xeb, 0x80, 0x21, 0x4c, 0xff, 0x4d, 0x2d, 0xfd, 0x57, 0x80, 0xde, 0x9e,
0x54, 0xfe, 0x7d, 0xf1, 0x23, 0x8f, 0xbf, 0xd4, 0x78, 0xcc, 0xa2, 0x13, 0x73, 0x2e, 0x65, 0x2c,
0xba, 0xf5, 0xfa, 0x22, 0xe2, 0xb5, 0x97, 0x80, 0x21, 0x72, 0xdd, 0x07, 0x01, 0x24, 0x53, 0xea,
0x32, 0x51, 0x4f, 0xbd, 0xf8, 0x34, 0xe2, 0xd2, 0x9f, 0xfa, 0x2c, 0xa9, 0x9b, 0x2b, 0x84, 0xfa,
0x65, 0x42, 0x75, 0x91, 0xb1, 0x6d, 0x56, 0xcd, 0xbf, 0x05, 0x0b, 0xa6, 0xab, 0xd0, 0xd4, 0x7b,
0x02, 0xf8, 0xce, 0x59, 0xfb, 0xcc, 0xb6, 0xbd, 0xda, 0x78, 0x5a, 0x1b, 0xdc, 0xd5, 0x9e, 0x69,
0x90, 0xb2, 0x4f, 0x27, 0x8d, 0x7c, 0xe6, 0x52, 0xcf, 0xbc, 0x7b, 0x77, 0xb2, 0xf6, 0x6e, 0x5b,
0x95, 0x6a, 0x0e, 0x73, 0xfd, 0x7d, 0x1d, 0x26, 0x7f, 0x07, 0x98, 0x4a, 0xb7, 0xdd, 0xee, 0x9c,
0x97, 0xa8, 0x03, 0x9c, 0x75, 0x88, 0x7c, 0xa3, 0x52, 0xb5, 0x0e, 0x91, 0x6f, 0x54, 0x56, 0xce,
0xf2, 0xf9, 0x0a, 0x8e, 0x32, 0xe5, 0xc9, 0xc9, 0x93, 0x6d, 0x5d, 0x3c, 0xf5, 0xce, 0x2f, 0x9e,
0xde, 0xbf, 0xaf, 0xa0, 0x0a, 0xcc, 0x1b, 0xf3, 0xfd, 0xc9, 0xd3, 0x7b, 0x00, 0xae, 0xb9, 0x73,
0xe6, 0x2e, 0x98, 0x67, 0xeb, 0xe9, 0xb1, 0x59, 0xd1, 0x84, 0x1c, 0xe7, 0xe9, 0x5d, 0xa3, 0xaa,
0x26, 0x47, 0x3b, 0x60, 0x47, 0x6b, 0xb0, 0xcb, 0x5d, 0x6f, 0x70, 0x57, 0x34, 0x00, 0x38, 0x6c,
0xd5, 0x83, 0x3f, 0x6a, 0x37, 0x2e, 0xca, 0x5c, 0xb0, 0xf7, 0xf6, 0x76, 0x46, 0x7e, 0xa3, 0x55,
0x2f, 0x5b, 0x1b, 0x6d, 0x59, 0xa3, 0xbf, 0xd9, 0xcd, 0x8b, 0x12, 0xaf, 0x36, 0xab, 0x96, 0x38,
0xb2, 0xbd, 0x25, 0x3b, 0xe3, 0x61, 0xc1, 0xce, 0x9a, 0xc4, 0x35, 0x95, 0xd7, 0x18, 0x70, 0x84,
0x7c, 0x0b, 0x58, 0xcd, 0xf3, 0x45, 0x1c, 0xd0, 0x37, 0x9b, 0x39, 0xd6, 0x27, 0x33, 0xe2, 0x11,
0x33, 0xbb, 0xe6, 0x24, 0xe0, 0xee, 0xc2, 0xac, 0xc2, 0x54, 0x21, 0xe9, 0x61, 0xbe, 0xe9, 0x8a,
0xa0, 0xc1, 0x0f, 0xfe, 0xa0, 0x01, 0xec, 0x23, 0x5e, 0x7c, 0xe9, 0xce, 0x4f, 0x62, 0x74, 0x99,
0xbb, 0x48, 0xae, 0xa3, 0x54, 0x2a, 0xff, 0xba, 0x54, 0x30, 0x82, 0xea, 0xef, 0xae, 0xf1, 0x62,
0xe3, 0xd4, 0xc5, 0x24, 0x61, 0x74, 0x71, 0xa1, 0x40, 0xd0, 0xfe, 0x4a, 0x20, 0x38, 0xb5, 0x0a,
0x72, 0x66, 0x9d, 0x95, 0xa9, 0xe0, 0xd4, 0x7f, 0x78, 0xde, 0x2a, 0x6a, 0x7e, 0x85, 0x3d, 0xe0,
0xec, 0x06, 0x58, 0x84, 0x85, 0x9c, 0xd3, 0xff, 0x8c, 0x5e, 0x3d, 0x73, 0xd6, 0xcc, 0x69, 0x89,
0x48, 0x5c, 0xdb, 0xcc, 0x5d, 0xa3, 0xf6, 0x24, 0x3e, 0xc5, 0xf6, 0x19, 0xb8, 0xfb, 0x12, 0x0c,
0xa5, 0xe4, 0xfc, 0xcf, 0x0f, 0x31, 0x3a, 0x90, 0x34, 0x09, 0x4e, 0x4c, 0x2d, 0x38, 0x57, 0x08,
0xb3, 0x72, 0x81, 0x04, 0x15, 0x44, 0xaf, 0xae, 0xc3, 0xd9, 0x84, 0x7b, 0x6f, 0x84, 0x47, 0x01,
0xa7, 0x9e, 0x6d, 0x02, 0x0b, 0x40, 0x0b, 0xac, 0x20, 0x24, 0x3e, 0xbc, 0xe2, 0xe0, 0x6f, 0x61,
0x66, 0xd1, 0x6e, 0x3c, 0x35, 0x09, 0xc4, 0x9a, 0x39, 0x87, 0x95, 0x98, 0x0b, 0x88, 0x7a, 0x06,
0x8f, 0x44, 0x3a, 0x09, 0x7d, 0x08, 0x3b, 0x68, 0x4e, 0x80, 0xea, 0xf9, 0xcf, 0xc4, 0x0d, 0xa8,
0x10, 0xb6, 0x29, 0x79, 0x9c, 0xf0, 0x97, 0xf5, 0xb9, 0x39, 0x0b, 0xe2, 0x3e, 0x4c, 0x4d, 0x52,
0x29, 0xe1, 0xc4, 0xf2, 0x2d, 0x06, 0xba, 0xfa, 0x45, 0x51, 0x73, 0x03, 0xdf, 0x5d, 0xd8, 0xe6,
0x2d, 0xd2, 0xfa, 0xd4, 0xab, 0xeb, 0x15, 0x60, 0x15, 0x48, 0xec, 0x40, 0x2a, 0x70, 0xfa, 0x88,
0xd3, 0xa7, 0xee, 0xa2, 0x40, 0x33, 0xd6, 0x31, 0x34, 0xa7, 0xa6, 0x33, 0xa6, 0xcf, 0x6c, 0x49,
0x7a, 0x9e, 0xe4, 0xe4, 0xe7, 0x4d, 0x1d, 0x2d, 0x41, 0xb6, 0x69, 0x0c, 0xd2, 0x69, 0xc2, 0x54,
0xcb, 0x31, 0x7e, 0x7c, 0xb9, 0x1e, 0x90, 0x7e, 0x02, 0xe2, 0x01, 0x7d, 0x4a, 0x98, 0x6f, 0x39,
0xdf, 0x07, 0x43, 0x32, 0x04, 0xe9, 0x76, 0x49, 0xcf, 0x8f, 0xe2, 0x54, 0x66, 0xf2, 0xf9, 0x3e,
0x34, 0xb3, 0xad, 0xa2, 0x34, 0x9c, 0xb0, 0x04, 0xa4, 0xe5, 0x47, 0xb6, 0xd9, 0x80, 0x5f, 0xfa,
0x6a, 0x9b, 0x9d, 0x76, 0xbb, 0xd5, 0x86, 0x53, 0x66, 0xa2, 0xf0, 0x60, 0x9c, 0xb0, 0x7f, 0x52,
0x3f, 0x61, 0xa8, 0x85, 0xc4, 0x69, 0x46, 0xde, 0x56, 0xaa, 0xcd, 0x5d, 0x54, 0x8d, 0x55, 0xb2,
0xbb, 0xa8, 0xaa, 0xbf, 0x55, 0x7a, 0xe0, 0x90, 0x4a, 0xb7, 0xf8, 0xbb, 0x4e, 0xd7, 0x50, 0x86,
0x01, 0x34, 0xb4, 0x87, 0x75, 0x95, 0x73, 0x39, 0xeb, 0xdc, 0x80, 0xf3, 0x6a, 0xec, 0xd1, 0x71,
0xd8, 0x3d, 0x89, 0x89, 0x8b, 0x64, 0x6b, 0x21, 0x4d, 0x66, 0x7e, 0xd4, 0xb5, 0x08, 0x4d, 0x25,
0xc7, 0x45, 0xe0, 0x4d, 0x7a, 0x90, 0x3c, 0x03, 0x11, 0x53, 0x38, 0xd4, 0xc7, 0x25, 0x19, 0xc9,
0x5e, 0xe5, 0x29, 0x0d, 0xfc, 0x59, 0xd4, 0x75, 0x19, 0xa6, 0x0f, 0x53, 0x6b, 0x67, 0x96, 0xf0,
0x34, 0xc6, 0x4c, 0x06, 0xc7, 0xab, 0x2b, 0x7c, 0x45, 0xc3, 0xd1, 0x33, 0xf0, 0xd7, 0x28, 0x46,
0x4d, 0x35, 0x32, 0x70, 0xd8, 0x2a, 0x26, 0xcf, 0x8a, 0x51, 0xbb, 0x18, 0x75, 0x8a, 0xd1, 0x87,
0x62, 0x74, 0xbe, 0xb9, 0xc5, 0x98, 0x45, 0x5e, 0xd7, 0x28, 0x20, 0x32, 0xb9, 0x68, 0x29, 0xa8,
0xd0, 0x37, 0xe1, 0xaf, 0x99, 0x74, 0x1a, 0xb9, 0xcf, 0xc0, 0xc8, 0x29, 0x63, 0x18, 0x5b, 0x51,
0x9a, 0x05, 0x4a, 0x73, 0x13, 0x65, 0x2b, 0x46, 0xab, 0x28, 0x06, 0x60, 0x78, 0x1c, 0xca, 0x59,
0xb1, 0xc9, 0xd9, 0xb1, 0x7c, 0xb5, 0x0b, 0x94, 0xf6, 0x91, 0x9b, 0x74, 0x96, 0x7c, 0x75, 0x8e,
0x44, 0xf9, 0x50, 0x6c, 0xf2, 0xe1, 0x58, 0xbe, 0xce, 0x0b, 0x94, 0xf3, 0x1c, 0x65, 0x55, 0x59,
0x23, 0xe6, 0x32, 0xff, 0x99, 0x75, 0x8f, 0x22, 0x36, 0x2a, 0xf4, 0x35, 0x6a, 0x1c, 0xc7, 0xf1,
0xa8, 0x59, 0x1c, 0x72, 0x74, 0xa4, 0xbe, 0x46, 0xad, 0x62, 0x93, 0xd6, 0x91, 0x87, 0x1c, 0x15,
0xfa, 0x1a, 0x9d, 0x1d, 0xb9, 0x49, 0x7b, 0xc9, 0xd7, 0x91, 0xfa, 0x1a, 0x75, 0x8a, 0x4d, 0x3a,
0xc7, 0xf2, 0x55, 0xe8, 0x6b, 0xf4, 0xe1, 0xc8, 0x4d, 0xce, 0x97, 0x7c, 0xad, 0xeb, 0xab, 0xae,
0x22, 0x84, 0x8a, 0x53, 0x85, 0xce, 0x22, 0xfe, 0x92, 0xd0, 0x78, 0x17, 0xbd, 0x9c, 0x0e, 0x24,
0x92, 0x7e, 0xe2, 0xcf, 0xe6, 0x32, 0x62, 0x42, 0x54, 0x7b, 0xf5, 0x1c, 0x6b, 0x3f, 0x76, 0x86,
0x7c, 0x65, 0x3a, 0x57, 0x3c, 0xe0, 0x49, 0xd5, 0xd8, 0x40, 0xa4, 0x10, 0x88, 0xf7, 0x23, 0xff,
0x69, 0x3a, 0xd7, 0xd3, 0x29, 0x73, 0xa5, 0x58, 0x22, 0x17, 0x71, 0xd6, 0xd8, 0x81, 0x35, 0x7e,
0x80, 0x60, 0x3a, 0x66, 0x33, 0x2c, 0xa3, 0x09, 0x8f, 0x31, 0xe5, 0x8b, 0xea, 0xfe, 0x8d, 0xc6,
0x37, 0xd0, 0x45, 0x90, 0x09, 0x4f, 0x23, 0x4f, 0xe0, 0x06, 0x18, 0x81, 0x88, 0xae, 0x9e, 0x5d,
0xaa, 0x08, 0x40, 0xfe, 0x23, 0x1e, 0x04, 0x7b, 0x57, 0x62, 0x07, 0x10, 0xcd, 0x58, 0x97, 0xec,
0x97, 0xda, 0x78, 0x60, 0x3a, 0xbb, 0x49, 0x65, 0x09, 0x33, 0x4e, 0x40, 0xa2, 0x84, 0x27, 0xe4,
0x6e, 0x74, 0x90, 0x5e, 0x7f, 0x85, 0xde, 0x65, 0xc0, 0x5e, 0xe9, 0x3a, 0xd5, 0xee, 0x81, 0x13,
0x5e, 0x6a, 0x74, 0x43, 0xe1, 0x0f, 0xe7, 0x7e, 0xe0, 0xc7, 0x82, 0xdc, 0xa6, 0x2c, 0x3b, 0xce,
0xcf, 0x11, 0xbb, 0x5d, 0x25, 0x76, 0x4f, 0xdd, 0x84, 0xff, 0x1c, 0xfe, 0xfd, 0x2a, 0xfe, 0xba,
0x70, 0xe4, 0x0b, 0x34, 0x6d, 0x87, 0xf0, 0x9b, 0x66, 0x66, 0x07, 0x8e, 0x31, 0x62, 0x13, 0xce,
0x65, 0x91, 0x8b, 0x89, 0xe4, 0x84, 0xc6, 0x71, 0xf0, 0x96, 0x9d, 0x4b, 0xd4, 0x7a, 0x75, 0x5f,
0x15, 0x18, 0x77, 0x91, 0x90, 0x34, 0x72, 0x19, 0xf9, 0xe2, 0x67, 0xe5, 0x85, 0x71, 0x1d, 0xa9,
0xa4, 0xe9, 0xe7, 0x2b, 0x01, 0xac, 0x1c, 0xd8, 0xfa, 0xeb, 0x97, 0x8c, 0xf5, 0x7b, 0xba, 0x60,
0x44, 0xce, 0x7d, 0xb1, 0x44, 0x87, 0x8c, 0xec, 0xf2, 0x67, 0x96, 0x20, 0xd1, 0x43, 0x64, 0x50,
0x9b, 0xc0, 0xc2, 0x88, 0xd1, 0x40, 0xfa, 0x21, 0x33, 0x14, 0x43, 0x99, 0x5f, 0x12, 0xac, 0x7b,
0x92, 0x6c, 0xe5, 0x00, 0xa1, 0x51, 0x66, 0x66, 0xb9, 0x38, 0xbe, 0x32, 0xf9, 0xc2, 0x93, 0x05,
0x19, 0xdc, 0xff, 0x49, 0x14, 0x9e, 0x3a, 0x3e, 0x2c, 0x3e, 0x02, 0x3a, 0xd0, 0x82, 0xfe, 0x0e,
0x6d, 0x58, 0x23, 0x0f, 0xee, 0x54, 0x5d, 0xa7, 0x04, 0x05, 0x52, 0xc5, 0x4a, 0x59, 0xf5, 0x7b,
0x40, 0x52, 0xfb, 0x0d, 0x31, 0x74, 0x25, 0x6d, 0x62, 0x41, 0x0e, 0xbe, 0xd8, 0xa8, 0xb5, 0x1a,
0xe4, 0x44, 0x5c, 0x5e, 0x7d, 0xad, 0xf4, 0xea, 0x1a, 0xa4, 0x00, 0xcd, 0x20, 0xb1, 0x2e, 0x37,
0x9d, 0xcb, 0x44, 0x9e, 0x02, 0x2b, 0x1b, 0x40, 0x39, 0x3d, 0xcb, 0x24, 0x9a, 0x13, 0x68, 0x9f,
0xcc, 0x7c, 0x04, 0x91, 0x22, 0x15, 0x92, 0x87, 0x04, 0x2b, 0xea, 0x25, 0x6a, 0x5d, 0xaf, 0xeb,
0x23, 0x62, 0x8d, 0x8b, 0x71, 0x0e, 0x1a, 0x15, 0xc7, 0xd8, 0x52, 0xc5, 0x5d, 0x1f, 0x55, 0x1b,
0xae, 0x9e, 0x6a, 0x77, 0xa1, 0xa8, 0xeb, 0xd5, 0xfb, 0x14, 0xf4, 0x80, 0x25, 0xe9, 0x01, 0x4d,
0x5c, 0x17, 0x46, 0x2d, 0x29, 0x36, 0x04, 0x11, 0x68, 0x12, 0xda, 0x9e, 0x32, 0x7f, 0xdf, 0xb7,
0xf2, 0x67, 0xe5, 0xfc, 0xb5, 0x3e, 0x7e, 0xfc, 0x58, 0x62, 0xc3, 0x00, 0xbd, 0x96, 0xac, 0x5c,
0x19, 0x35, 0xb9, 0x42, 0x0e, 0x08, 0x07, 0xda, 0x3d, 0x4a, 0xe6, 0x09, 0x9b, 0xda, 0xc5, 0xa5,
0xc0, 0xcc, 0x97, 0xf3, 0x74, 0x52, 0x73, 0x79, 0x58, 0xff, 0xc2, 0xbc, 0xcf, 0xaf, 0xfa, 0x09,
0x67, 0x05, 0xde, 0x66, 0x78, 0x7b, 0xf1, 0xf7, 0x24, 0xa0, 0xd1, 0xc2, 0x74, 0xd4, 0x7c, 0xaf,
0x4e, 0x9d, 0x5f, 0x54, 0x70, 0x59, 0xf8, 0x31, 0x12, 0x3c, 0xe5, 0xd3, 0x53, 0x01, 0x7b, 0x31,
0x34, 0xeb, 0x18, 0x6a, 0x7d, 0x26, 0x97, 0x3e, 0x6d, 0xec, 0x38, 0xff, 0x58, 0x9f, 0x1f, 0x2d,
0x4f, 0x28, 0x11, 0x50, 0xcf, 0xc3, 0xf8, 0x56, 0x92, 0xc0, 0xe0, 0x72, 0xa3, 0xa2, 0x5d, 0x13,
0x41, 0xbb, 0x61, 0x95, 0x04, 0x80, 0x14, 0x43, 0xee, 0x6d, 0x9a, 0xef, 0xbd, 0x59, 0xb6, 0x3e,
0xbc, 0x0d, 0x1a, 0xf8, 0x02, 0x3d, 0xd0, 0xdb, 0x65, 0xa1, 0x50, 0x79, 0x8c, 0xa1, 0xa7, 0x03,
0xc7, 0x1f, 0xdd, 0xf4, 0x77, 0x01, 0x41, 0x84, 0x31, 0x32, 0xa8, 0xc1, 0x1e, 0xb0, 0x56, 0x9e,
0xa0, 0x76, 0x01, 0x80, 0x2f, 0x28, 0x03, 0xc2, 0xbd, 0x8c, 0x5d, 0x40, 0x50, 0x40, 0x0c, 0xfc,
0x30, 0x64, 0x09, 0x79, 0x4f, 0x0a, 0xe8, 0x9d, 0x0e, 0x06, 0x9c, 0x15, 0x40, 0x3f, 0x76, 0xb8,
0x09, 0x25, 0xc6, 0xba, 0x41, 0xec, 0xb8, 0x25, 0x62, 0xe8, 0xd1, 0xa7, 0x5e, 0xf8, 0x5a, 0x07,
0xa5, 0x94, 0x4c, 0x43, 0x7b, 0xbb, 0x1f, 0x4d, 0x39, 0xda, 0x87, 0xa1, 0x82, 0x08, 0x04, 0x24,
0x30, 0x8f, 0xb2, 0x4d, 0x3f, 0x1e, 0xf0, 0x39, 0xcb, 0x5a, 0x55, 0x29, 0x09, 0x55, 0x8e, 0x35,
0x3e, 0xf3, 0x04, 0xac, 0x0b, 0x40, 0xc8, 0xa4, 0xa8, 0x2e, 0x0e, 0xf8, 0xd8, 0xe7, 0x2c, 0x09,
0xe6, 0x3a, 0x2e, 0xa2, 0x24, 0x99, 0xd1, 0x30, 0xa4, 0xd0, 0xe0, 0x24, 0x98, 0xa2, 0x41, 0x1e,
0x87, 0xc2, 0xe6, 0x4d, 0x46, 0x28, 0x0f, 0xc0, 0x04, 0xbb, 0x4f, 0x3e, 0x9d, 0x42, 0x53, 0x5a,
0x3a, 0xdd, 0x8f, 0x87, 0xad, 0xa7, 0x3b, 0x6d, 0xb6, 0xdb, 0xd9, 0x01, 0xd5, 0xc8, 0x58, 0x9a,
0x2c, 0x44, 0x72, 0x9d, 0xa0, 0xff, 0xe0, 0x90, 0xcb, 0xc8, 0xa5, 0x10, 0x3e, 0x66, 0x08, 0x9d,
0x74, 0xae, 0xc3, 0x34, 0xa0, 0x92, 0x65, 0x29, 0x5c, 0xdf, 0x51, 0x1e, 0x72, 0xad, 0xcb, 0x2c,
0xe9, 0x68, 0x1c, 0x3f, 0x7a, 0xe6, 0x3a, 0x5b, 0xaa, 0xe5, 0xd2, 0x49, 0xb1, 0x9f, 0x2b, 0x8a,
0x86, 0xcb, 0x3b, 0xc5, 0x62, 0xc0, 0xa2, 0x99, 0x9c, 0x83, 0xb5, 0x36, 0x75, 0xd6, 0xe9, 0x07,
0x6f, 0xd1, 0x42, 0x71, 0xd3, 0x9b, 0x38, 0x86, 0x7a, 0xab, 0x92, 0xfb, 0x6f, 0x8f, 0x8f, 0x04,
0x4b, 0x32, 0x2c, 0x0a, 0x04, 0xb6, 0x80, 0x34, 0x08, 0xf0, 0xbe, 0x35, 0x42, 0x8f, 0x83, 0xb4,
0x0a, 0x84, 0x59, 0x12, 0xd1, 0x80, 0xcc, 0xb9, 0x90, 0x42, 0xc5, 0x0b, 0xe3, 0x11, 0x13, 0x60,
0x48, 0xdf, 0x88, 0x1f, 0x42, 0x98, 0x00, 0xb0, 0x39, 0xea, 0x44, 0xc4, 0x90, 0xc9, 0x21, 0xfc,
0x45, 0xaa, 0xba, 0x99, 0xaa, 0xd9, 0xeb, 0xf1, 0xf0, 0xbc, 0xd9, 0xe9, 0x40, 0xe4, 0x9a, 0x38,
0xb9, 0xfa, 0xc9, 0x84, 0x09, 0x0c, 0x6a, 0x02, 0xcc, 0x19, 0x4a, 0x34, 0x1e, 0x41, 0xda, 0x4e,
0x05, 0x83, 0x01, 0xcb, 0xd0, 0xe0, 0x45, 0xb0, 0x04, 0x65, 0x24, 0x08, 0x85, 0x88, 0x42, 0x50,
0x57, 0x35, 0x85, 0x7f, 0x02, 0x8a, 0x43, 0x7e, 0x24, 0x6c, 0x14, 0xbc, 0x55, 0x0b, 0x4e, 0x29,
0x60, 0xc0, 0xd8, 0xc3, 0x1d, 0x91, 0x6d, 0xa0, 0x12, 0xaa, 0x73, 0x21, 0x65, 0xe4, 0x04, 0xb3,
0x2b, 0x9e, 0xaf, 0x92, 0xe7, 0xcd, 0x5b, 0x8e, 0xc1, 0xdd, 0xd8, 0x22, 0x46, 0x2d, 0xc5, 0xfe,
0xed, 0x86, 0x14, 0xb7, 0x5d, 0x20, 0xf4, 0x87, 0x66, 0xae, 0xc0, 0x23, 0x72, 0xcf, 0xb9, 0xb5,
0x7a, 0x97, 0xa0, 0xe3, 0x9c, 0x32, 0x06, 0x72, 0x99, 0xca, 0x39, 0x30, 0xbe, 0x60, 0xd1, 0x92,
0xa9, 0x6c, 0x87, 0xdf, 0xd7, 0x19, 0x69, 0x15, 0x65, 0xd0, 0x55, 0xc0, 0x68, 0xa2, 0x4e, 0xa7,
0x10, 0xc9, 0xd4, 0x67, 0x81, 0xaa, 0x85, 0x3c, 0xed, 0x28, 0x35, 0xa2, 0xea, 0x80, 0x63, 0xc3,
0xc2, 0x04, 0x4d, 0x62, 0x4b, 0x48, 0x18, 0xe3, 0x95, 0x4d, 0x11, 0x12, 0xd4, 0xb5, 0x0d, 0x9a,
0x8d, 0x36, 0x6c, 0x5d, 0x4c, 0xe1, 0xfb, 0x01, 0xe7, 0xbb, 0xff, 0xa6, 0xf9, 0xee, 0x27, 0xc0,
0x6b, 0x52, 0x36, 0xfe, 0x55, 0xc9, 0xdf, 0x8f, 0x8f, 0x92, 0xfc, 0xfd, 0xb7, 0xe1, 0xc3, 0xe8,
0x71, 0x7b, 0x5a, 0x29, 0x49, 0xbf, 0x24, 0x72, 0xb4, 0xff, 0xc7, 0xb9, 0xe6, 0x9a, 0xb8, 0xe0,
0xbd, 0xd0, 0x33, 0xf8, 0x34, 0x00, 0x63, 0x4b, 0xd0, 0xf2, 0xb0, 0x81, 0x80, 0x2c, 0x0e, 0xe6,
0x03, 0xf9, 0x1c, 0xcc, 0x2a, 0xc5, 0x0a, 0x33, 0x33, 0x34, 0xf0, 0x3f, 0x6d, 0x88, 0x5f, 0x19,
0x82, 0xe4, 0xd6, 0xa5, 0x28, 0xc5, 0xb0, 0x09, 0x94, 0x61, 0x1e, 0x99, 0x72, 0x44, 0xe6, 0xb0,
0x90, 0xe4, 0x86, 0xfc, 0x4b, 0xee, 0x01, 0xdf, 0x05, 0x9a, 0x6f, 0xc8, 0xf6, 0x0a, 0xe0, 0xdb,
0xf7, 0xf1, 0xf5, 0x68, 0x4d, 0x08, 0x67, 0x96, 0x66, 0x7d, 0x98, 0xed, 0x51, 0x12, 0x76, 0xbe,
0x75, 0x11, 0x03, 0x40, 0x38, 0x97, 0xe3, 0x75, 0x39, 0x76, 0xce, 0x34, 0x89, 0xab, 0xc0, 0xc7,
0x23, 0xde, 0x0d, 0xb6, 0xc6, 0x90, 0x1c, 0xfd, 0xea, 0x6e, 0xa0, 0xef, 0xc0, 0xca, 0x1c, 0x64,
0xf6, 0xfa, 0xc8, 0x63, 0xdf, 0xdd, 0x47, 0x61, 0xb0, 0xa1, 0x44, 0x95, 0x4c, 0x6e, 0xf0, 0x86,
0xe9, 0x30, 0xf6, 0xcd, 0x66, 0x08, 0x43, 0xa9, 0x0f, 0xd3, 0x09, 0x94, 0xeb, 0xf3, 0x72, 0x33,
0x75, 0xc0, 0xf4, 0xfa, 0xf7, 0x3f, 0xd1, 0x39, 0xfc, 0x9c, 0xcf, 0x84, 0xff, 0x48, 0xb9, 0xc5,
0x65, 0x94, 0x3d, 0xac, 0x79, 0xcc, 0x4a, 0xf3, 0xa5, 0x63, 0x30, 0xf0, 0xf2, 0x17, 0x4f, 0x89,
0x4b, 0xd1, 0x6f, 0x21, 0x50, 0xa1, 0x19, 0x41, 0x4a, 0xf4, 0xa0, 0x2b, 0xbb, 0x1b, 0xaa, 0xd0,
0x85, 0x33, 0x01, 0xe6, 0x48, 0xa2, 0x8d, 0x1b, 0x08, 0xaa, 0xb9, 0x5f, 0x2f, 0xa1, 0x67, 0x95,
0xbf, 0x62, 0xc4, 0x53, 0xf9, 0x20, 0x8b, 0xb5, 0x73, 0x88, 0xe0, 0x70, 0x94, 0x9a, 0x91, 0x17,
0xff, 0x43, 0x0e, 0xa1, 0x1c, 0xe3, 0xba, 0x26, 0xb2, 0xe6, 0x3c, 0xb7, 0x5f, 0xf6, 0x66, 0x6f,
0x28, 0x47, 0x1d, 0x82, 0x16, 0xfe, 0x56, 0x0a, 0x46, 0xb7, 0x77, 0xdb, 0xf1, 0x2c, 0x6b, 0x2d,
0xef, 0x63, 0xba, 0x3f, 0x94, 0xdf, 0x6e, 0x87, 0x5a, 0x2b, 0xe0, 0x89, 0x51, 0x15, 0x14, 0xa2,
0xbb, 0xa0, 0xbd, 0x8a, 0xbc, 0x7d, 0xc0, 0x8e, 0xfd, 0x21, 0xaa, 0x3f, 0x4c, 0xa7, 0x07, 0x9a,
0xfb, 0x5b, 0x28, 0x1a, 0xc8, 0xca, 0x05, 0x06, 0x59, 0xb9, 0x77, 0xd8, 0xc5, 0xd0, 0x15, 0xa0,
0xa8, 0x6b, 0x0b, 0x95, 0x1f, 0x40, 0x70, 0xfd, 0x5c, 0x1f, 0xdd, 0x8d, 0x8b, 0xde, 0x5b, 0x6b,
0x23, 0xee, 0x67, 0x51, 0x46, 0x94, 0xaa, 0x7b, 0x2c, 0x14, 0x1c, 0x52, 0x2b, 0xc9, 0xbf, 0xb1,
0x11, 0xb8, 0x7e, 0x0a, 0x7d, 0xe3, 0xda, 0x7a, 0x13, 0xdb, 0xd8, 0x83, 0xde, 0x3a, 0x8c, 0xbe,
0xc4, 0xce, 0x43, 0xe6, 0x50, 0xdd, 0x5b, 0xa0, 0xa9, 0xc5, 0xa9, 0x98, 0x07, 0x7e, 0xb4, 0xc8,
0x9d, 0x90, 0x47, 0x2b, 0xe6, 0x0b, 0xa2, 0x9e, 0x82, 0x7f, 0xc0, 0x0c, 0xe4, 0x6e, 0x41, 0x9f,
0xb3, 0x86, 0x39, 0xa6, 0xb3, 0x65, 0x14, 0x34, 0x4e, 0x5e, 0xe6, 0x2a, 0x61, 0x25, 0x50, 0x0a,
0xe4, 0xa1, 0x35, 0x9a, 0x55, 0x72, 0xc1, 0x43, 0xe5, 0x24, 0x53, 0xb4, 0x20, 0xbc, 0xb9, 0x2e,
0x98, 0xf3, 0x63, 0x2c, 0x99, 0x75, 0x9d, 0xaf, 0x9d, 0x01, 0xe8, 0x4e, 0x52, 0x3f, 0xf0, 0xf0,
0xbb, 0x0b, 0x40, 0x2a, 0x57, 0x1b, 0xb3, 0x04, 0x82, 0xb9, 0x72, 0xb2, 0x3e, 0x4d, 0x3d, 0x92,
0x40, 0xe1, 0x55, 0x6e, 0x22, 0xfa, 0x83, 0x8d, 0x26, 0xa2, 0xd1, 0x68, 0x43, 0x94, 0xc1, 0xa7,
0x65, 0xed, 0xac, 0xd9, 0x9b, 0x2d, 0x0b, 0xa2, 0x28, 0x3e, 0x2d, 0x6b, 0x67, 0xf1, 0xdf, 0xb1,
0xa0, 0x6b, 0xc6, 0xe7, 0x1e, 0x42, 0xda, 0x4b, 0xf0, 0xb9, 0x9b, 0x50, 0xfb, 0x43, 0x07, 0x61,
0xe0, 0xb9, 0x87, 0xd0, 0xc7, 0x66, 0x03, 0x7a, 0x03, 0x7c, 0xee, 0x26, 0xd4, 0xb0, 0xd4, 0x6e,
0xea, 0x67, 0x0f, 0xa9, 0x86, 0x66, 0xaa, 0x51, 0xe6, 0x6a, 0xad, 0xc7, 0x80, 0xb0, 0xf5, 0x3b,
0x63, 0x31, 0xd6, 0x65, 0x5a, 0x56, 0x18, 0x41, 0x31, 0x0d, 0xde, 0x85, 0x71, 0xc2, 0x9f, 0x6b,
0x64, 0xcc, 0xa1, 0xae, 0x9e, 0x70, 0x9a, 0x78, 0xba, 0x46, 0x84, 0x3c, 0x48, 0x44, 0x1a, 0xab,
0xef, 0x65, 0x73, 0x70, 0x47, 0xa5, 0x8f, 0xfc, 0x82, 0x26, 0x29, 0x7f, 0x46, 0x3a, 0xe2, 0xc3,
0xd3, 0xee, 0xef, 0x4e, 0xc6, 0xca, 0x37, 0x2d, 0xfc, 0xb8, 0x06, 0x3f, 0xf8, 0xfd, 0x0d, 0x3f,
0xc6, 0xe1, 0x7f, 0x1c, 0xfc, 0x1f, 0x60, 0xa7, 0x58, 0xea, 0x81, 0x20, 0x00, 0x00
};

File diff suppressed because it is too large Load Diff

View File

@ -88,7 +88,7 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
void changeEffect(uint8_t fx)
{
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -103,7 +103,7 @@ void changeEffect(uint8_t fx)
void changePalette(uint8_t pal)
{
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -121,7 +121,7 @@ void changeEffectSpeed(int8_t amount)
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0,255);
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -145,7 +145,7 @@ void changeEffectSpeed(int8_t amount)
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -167,7 +167,7 @@ void changeEffectIntensity(int8_t amount)
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectIntensity + amount;
effectIntensity = (byte)constrain(new_val,0,255);
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -189,7 +189,7 @@ void changeEffectIntensity(int8_t amount)
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
if (!seg.isActive() || !seg.isSelected()) continue;
@ -208,7 +208,7 @@ void changeEffectIntensity(int8_t amount)
void changeColor(uint32_t c, int16_t cct=-1)
{
if (strip.applyToAllSelected) {
if (irApplyToAllSelected) {
// main segment may not be selected!
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
WS2812FX::Segment& seg = strip.getSegment(i);
@ -262,8 +262,6 @@ void decodeIR(uint32_t code)
}
if (code > 0xFFFFFF) return; //invalid code
strip.applyToAllSelected = irApplyToAllSelected;
switch (irEnabled) {
case 1:
if (code > 0xF80000) {
@ -283,8 +281,6 @@ void decodeIR(uint32_t code)
//case 8: return; // ir.json file, handled above switch statement
}
strip.applyToAllSelected = false;
if (nightlightActive && bri == 0) nightlightActive = false;
colorUpdated(CALL_MODE_BUTTON); //for notifier, IR is considered a button input
}
@ -643,9 +639,6 @@ void decodeIRJson(uint32_t code)
cmdStr = fdo["cmd"].as<String>();
jsonCmdObj = fdo["cmd"]; //object
// command is JSON object
//allow applyPreset() to reuse JSON buffer, or it would alloc. a second buffer and run out of mem.
//fileDoc = &doc; // used for applying presets (presets.cpp)
if (jsonCmdObj.isNull()) // we could also use: fdo["cmd"].is<String>()
{
if (cmdStr.startsWith("!")) {

View File

@ -12,8 +12,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
if (id >= strip.getMaxSegments()) return;
WS2812FX::Segment& seg = strip.getSegment(id);
//WS2812FX::Segment prev;
//prev = seg; //make a backup so we can tell if something changed
WS2812FX::Segment prev = seg; //make a backup so we can tell if something changed
uint16_t start = elem["start"] | seg.start;
int stop = elem["stop"] | -1;
@ -68,7 +67,6 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
uint16_t grp = elem["grp"] | seg.grouping;
uint16_t spc = elem[F("spc")] | seg.spacing;
uint16_t of = seg.offset;
if (!(elem[F("spc")].isNull() && elem["grp"].isNull())) effectChanged = true; //send UDP
uint16_t len = 1;
if (stop > start) len = stop - start;
@ -95,9 +93,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
if (elem["frz"].is<const char*>() && elem["frz"].as<const char*>()[0] == 't') frz = !seg.getOption(SEG_OPTION_FREEZE);
seg.setOption(SEG_OPTION_FREEZE, frz, id);
uint8_t cctPrev = seg.cct;
seg.setCCT(elem["cct"] | seg.cct, id);
if (seg.cct != cctPrev && id == strip.getMainSegmentId()) effectChanged = true; //send UDP
JsonArray colarr = elem["col"];
if (!colarr.isNull())
@ -151,26 +147,20 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
}
#endif
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
if (!(elem[F("sel")].isNull() && elem["rev"].isNull() && elem["on"].isNull() && elem[F("mi")].isNull())) effectChanged = true; //send UDP
byte fx = seg.mode;
byte fxPrev = fx;
if (getVal(elem["fx"], &fx, 1, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 1-255 exact value)
if (!presetId && currentPlaylist>=0) unloadPlaylist();
strip.setMode(id, fx);
if (!presetId && fx != fxPrev) effectChanged = true; //send UDP
}
byte prevSpd = seg.speed;
byte prevInt = seg.intensity;
byte prevPal = seg.palette;
if (getVal(elem[F("sx")], &seg.speed, 0, 255) && !presetId && prevSpd != seg.speed) effectChanged = true; //also supports inc/decrementing and random
if (getVal(elem[F("ix")], &seg.intensity, 0, 255) && !presetId && prevInt != seg.intensity) effectChanged = true; //also supports inc/decrementing and random
if (getVal(elem["pal"], &seg.palette, 1, strip.getPaletteCount()) && !presetId && prevPal != seg.palette) effectChanged = true; //also supports inc/decrementing and random
//getVal also supports inc/decrementing and random
getVal(elem[F("sx")], &seg.speed, 0, 255);
getVal(elem[F("ix")], &seg.intensity, 0, 255);
getVal(elem["pal"], &seg.palette, 1, strip.getPaletteCount());
JsonArray iarr = elem[F("i")]; //set individual LEDs
if (!iarr.isNull()) {
@ -225,8 +215,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
} else if (!elem["frz"] && iarr.isNull()) { //return to regular effect
seg.setOption(SEG_OPTION_FREEZE, false);
}
return; // seg.differs(prev);
//send UDP if not in preset and something changed that is not just selection
if (!presetId && (seg.differs(prev) & 0x7F)) effectChanged = true;
return;
}
// deserializes WLED state (fileDoc points to doc object if called from web server)
@ -234,7 +225,6 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
{
DEBUG_PRINTLN(F("Deserializing state"));
strip.applyToAllSelected = false;
bool stateResponse = root[F("v")] | false;
getVal(root["bri"], &bri);
@ -295,9 +285,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
else realtimeTimeout = 0; //cancel realtime mode immediately
}
byte prevMain = strip.getMainSegmentId();
strip.mainSegment = root[F("mainseg")] | prevMain;
//if (strip.getMainSegmentId() != prevMain) setValuesFromMainSeg();
strip.setMainSegmentId(root[F("mainseg")] | strip.getMainSegmentId());
int it = 0;
JsonVariant segVar = root["seg"];
@ -308,11 +296,9 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
if (id < 0) {
//apply all selected segments
//bool didSet = false;
//byte lowestActive = 99;
for (byte s = 0; s < strip.getMaxSegments(); s++) {
WS2812FX::Segment &sg = strip.getSegment(s);
if (sg.isActive()) {
//if (lowestActive == 99) lowestActive = s;
if (sg.isSelected()) {
deserializeSegment(segVar, s, presetId);
//didSet = true;
@ -320,7 +306,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
}
}
//TODO: not sure if it is good idea to change first active but unselected segment
//if (!didSet && lowestActive < strip.getMaxSegments()) deserializeSegment(segVar, lowestActive, presetId);
//if (!didSet) deserializeSegment(segVar, strip.getMainSegmentId(), presetId);
} else {
deserializeSegment(segVar, id, presetId); //apply only the segment with the specified ID
}
@ -332,7 +318,9 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
it++;
}
}
setValuesFromMainSeg(); //to make transition work on main segment
//refresh main segment (ensure it is selected, if there are any selected segments)
strip.setMainSegmentId(strip.getMainSegmentId());
#ifndef WLED_DISABLE_CRONIXIE
if (root["nx"].is<const char*>()) {
@ -380,7 +368,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
interfaceUpdateCallMode = CALL_MODE_WS_SEND;
}
colorUpdated(callMode);
stateUpdated(callMode);
return stateResponse;
}
@ -411,15 +399,10 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
for (uint8_t i = 0; i < 3; i++)
{
byte segcol[4]; byte* c = segcol;
if (id == strip.getMainSegmentId() && i < 2) //temporary, to make transition work on main segment
{
c = (i == 0)? col:colSec;
} else {
segcol[0] = R(seg.colors[i]);
segcol[1] = G(seg.colors[i]);
segcol[2] = B(seg.colors[i]);
segcol[3] = W(seg.colors[i]);
}
segcol[0] = R(seg.colors[i]);
segcol[1] = G(seg.colors[i]);
segcol[2] = B(seg.colors[i]);
segcol[3] = W(seg.colors[i]);
char tmpcol[22];
sprintf_P(tmpcol, format, (unsigned)c[0], (unsigned)c[1], (unsigned)c[2], (unsigned)c[3]);
strcat(colstr, i<2 ? strcat(tmpcol, ",") : tmpcol);
@ -496,10 +479,9 @@ void serializeInfo(JsonObject root)
JsonObject leds = root.createNestedObject("leds");
leds[F("count")] = strip.getLengthTotal();
leds[F("rgbw")] = strip.hasWhiteChannel();
leds[F("wv")] = false;
leds["cct"] = correctWB || strip.hasCCTBus();
leds[F("rgbw")] = strip.hasRGBWBus(); //deprecated, use info.leds.lc
leds[F("wv")] = false; //deprecated, use info.leds.lc
leds["cct"] = correctWB || strip.hasCCTBus(); //deprecated, use info.leds.lc
switch (Bus::getAutoWhiteMode()) {
case RGBW_MODE_MANUAL_ONLY:
case RGBW_MODE_DUAL:
@ -521,6 +503,17 @@ void serializeInfo(JsonObject root)
leds[F("maxseg")] = strip.getMaxSegments();
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
uint8_t totalLC = 0;
JsonArray lcarr = leds.createNestedArray(F("seglc"));
uint8_t nSegs = strip.getLastActiveSegmentId();
for (byte s = 0; s <= nSegs; s++) {
uint8_t lc = strip.getSegment(s).getLightCapabilities();
totalLC |= lc;
lcarr.add(lc);
}
leds["lc"] = totalLC;
root[F("str")] = syncToggleReceive;
root[F("name")] = serverDescription;

View File

@ -21,6 +21,33 @@ void setValuesFromMainSeg()
}
//applies global legacy values (col, colSec, effectCurrent...)
void applyValuesToSelectedSegs()
{
//copy of main segment to tell if value was updated
WS2812FX::Segment mainsegPrev = strip.getMainSegment();
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
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]);
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;}
}
}
void resetTimebase()
{
strip.timebase = 0 - millis();
@ -49,9 +76,8 @@ byte scaledBri(byte in)
}
void setAllLeds() {
strip.setColor(0, RGBW32(col[0], col[1], col[2], col[3]));
strip.setColor(1, RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]));
//applies global brightness
void applyBri() {
if (!realtimeMode || !arlsForceMaxBri)
{
strip.setBrightness(scaledBri(briT));
@ -59,18 +85,20 @@ void setAllLeds() {
}
void setLedsStandard()
{
//applies global brightness and sets it as the "current" brightness (no transition)
void applyFinalBri() {
briOld = bri;
briT = bri;
setAllLeds();
applyBri();
}
void colorUpdated(int callMode)
{
//called after every state changes, schedules interface updates, handles brightness transition and nightlight activation
//unlike colorUpdated(), does NOT apply any colors or FX to segments
void stateUpdated(byte callMode) {
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 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 (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
@ -109,9 +137,7 @@ void colorUpdated(int callMode)
jsonTransitionOnce = false;
strip.setTransition(transitionDelayTemp);
if (transitionDelayTemp == 0) {
//setLedsStandard();
briOld = briT = bri;
if (!realtimeMode || !arlsForceMaxBri) strip.setBrightness(scaledBri(briT));
applyFinalBri();
strip.trigger();
return;
}
@ -125,9 +151,7 @@ void colorUpdated(int callMode)
transitionStartTime = millis();
} else {
strip.setTransition(0);
//setLedsStandard();
briOld = briT = bri;
if (!realtimeMode || !arlsForceMaxBri) strip.setBrightness(scaledBri(briT));
applyFinalBri();
strip.trigger();
}
}
@ -156,7 +180,7 @@ void updateInterfaces(uint8_t callMode)
void handleTransitions()
{
//handle still pending interface update
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > 2000)
if (interfaceUpdateCallMode && millis() - lastInterfaceUpdate > INTERFACE_UPDATE_COOLDOWN)
{
updateInterfaces(interfaceUpdateCallMode);
interfaceUpdateCallMode = 0; //disable
@ -171,18 +195,25 @@ void handleTransitions()
strip.setTransitionMode(false);
transitionActive = false;
tperLast = 0;
setLedsStandard();
applyFinalBri();
return;
}
if (tper - tperLast < 0.004) return;
tperLast = tper;
briT = briOld +((bri - briOld )*tper);
setAllLeds();
applyBri();
}
}
//legacy method, applies values from col, effectCurrent, ... to selected segments
void colorUpdated(byte callMode){
applyValuesToSelectedSegs();
stateUpdated(callMode);
}
void handleNightlight()
{
static unsigned long lastNlUpdate;
@ -244,7 +275,7 @@ void handleNightlight()
effectSpeed = colNlT[1];
effectPalette = colNlT[2];
toggleOnOff();
setLedsStandard();
applyFinalBri();
}
}
#ifndef WLED_DISABLE_BLYNK

View File

@ -9,13 +9,13 @@
void parseMQTTBriPayload(char* payload)
{
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; colorUpdated(1);}
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); colorUpdated(1);}
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; stateUpdated(1);}
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); stateUpdated(1);}
else {
uint8_t in = strtoul(payload, NULL, 10);
if (in == 0 && bri > 0) briLast = bri;
bri = in;
colorUpdated(CALL_MODE_DIRECT_CHANGE);
stateUpdated(CALL_MODE_DIRECT_CHANGE);
}
}

View File

@ -218,6 +218,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
receiveNotificationColor = request->hasArg(F("RC"));
receiveNotificationEffects = request->hasArg(F("RX"));
receiveSegmentOptions = request->hasArg(F("SO"));
receiveSegmentBounds = request->hasArg(F("SG"));
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects || receiveSegmentOptions);
notifyDirectDefault = request->hasArg(F("SD"));
notifyDirect = notifyDirectDefault;
@ -450,7 +451,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
JsonObject um = doc.createNestedObject("um");
size_t args = request->args();
uint j=0;
uint16_t j=0;
for (size_t i=0; i<args; i++) {
String name = request->argName(i);
String value = request->arg(i);
@ -540,31 +541,31 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
DEBUG_PRINT(F("API req: "));
DEBUG_PRINTLN(req);
strip.applyToAllSelected = true;
//segment select (sets main segment)
byte prevMain = strip.getMainSegmentId();
pos = req.indexOf(F("SM="));
if (pos > 0) {
strip.mainSegment = getNumVal(&req, pos);
strip.setMainSegmentId(getNumVal(&req, pos));
}
byte selectedSeg = strip.getMainSegmentId();
if (selectedSeg != prevMain) setValuesFromMainSeg();
//snapshot to check if request changed values later, temporary.
byte prevCol[4] = {col[0], col[1], col[2], col[3]};
byte prevColSec[4] = {colSec[0], colSec[1], colSec[2], colSec[3]};
byte prevEffect = effectCurrent;
byte prevSpeed = effectSpeed;
byte prevIntensity = effectIntensity;
byte prevPalette = effectPalette;
//temporary values, do not write direcly to global values of 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="));
if (pos > 0) {
byte t = getNumVal(&req, pos);
if (t < strip.getMaxSegments()) {
selectedSeg = t;
strip.applyToAllSelected = false;
singleSegment = true;
}
}
@ -641,27 +642,23 @@ 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=", &col[0]);
updateVal(&req, "&G=", &col[1]);
updateVal(&req, "&B=", &col[2]);
updateVal(&req, "&W=", &col[3]);
for (byte i=0; i<4; i++) if (prevCol[i]!=col[i]) col0Changed = colorChanged = true;
if (col0Changed) selseg.setColor(0, RGBW32(col[0], col[1], col[2], col[3]), selectedSeg); // use transitions
updateVal(&req, "R2=", &colSec[0]);
updateVal(&req, "G2=", &colSec[1]);
updateVal(&req, "B2=", &colSec[2]);
updateVal(&req, "W2=", &colSec[3]);
for (byte i=0; i<4; i++) if (prevColSec[i]!=colSec[i]) col1Changed = colorChanged = true;
if (col1Changed) selseg.setColor(1, RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]), selectedSeg); // use transitions
#ifdef WLED_ENABLE_LOXONE
//lox parser
pos = req.indexOf(F("LX=")); // Lox primary color
if (pos > 0) {
int lxValue = getNumVal(&req, pos);
if (parseLx(lxValue, col)) {
if (parseLx(lxValue, colIn)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
}
@ -669,7 +666,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
pos = req.indexOf(F("LY=")); // Lox secondary color
if (pos > 0) {
int lxValue = getNumVal(&req, pos);
if(parseLx(lxValue, colSec)) {
if(parseLx(lxValue, colInSec)) {
bri = 255;
nightlightActive = false; //always disable nightlight when toggling
}
@ -686,51 +683,40 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
tempsat = getNumVal(&req, pos);
}
byte sec = req.indexOf(F("H2"));
colorHStoRGB(temphue, tempsat, (sec>0) ? colSec : col);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
colorHStoRGB(temphue, tempsat, (sec>0) ? colInSec : colIn);
}
//set white spectrum (kelvin)
pos = req.indexOf(F("&K="));
if (pos > 0) {
byte sec = req.indexOf(F("K2"));
colorKtoRGB(getNumVal(&req, pos), (sec>0) ? colSec : col);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
colorKtoRGB(getNumVal(&req, pos), (sec>0) ? colInSec : colIn);
}
//set color from HEX or 32bit DEC
byte tmpCol[4];
pos = req.indexOf(F("CL="));
if (pos > 0) {
colorFromDecOrHexString(col, (char*)req.substring(pos + 3).c_str());
selseg.setColor(0, RGBW32(col[0], col[1], col[2], col[3]), selectedSeg); // defined above (SS= or main)
col0Changed = colorChanged = true;
colorFromDecOrHexString(colIn, (char*)req.substring(pos + 3).c_str());
}
pos = req.indexOf(F("C2="));
if (pos > 0) {
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
selseg.setColor(1, RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]), selectedSeg); // defined above (SS= or main)
col1Changed = colorChanged = true;
colorFromDecOrHexString(colInSec, (char*)req.substring(pos + 3).c_str());
}
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)
colorChanged = true;
if (!singleSegment) strip.setColor(2, col2);
}
//set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf(F("SR"));
if (pos > 0) {
byte sec = getNumVal(&req, pos);
_setRandomColor(sec);
if (sec>0) col1Changed = true;
else col0Changed = true;
colorChanged = true;
setRandomColor(sec? colInSec : colIn);
}
//swap 2nd & 1st
@ -738,23 +724,41 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
if (pos > 0) {
byte temp;
for (uint8_t i=0; i<4; i++) {
temp = col[i];
col[i] = colSec[i];
colSec[i] = temp;
temp = colIn[i];
colIn[i] = colInSec[i];
colInSec[i] = temp;
}
col0Changed = col1Changed = colorChanged = true;
}
//apply colors to selected segment, and main color array if applicable
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);
if (!singleSegment) {
for (byte i=0; i<4; i++) col[i] = colIn[i];
}
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);
if (!singleSegment) {
for (byte i=0; i<4; i++) colSec[i] = colInSec[i];
}
//set effect parameters
if (updateVal(&req, "FX=", &effectCurrent, 0, strip.getModeCount()-1) && request != nullptr) unloadPlaylist(); //unload playlist if changing FX using web request
updateVal(&req, "SX=", &effectSpeed);
updateVal(&req, "IX=", &effectIntensity);
updateVal(&req, "FP=", &effectPalette, 0, strip.getPaletteCount()-1);
strip.setMode(selectedSeg, effectCurrent);
selseg.speed = effectSpeed;
selseg.intensity = effectIntensity;
selseg.palette = effectPalette;
if (effectCurrent != prevEffect || effectSpeed != prevSpeed || effectIntensity != prevIntensity || effectPalette != prevPalette) effectChanged = true;
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;
if (!singleSegment) {
effectCurrent = effectIn;
effectSpeed = speedIn;
effectIntensity = intensityIn;
effectPalette = paletteIn;
}
//set advanced overlay
pos = req.indexOf(F("OL="));
@ -884,24 +888,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
}
//you can add more if you need
//apply to all selected manually to prevent #1618. Temporary
if (strip.applyToAllSelected) {
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 != prevEffect) strip.setMode(i, effectCurrent);
if (effectSpeed != prevSpeed) seg.speed = effectSpeed;
if (effectIntensity != prevIntensity) seg.intensity = effectIntensity;
if (effectPalette != prevPalette) seg.palette = effectPalette;
if (col0Changed) seg.setColor(0, RGBW32(col[0], col[1], col[2], col[3]), i); // use transitions
if (col1Changed) seg.setColor(1, RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]), i); // use transitions
if (col2Changed) seg.colors[2] = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
}
}
strip.applyToAllSelected = false;
setValuesFromMainSeg();
//end of temporary fix code
if (!apply) return true; //when called by JSON API, do not call colorUpdated() here
//internal call, does not send XML response

View File

@ -28,37 +28,39 @@ void notify(byte callMode, bool followUp)
default: return;
}
byte udpOut[WLEDPACKETSIZE];
WS2812FX::Segment& mainseg = strip.getSegment(strip.getMainSegmentId());
WS2812FX::Segment& mainseg = strip.getMainSegment();
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
udpOut[1] = callMode;
udpOut[2] = bri;
udpOut[3] = col[0];
udpOut[4] = col[1];
udpOut[5] = col[2];
uint32_t col = mainseg.colors[0];
udpOut[3] = R(col);
udpOut[4] = G(col);
udpOut[5] = B(col);
udpOut[6] = nightlightActive;
udpOut[7] = nightlightDelayMins;
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = col[3];
udpOut[8] = mainseg.mode;
udpOut[9] = mainseg.speed;
udpOut[10] = W(col);
//compatibilityVersionByte:
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color 8: supports sys time sync, 36 byte packet
//9: supports sync groups, 37 byte packet 10: supports CCT, 39 byte packet 11: per segment options, variable packet length (40+MAX_NUM_SEGMENTS*3)
udpOut[11] = 11;
udpOut[12] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
udpOut[15] = colSec[3];
udpOut[16] = effectIntensity;
col = mainseg.colors[1];
udpOut[12] = R(col);
udpOut[13] = G(col);
udpOut[14] = B(col);
udpOut[15] = W(col);
udpOut[16] = mainseg.intensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette;
uint32_t colTer = mainseg.colors[2];
udpOut[20] = (colTer >> 16) & 0xFF;
udpOut[21] = (colTer >> 8) & 0xFF;
udpOut[22] = (colTer >> 0) & 0xFF;
udpOut[23] = (colTer >> 24) & 0xFF;
udpOut[19] = mainseg.palette;
col = mainseg.colors[2];
udpOut[20] = R(col);
udpOut[21] = G(col);
udpOut[22] = B(col);
udpOut[23] = W(col);
udpOut[24] = followUp;
uint32_t t = millis() + strip.timebase;
@ -322,16 +324,20 @@ void handleNotifications()
if (version < 200)
{
if (applyEffects && currentPlaylist >= 0) unloadPlaylist();
if (version > 10 && receiveSegmentOptions) {
//does not sync start & stop
uint8_t srcSegs = udpIn[39];
//if (srcSegs > strip.getMaxSegments()) srcSegs = strip.getMaxSegments();
for (uint8_t i = 0; i < srcSegs; i++) {
if (version > 10 && (receiveSegmentOptions || receiveSegmentBounds)) {
uint8_t numSrcSegs = udpIn[39];
for (uint8_t i = 0; i < numSrcSegs; i++) {
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
uint8_t id = udpIn[0 +ofs];
if (id > strip.getMaxSegments()) break;
WS2812FX::Segment& selseg = strip.getSegment(id);
//bytes 1+2 contain start, 3+4 stop, unused at this time
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
if (!receiveSegmentOptions) {
strip.setSegment(id, start, stop, selseg.grouping, selseg.spacing, offset);
continue;
}
for (uint8_t j = 0; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01, id); //only take into account mirrored, selected, on, reversed
selseg.setOpacity(udpIn[10+ofs], id);
if (applyEffects) {
@ -346,12 +352,18 @@ void handleNotifications()
selseg.setColor(2, RGBW32(udpIn[23+ofs],udpIn[24+ofs],udpIn[25+ofs],udpIn[26+ofs]), id);
selseg.setCCT(udpIn[27+ofs], id);
}
strip.setSegment(id, selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], (udpIn[7+ofs]<<8 | udpIn[8+ofs])); //also properly resets segments
//setSegment() also properly resets segments
if (receiveSegmentBounds) {
strip.setSegment(id, start, stop, udpIn[5+ofs], udpIn[6+ofs], offset);
} else {
strip.setSegment(id, selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], selseg.offset);
}
}
setValuesFromMainSeg();
effectChanged = true;
colorChanged = true;
} else if (applyEffects) { //simple effect sync, applies to all selected
}
if (applyEffects && (version < 11 || !receiveSegmentOptions)) { //simple effect sync, applies to all selected
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
effectSpeed = udpIn[9];
if (version > 2) effectIntensity = udpIn[16];

View File

@ -179,18 +179,6 @@ void prepareHostname(char* hostname)
}
void _setRandomColor(bool _sec, bool fromButton)
{
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
if (_sec){
colorHStoRGB(lastRandomIndex*256,255,colSec);
} else {
colorHStoRGB(lastRandomIndex*256,255,col);
}
if (fromButton) colorUpdated(CALL_MODE_BUTTON);
}
bool isAsterisksOnly(const char* str, byte maxLen)
{
for (byte i = 0; i < maxLen; i++) {

View File

@ -27,7 +27,7 @@ void WLED::reset()
while (millis() - dly < 450) {
yield(); // enough time to send response to client
}
setAllLeds();
applyBri();
DEBUG_PRINTLN(F("MODULE RESET"));
ESP.restart();
}

View File

@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2202191
#define VERSION 2202201
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG
@ -325,6 +325,7 @@ WLED_GLOBAL bool receiveNotificationBrightness _INIT(true); // apply brigh
WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color
WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup
WLED_GLOBAL bool receiveSegmentOptions _INIT(false); // apply segment options
WLED_GLOBAL bool receiveSegmentBounds _INIT(false); // apply segment bounds (start, stop, offset)
WLED_GLOBAL bool notifyDirect _INIT(false); // send notification if change via UI or HTTP API
WLED_GLOBAL bool notifyButton _INIT(false); // send if updated by button or infrared remote
WLED_GLOBAL bool notifyAlexa _INIT(false); // send notification if updated via Alexa

View File

@ -175,6 +175,7 @@ void initServer()
//request->send_P(200, "text/html", PAGE_usermod);
});
//Deprecated, use of /json/state and presets recommended instead
server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
URL_response(request);
});

View File

@ -55,13 +55,13 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
verboseResponse = deserializeState(root);
if (!interfaceUpdateCallMode) {
//special case, only on playlist load, avoid sending twice in rapid succession
if (millis() - lastInterfaceUpdate > 1700) verboseResponse = false;
if (millis() - lastInterfaceUpdate > (INTERFACE_UPDATE_COOLDOWN -300)) verboseResponse = false;
}
}
releaseJSONBufferLock(); // will clean fileDoc
}
//update if it takes longer than 300ms until next "broadcast"
if (verboseResponse && (millis() - lastInterfaceUpdate < 1700 || !interfaceUpdateCallMode)) sendDataWs(client);
if (verboseResponse && (millis() - lastInterfaceUpdate < (INTERFACE_UPDATE_COOLDOWN -300) || !interfaceUpdateCallMode)) sendDataWs(client);
}
} else {
//message is comprised of multiple frames or the frame is split into multiple packets
@ -114,7 +114,8 @@ void sendDataWs(AsyncWebSocketClient * client)
size_t heap2 = ESP.getFreeHeap();
if (!buffer || heap1-heap2<len) {
releaseJSONBufferLock();
ws.cleanupClients(0); // disconnect all clients to release memory
ws.closeAll(1013); //code 1013 = temporary overload, try again later
ws.cleanupClients(0); //disconnect all clients to release memory
return; //out of memory
}
serializeJson(doc, (char *)buffer->get(), len +1);
@ -163,7 +164,7 @@ void handleWs()
if (millis() - wsLastLiveTime > WS_LIVE_INTERVAL)
{
#ifdef ESP8266
ws.cleanupClients(2);
ws.cleanupClients(3);
#else
ws.cleanupClients();
#endif

View File

@ -72,6 +72,7 @@ void XML_response(AsyncWebServerRequest *request, char* dest)
if (request != nullptr) request->send(200, "text/xml", obuf);
}
//Deprecated, use of /json/state and presets recommended instead
void URL_response(AsyncWebServerRequest *request)
{
char sbuf[256];
@ -439,6 +440,7 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',SET_F("RC"),receiveNotificationColor);
sappend('c',SET_F("RX"),receiveNotificationEffects);
sappend('c',SET_F("SO"),receiveSegmentOptions);
sappend('c',SET_F("SG"),receiveSegmentBounds);
sappend('c',SET_F("SD"),notifyDirectDefault);
sappend('c',SET_F("SB"),notifyButton);
sappend('c',SET_F("SH"),notifyHue);