From 7b969bb8c27cc5b0474b4b075ce36f02a3fce938 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Wed, 16 Feb 2022 21:12:33 +0100 Subject: [PATCH] Various state changed logic simplifications Changed main segment, must be selected --- .../usermod.cpp | 8 +- .../usermod_bme280.cpp | 8 +- .../PIR_sensor_switch/PIR_Highlight_Standby | 6 +- .../usermod_PIR_sensor_switch.h | 6 +- usermods/ST7789_display/ST7789_display.h | 8 +- usermods/TTGO-T-Display/usermod.cpp | 8 +- .../usermod_vl53l0x_gestures.h | 2 +- .../usermod.cpp | 8 +- .../usermod_bme280.cpp | 8 +- .../wled06_usermod.ino | 8 - .../usermod_seven_segment_reloaded.h | 2 +- .../stairway-wipe-usermod-v2.h | 2 +- .../stairway_wipe_basic/wled06_usermod.ino | 2 +- .../usermod_v2_auto_save.h | 8 +- .../usermod_v2_four_line_display.h | 8 +- .../usermod_v2_rotary_encoder_ui.h | 8 +- .../usermod_v2_rotary_encoder_ui_ALT.h | 7 +- wled00/FX.h | 24 ++- wled00/FX_fcn.cpp | 114 ++++--------- wled00/alexa.cpp | 8 +- wled00/blynk.cpp | 8 +- wled00/button.cpp | 35 +--- wled00/colors.cpp | 6 + wled00/const.h | 2 + wled00/fcn_declare.h | 11 +- wled00/json.cpp | 53 ++---- wled00/led.cpp | 69 +++++--- wled00/mqtt.cpp | 6 +- wled00/set.cpp | 159 ++++++++---------- wled00/udp.cpp | 42 ++--- wled00/wled.cpp | 2 +- wled00/wled_server.cpp | 1 + wled00/ws.cpp | 4 +- wled00/xml.cpp | 1 + 34 files changed, 279 insertions(+), 373 deletions(-) diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp b/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp index 9724a1b7..36d322fa 100644 --- a/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp +++ b/usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp @@ -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); diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp b/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp index c39c74d2..58731283 100644 --- a/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp +++ b/usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp @@ -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); diff --git a/usermods/PIR_sensor_switch/PIR_Highlight_Standby b/usermods/PIR_sensor_switch/PIR_Highlight_Standby index 4cca1874..152388e8 100644 --- a/usermods/PIR_sensor_switch/PIR_Highlight_Standby +++ b/usermods/PIR_sensor_switch/PIR_Highlight_Standby @@ -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 } } diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h index 8e683a49..8085d79a 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h @@ -61,7 +61,7 @@ private: bool savedState = false; 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; @@ -136,7 +136,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); } } } diff --git a/usermods/ST7789_display/ST7789_display.h b/usermods/ST7789_display/ST7789_display.h index bd501d08..19ad5790 100644 --- a/usermods/ST7789_display/ST7789_display.h +++ b/usermods/ST7789_display/ST7789_display.h @@ -118,11 +118,11 @@ class St7789DisplayUsermod : public Usermod { { 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; } @@ -148,8 +148,8 @@ class St7789DisplayUsermod : public Usermod { #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); diff --git a/usermods/TTGO-T-Display/usermod.cpp b/usermods/TTGO-T-Display/usermod.cpp index 75e90b1e..9e08a001 100644 --- a/usermods/TTGO-T-Display/usermod.cpp +++ b/usermods/TTGO-T-Display/usermod.cpp @@ -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); diff --git a/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h b/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h index 9597992f..210ec3f5 100644 --- a/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h +++ b/usermods/VL53L0X_gestures/usermod_vl53l0x_gestures.h @@ -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; diff --git a/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp b/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp index a93b20c9..79241b5e 100644 --- a/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp +++ b/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp @@ -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); diff --git a/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp b/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp index 15ec58ad..fe53a462 100644 --- a/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp +++ b/usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp @@ -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); diff --git a/usermods/battery_keypad_controller/wled06_usermod.ino b/usermods/battery_keypad_controller/wled06_usermod.ino index acc1bd8c..b70682b4 100644 --- a/usermods/battery_keypad_controller/wled06_usermod.ino +++ b/usermods/battery_keypad_controller/wled06_usermod.ino @@ -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': diff --git a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h index 2deb6338..6274abce 100644 --- a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h +++ b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h @@ -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(); diff --git a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h index 67c78fee..08d551be 100644 --- a/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h +++ b/usermods/stairway_wipe_basic/stairway-wipe-usermod-v2.h @@ -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; diff --git a/usermods/stairway_wipe_basic/wled06_usermod.ino b/usermods/stairway_wipe_basic/wled06_usermod.ino index a0dcc3bb..eeece443 100644 --- a/usermods/stairway_wipe_basic/wled06_usermod.ino +++ b/usermods/stairway_wipe_basic/wled06_usermod.ino @@ -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; diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h index f2864362..0c0614c4 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h @@ -91,8 +91,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 @@ -106,8 +106,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) { diff --git a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h index c5251cba..a49961dd 100644 --- a/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h +++ b/usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h @@ -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; diff --git a/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h b/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h index bf909bdc..0ea77e84 100644 --- a/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h +++ b/usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h @@ -290,12 +290,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) { diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h index 98d84016..b6e5ee70 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h @@ -466,12 +466,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) { diff --git a/wled00/FX.h b/wled00/FX.h index 30cd5a48..5b50af92 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -287,9 +287,8 @@ class WS2812FX { } void setOption(uint8_t n, bool val, uint8_t segn = 255) { - bool prevOn = false; + bool prevOn = getOption(n); if (n == SEG_OPTION_ON) { - prevOn = getOption(SEG_OPTION_ON); if (!val && prevOn) { //fade off ColorTransition::startTransition(opacity, colors[0], instance->_transitionDur, segn, 0); } @@ -305,6 +304,10 @@ class WS2812FX { if (n == SEG_OPTION_ON && val && !prevOn) { //fade on ColorTransition::startTransition(0, colors[0], instance->_transitionDur, segn, 0); } + if (n == SEG_OPTION_SELECTED && !val && prevOn) { + //choose a new main segment if the main segment is deselected + if (segn == instance->_mainSegment) instance->setMainSegmentId(0); + } } bool getOption(uint8_t n) { @@ -649,6 +652,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(), @@ -662,27 +666,21 @@ 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), // 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), setPixelSegment(uint8_t n), @@ -714,11 +712,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); @@ -912,6 +908,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}} diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 302464b6..7330941a 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -393,63 +393,20 @@ 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,27 +431,33 @@ 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 - { - if (_segments[i].isActive()) return i; - } - return 0; + return _mainSegment; } uint8_t WS2812FX::getActiveSegmentsNum(void) { @@ -539,8 +494,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) { @@ -596,17 +551,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 active as main segment + if (n == _mainSegment) setMainSegmentId(0); return; } if (i1 < _length) seg.start = i1; @@ -628,7 +574,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; diff --git a/wled00/alexa.cpp b/wled00/alexa.cpp index 1f85f7ab..8f04f016 100644 --- a/wled00/alexa.cpp +++ b/wled00/alexa.cpp @@ -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 diff --git a/wled00/blynk.cpp b/wled00/blynk.cpp index ce390448..b1619d81 100644 --- a/wled00/blynk.cpp +++ b/wled00/blynk.cpp @@ -44,27 +44,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) diff --git a/wled00/button.cpp b/wled00/button.cpp index 8472d392..03a90aaa 100644 --- a/wled00/button.cpp +++ b/wled00/button.cpp @@ -16,8 +16,8 @@ void shortPressAction(uint8_t b) { if (!macroButton[b]) { switch (b) { - case 0: toggleOnOff(); colorUpdated(CALL_MODE_BUTTON); break; - case 1: ++effectCurrent %= strip.getModeCount(); effectChanged = true; colorUpdated(CALL_MODE_BUTTON); break; + case 0: toggleOnOff(); stateUpdated(CALL_MODE_BUTTON); break; + case 1: ++effectCurrent %= strip.getModeCount(); colorUpdated(CALL_MODE_BUTTON); break; } } else { applyPreset(macroButton[b], CALL_MODE_BUTTON_PRESET); @@ -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 @@ -258,7 +239,7 @@ void handleButton() if (b == 0 && dur > WLED_LONG_AP) { //long press on button 0 (when released) WLED::instance().initAP(true); } else if (!buttonLongPressed[b]) { //short press - if (b == 0 && !macroDoublePress[b]) { //don't wait for double press on button 0 if no double press macro set + 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) { diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 0655060e..01dbdcb4 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -4,6 +4,12 @@ * Color conversion methods */ +void setRandomColor(byte* rgb) +{ + lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex); + colorHStoRGB(lastRandomIndex*256,255,rgb); +} + void colorFromUint32(uint32_t in, bool secondary) { byte *_col = secondary ? colSec : col; diff --git a/wled00/const.h b/wled00/const.h index aaeb7fc5..4dacddc6 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -344,4 +344,6 @@ #define DEFAULT_LED_COUNT 30 #endif +#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates + #endif diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 4086e9ee..faeea2c7 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -75,6 +75,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(); @@ -145,9 +147,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(); @@ -201,7 +204,6 @@ inline void saveTemporaryPreset() {savePreset(255, false);}; void deletePreset(byte index); //set.cpp -void _setRandomColor(bool _sec,bool fromButton=false); bool isAsterisksOnly(const char* str, byte maxLen); void handleSettingsSet(AsyncWebServerRequest *request, byte subPage); bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply=true); @@ -224,7 +226,6 @@ void sendSysInfoUDP(); //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); //bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); void releaseJSONBufferLock(); diff --git a/wled00/json.cpp b/wled00/json.cpp index e7453612..7ce77342 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -27,8 +27,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; @@ -83,7 +82,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; @@ -110,9 +108,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId) if (elem["frz"].is() && elem["frz"].as()[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()) @@ -167,25 +163,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_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED), id); 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 && seg.mode != 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()) { @@ -240,13 +231,13 @@ 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); + if (!presetId && seg.differs(prev)) effectChanged = true; + return; } // deserializes WLED state (fileDoc points to doc object if called from web server) bool deserializeState(JsonObject root, byte callMode, byte presetId) { - strip.applyToAllSelected = false; bool stateResponse = root[F("v")] | false; getVal(root["bri"], &bri); @@ -307,9 +298,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"]; @@ -320,19 +309,17 @@ 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; } } } - //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 none selected, apply to the main segment + if (!didSet) deserializeSegment(segVar, strip.getMainSegmentId(), presetId); } else { deserializeSegment(segVar, id, presetId); //apply only the segment with the specified ID } @@ -344,7 +331,6 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) it++; } } - setValuesFromMainSeg(); //to make transition work on main segment #ifndef WLED_DISABLE_CRONIXIE if (root["nx"].is()) { @@ -391,7 +377,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId) interfaceUpdateCallMode = CALL_MODE_WS_SEND; } - colorUpdated(callMode); + stateUpdated(callMode); return stateResponse; } @@ -422,15 +408,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); diff --git a/wled00/led.cpp b/wled00/led.cpp index f5c235bf..c8f72f4f 100644 --- a/wled00/led.cpp +++ b/wled00/led.cpp @@ -5,7 +5,7 @@ */ void setValuesFromMainSeg() { - WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId()); + WS2812FX::Segment& seg = strip.getMainSegment(); colorFromUint32(seg.colors[0]); colorFromUint32(seg.colors[1], true); effectCurrent = seg.mode; @@ -15,6 +15,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(); @@ -43,9 +70,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)); @@ -53,18 +79,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; @@ -103,9 +131,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; } @@ -119,9 +145,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(); } } @@ -150,7 +174,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 @@ -165,18 +189,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() { /* @@ -239,7 +270,7 @@ void handleNightlight() effectSpeed = colNlT[1]; effectPalette = colNlT[2]; toggleOnOff(); - setLedsStandard(); + applyFinalBri(); } } #ifndef WLED_DISABLE_BLYNK diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 2823eee4..85aa85f3 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -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); } } diff --git a/wled00/set.cpp b/wled00/set.cpp index a2a5812e..25ce6ef8 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -3,19 +3,6 @@ /* * Receives client input */ - -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(2); -} - - bool isAsterisksOnly(const char* str, byte maxLen) { for (byte i = 0; i < maxLen; i++) { @@ -470,7 +457,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; iargName(i); String value = request->arg(i); @@ -616,31 +603,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; } } @@ -648,8 +635,8 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) pos = req.indexOf(F("SV=")); //segment selected if (pos > 0) { byte t = getNumVal(&req, pos); - if (t == 2) for (uint8_t i = 0; i < strip.getMaxSegments(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments - selseg.setOption(SEG_OPTION_SELECTED, t); + if (t == 2) for (uint8_t i = 0; i < strip.getMaxSegments(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0, i); // unselect other segments + selseg.setOption(SEG_OPTION_SELECTED, t, selectedSeg); } uint16_t startI = selseg.start; @@ -717,27 +704,24 @@ 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); - 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); + updateVal(&req, "&R=", &colIn[0]); + updateVal(&req, "&G=", &colIn[1]); + updateVal(&req, "&B=", &colIn[2]); + updateVal(&req, "&W=", &colIn[3]); + + updateVal(&req, "R2=", &colInSec[0]); + updateVal(&req, "G2=", &colInSec[1]); + updateVal(&req, "B2=", &colInSec[2]); + updateVal(&req, "W2=", &colInSec[3]); #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 } @@ -745,7 +729,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 } @@ -762,51 +746,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 @@ -814,23 +787,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=")); @@ -960,24 +951,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 diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 03205851..b73a7fd8 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -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; + udpOut[11] = 11; + 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; @@ -357,7 +359,6 @@ void handleNotifications() strip.setSegment(id, selseg.start, selseg.stop, udpIn[5+ofs], udpIn[6+ofs], selseg.offset); } } - setValuesFromMainSeg(); effectChanged = true; colorChanged = true; } @@ -411,7 +412,6 @@ void handleNotifications() if (nightlightActive) nightlightDelayMins = udpIn[7]; if (receiveNotificationBrightness || !someSel) bri = udpIn[2]; - strip.applyToAllSelected = !(version > 10 && receiveSegmentOptions); colorUpdated(CALL_MODE_NOTIFICATION); return; } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index acc96d53..9da27812 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -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(); } diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index adee38a9..38fa584d 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -160,6 +160,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); }); diff --git a/wled00/ws.cpp b/wled00/ws.cpp index 5d26a07c..42d070ec 100644 --- a/wled00/ws.cpp +++ b/wled00/ws.cpp @@ -56,13 +56,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 diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 03da27fc..2a71f1ab 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -75,6 +75,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];