diff --git a/wled00/NpbWrapper.h b/wled00/NpbWrapper.h index 1a271844..173a4917 100644 --- a/wled00/NpbWrapper.h +++ b/wled00/NpbWrapper.h @@ -3,10 +3,10 @@ #define NpbWrapper_h //PIN CONFIGURATION -#define LEDPIN 5 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos) +#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos) //#define USE_APA102 // Uncomment for using APA102 LEDs. #define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended) -#define IR_PIN 4 //infrared pin (-1 to disable) +#define IR_PIN -1 //infrared pin (-1 to disable) #define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,... #define AUXPIN -1 //debug auxiliary output pin (-1 to disable) diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 15d9e626..65c14e96 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -42,12 +42,13 @@ /* each segment uses 37 bytes of SRAM memory, so if you're application fails because of insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ -#define MAX_NUM_SEGMENTS 8 +#define MAX_NUM_SEGMENTS 10 #define NUM_COLORS 3 /* number of colors per segment */ #define SEGMENT _segments[_segment_index] #define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x]) #define SEGENV _segment_runtimes[_segment_index] #define SEGLEN SEGMENT.length() +#define SEGACT SEGMENT.stop #define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN #define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes)) @@ -190,7 +191,15 @@ class WS2812FX { { return ((options >> n) & 0x01); } - inline uint16_t length() + bool isSelected() + { + return getOption(0); + } + bool isActive() + { + return stop > start; + } + uint16_t length() { return stop - start; } @@ -289,11 +298,6 @@ class WS2812FX { _mode[FX_MODE_RIPPLE] = &WS2812FX::mode_ripple; _brightness = DEFAULT_BRIGHTNESS; - _num_segments = 1; - _segments[0].mode = DEFAULT_MODE; - _segments[0].colors[0] = DEFAULT_COLOR; - _segments[0].start = 0; - _segments[0].speed = DEFAULT_SPEED; currentPalette = CRGBPalette16(CRGB::Black); targetPalette = CloudColors_p; ablMilliampsMax = 850; @@ -301,7 +305,7 @@ class WS2812FX { _locked = nullptr; _modeUsesLock = false; bus = new NeoPixelWrapper(); - RESET_RUNTIME; + resetSegments(); } void @@ -310,13 +314,12 @@ class WS2812FX { blur(uint8_t), fade_out(uint8_t r), setMode(uint8_t m), + setMode(uint8_t segid, uint8_t m), setSpeed(uint8_t s), setIntensity(uint8_t i), setPalette(uint8_t p), - setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), - setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), - setColor(uint32_t c), - setSecondaryColor(uint32_t c), + setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), + setColor(uint8_t slot, uint32_t c), setBrightness(uint8_t b), driverModeCronixie(bool b), setCronixieDigits(byte* d), @@ -337,22 +340,24 @@ class WS2812FX { show(void); bool - reverseMode = true, + reverseMode = false, gammaCorrectBri = false, gammaCorrectCol = true, setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p); uint8_t + returnedSegment = 0, paletteFade = 0, paletteBlend = 0, colorOrder = 0, getBrightness(void), getMode(void), getSpeed(void), - getNumSegments(void), getModeCount(void), getPaletteCount(void), getMaxSegments(void), + getFirstSelectedSegment(void), + getReturnedSegmentId(void), gamma8(uint8_t), get_random_wheel_index(uint8_t); @@ -506,7 +511,6 @@ class WS2812FX { uint8_t _segment_index = 0; uint8_t _segment_index_palette_last = 99; - uint8_t _num_segments = 1; segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element // start, stop, speed, intensity, palette, mode, options, color[] { 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, {DEFAULT_COLOR}} diff --git a/wled00/WS2812FX_fcn.cpp b/wled00/WS2812FX_fcn.cpp index 34b76469..4f93a25d 100644 --- a/wled00/WS2812FX_fcn.cpp +++ b/wled00/WS2812FX_fcn.cpp @@ -58,16 +58,19 @@ void WS2812FX::service() { unsigned long now = millis(); // Be aware, millis() rolls over every 49 days if (now - _lastShow < MIN_SHOW_DELAY) return; bool doShow = false; - for(uint8_t i=0; i < _num_segments; i++) + for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++) { _segment_index = i; - if(now > SEGENV.next_time || _triggered) + if (SEGMENT.isActive()) { - doShow = true; - handle_palette(); - uint16_t delay = (this->*_mode[SEGMENT.mode])(); - SEGENV.next_time = now + max(delay, MIN_SHOW_DELAY); - SEGENV.call++; + if(now > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary + { + doShow = true; + handle_palette(); + uint16_t delay = (this->*_mode[SEGMENT.mode])(); + SEGENV.next_time = now + delay; + SEGENV.call++; + } } } if(doShow) { @@ -249,14 +252,24 @@ void WS2812FX::trigger() { _triggered = true; } -void WS2812FX::setMode(uint8_t m) { - RESET_RUNTIME; - bool ua = modeUsesLock(_segments[0].mode) && !modeUsesLock(m); - if (m > MODE_COUNT - 1) m = MODE_COUNT - 1; - _segments[0].mode = m; - if (ua) unlockAll(); - _modeUsesLock = modeUsesLock(_segments[0].mode); - setBrightness(_brightness); +void WS2812FX::setMode(uint8_t segid, uint8_t m) { + if (segid >= MAX_NUM_SEGMENTS) return; + + bool anyUsedLock = _modeUsesLock, anyUseLock = false; + if (m >= MODE_COUNT) m = MODE_COUNT - 1; + + if (_segments[segid].mode != m) + { + _segment_runtimes[segid].reset(); + _segments[segid].mode = m; + } + + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (modeUsesLock(_segments[i].mode)) anyUseLock = true; + } + if (anyUsedLock && !anyUseLock) unlockAll(); + _modeUsesLock = anyUseLock; } uint8_t WS2812FX::getModeCount() @@ -271,42 +284,64 @@ uint8_t WS2812FX::getPaletteCount() //TODO transitions +void WS2812FX::setMode(uint8_t m) { + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isSelected()) setMode(i, m); + } +} + void WS2812FX::setSpeed(uint8_t s) { - _segments[0].speed = s; + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isSelected()) _segments[i].speed = s; + } } void WS2812FX::setIntensity(uint8_t in) { - _segments[0].intensity = in; + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isSelected()) _segments[i].intensity = in; + } } void WS2812FX::setPalette(uint8_t p) { - _segments[0].palette = p; + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isSelected()) _segments[i].palette = p; + } } -bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p) { - bool changed = false; - m = constrain(m, 0, MODE_COUNT - 1); - if (m != _segments[0].mode) { setMode(m); changed = true; } - if (s != _segments[0].speed) { setSpeed(s); changed = true; } - if (i != _segments[0].intensity) { setIntensity(i); changed = true; } - if (p != _segments[0].palette) { setPalette(p); changed = true; } - return changed; +bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) { + uint8_t retSeg = getReturnedSegmentId(); + Segment& seg = _segments[retSeg]; + uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette; + + 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); + } + } + + if (seg.mode != modePrev || seg.speed != speedPrev || seg.intensity != intensityPrev || seg.palette != palettePrev) return true; + return false; } -void WS2812FX::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { - setColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); +void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + setColor(slot, ((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); } -void WS2812FX::setSecondaryColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { - setSecondaryColor(((uint32_t)w << 24) |((uint32_t)r << 16) | ((uint32_t)g << 8) | b); -} - -void WS2812FX::setColor(uint32_t c) { - _segments[0].colors[0] = c; -} - -void WS2812FX::setSecondaryColor(uint32_t c) { - _segments[0].colors[1] = c; +void WS2812FX::setColor(uint8_t slot, uint32_t c) { + if (slot >= NUM_COLORS) return; + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isSelected()) _segments[i].colors[slot] = c; + } } void WS2812FX::setBrightness(uint8_t b) { @@ -316,27 +351,44 @@ void WS2812FX::setBrightness(uint8_t b) { } uint8_t WS2812FX::getMode(void) { - return _segments[0].mode; + return _segments[getReturnedSegmentId()].mode; } uint8_t WS2812FX::getSpeed(void) { - return _segments[0].speed; + return _segments[getReturnedSegmentId()].speed; } uint8_t WS2812FX::getBrightness(void) { return _brightness; } -uint8_t WS2812FX::getNumSegments(void) { - return _num_segments; -} - uint8_t WS2812FX::getMaxSegments(void) { return MAX_NUM_SEGMENTS; } +uint8_t WS2812FX::getFirstSelectedSegment(void) +{ + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) + { + if (_segments[i].isActive() && _segments[i].isSelected()) return i; + } + for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++) //if none selected, get first active + { + if (_segments[i].isActive()) return i; + } + return 0; +} + +uint8_t WS2812FX::getReturnedSegmentId(void) { + if (returnedSegment >= MAX_NUM_SEGMENTS || !_segments[returnedSegment].isActive()) + { + return getFirstSelectedSegment(); + } + return returnedSegment; +} + uint32_t WS2812FX::getColor(void) { - return _segments[0].colors[0]; + return _segments[getReturnedSegmentId()].colors[0]; } uint32_t WS2812FX::getPixelColor(uint16_t i) @@ -392,6 +444,16 @@ void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) { if (n >= MAX_NUM_SEGMENTS) return; Segment& seg = _segments[n]; if (seg.start == i1 && seg.stop == i2) return; + if (seg.isActive() && modeUsesLock(seg.mode)) + { + _modeUsesLock = false; + unlockRange(seg.start, seg.stop); + _modeUsesLock = true; + } + if (i2 <= i1) //disable segment + { + seg.stop = 0; return; + } if (i1 < _length) seg.start = i1; seg.stop = i2; if (i2 > _length) seg.stop = _length; @@ -402,12 +464,12 @@ void WS2812FX::resetSegments() { memset(_segments, 0, sizeof(_segments)); memset(_segment_runtimes, 0, sizeof(_segment_runtimes)); _segment_index = 0; - _num_segments = 1; _segments[0].mode = DEFAULT_MODE; _segments[0].colors[0] = DEFAULT_COLOR; _segments[0].start = 0; _segments[0].speed = DEFAULT_SPEED; _segments[0].stop = _length; + _segments[0].setOption(0, 1); //select } void WS2812FX::setIndividual(uint16_t i, uint32_t col) @@ -434,28 +496,28 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) void WS2812FX::lock(uint16_t i) { - if (modeUsesLock(SEGMENT.mode)) return; + if (_modeUsesLock) return; if (i >= 0 && i < _length) _locked[i] = true; } void WS2812FX::lockRange(uint16_t i, uint16_t i2) { - if (modeUsesLock(SEGMENT.mode)) return; + if (_modeUsesLock) return; for (uint16_t x = i; x < i2; x++) { - if (i >= 0 && i < _length) _locked[i] = true; + if (x >= 0 && x < _length) _locked[i] = true; } } void WS2812FX::unlock(uint16_t i) { - if (modeUsesLock(SEGMENT.mode)) return; + if (_modeUsesLock) return; if (i >= 0 && i < _length) _locked[i] = false; } void WS2812FX::unlockRange(uint16_t i, uint16_t i2) { - if (modeUsesLock(SEGMENT.mode)) return; + if (_modeUsesLock) return; for (uint16_t x = i; x < i2; x++) { if (x >= 0 && x < _length) _locked[x] = false; diff --git a/wled00/src/dependencies/espalexa/Espalexa.h b/wled00/src/dependencies/espalexa/Espalexa.h index 997fada2..64e7e41d 100644 --- a/wled00/src/dependencies/espalexa/Espalexa.h +++ b/wled00/src/dependencies/espalexa/Espalexa.h @@ -10,7 +10,7 @@ */ /* * @title Espalexa library - * @version 2.4.2 + * @version 2.4.3 * @author Christian Schwinne * @license MIT * @contributors d-999 @@ -49,7 +49,7 @@ #include #ifdef ESPALEXA_DEBUG - #pragma message "Espalexa 2.4.2 debug mode" + #pragma message "Espalexa 2.4.3 debug mode" #define EA_DEBUG(x) Serial.print (x) #define EA_DEBUGLN(x) Serial.println (x) #else @@ -121,11 +121,25 @@ private: return "Plug"; } + //Workaround functions courtesy of Sonoff-Tasmota + uint32_t encodeLightId(uint8_t idx) + { + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF); + return id; + } + + uint32_t decodeLightId(uint32_t id) { + return id & 0xF; + } + //device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001) String deviceJsonString(uint8_t deviceId) { - if (deviceId < 1 || deviceId > currentDeviceCount) return "{}"; //error - EspalexaDevice* dev = devices[deviceId-1]; + deviceId--; + if (deviceId >= currentDeviceCount) return "{}"; //error + EspalexaDevice* dev = devices[deviceId]; String json = "{\"state\":{\"on\":"; json += boolString(dev->getValue()); @@ -149,8 +163,8 @@ private: json += "\",\"name\":\"" + dev->getName(); json += "\",\"modelid\":\"" + modelidString(dev->getType()); json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast(dev->getType())); - json += "\",\"uniqueid\":\""+ WiFi.macAddress() +"-"+ (deviceId+1); - json += "\",\"swversion\":\"espalexa-2.4.2\"}"; + json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1)); + json += "\",\"swversion\":\"espalexa-2.4.3\"}"; return json; } @@ -174,7 +188,7 @@ private: } res += "\r\nFree Heap: " + (String)ESP.getFreeHeap(); res += "\r\nUptime: " + (String)millis(); - res += "\r\n\r\nEspalexa library v2.4.2 by Christian Schwinne 2019"; + res += "\r\n\r\nEspalexa library v2.4.3 by Christian Schwinne 2019"; server->send(200, "text/plain", res); } #endif @@ -219,15 +233,6 @@ private: ""+ escapedMac +"" "uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"" "index.html" - "" - " " - " image/png" - " 48" - " 48" - " 24" - " hue_logo_0.png" - " " - "" "" ""; @@ -450,22 +455,27 @@ public: { server->send(200, "application/json", "[{\"success\":true}]"); //short valid response - int devId = req.substring(req.indexOf("lights")+7).toInt(); + uint32_t devId = req.substring(req.indexOf("lights")+7).toInt(); EA_DEBUG("ls"); EA_DEBUGLN(devId); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::none); + devId = decodeLightId(devId); + EA_DEBUGLN(devId); + devId--; //zero-based for devices array + if (devId >= currentDeviceCount) return true; //return if invalid ID + + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::none); if (body.indexOf("false")>0) //OFF command { - devices[devId-1]->setValue(0); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::off); - devices[devId-1]->doCallback(); + devices[devId]->setValue(0); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::off); + devices[devId]->doCallback(); return true; } if (body.indexOf("true") >0) //ON command { - devices[devId-1]->setValue(devices[devId-1]->getLastValue()); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::on); + devices[devId]->setValue(devices[devId]->getLastValue()); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::on); } if (body.indexOf("bri") >0) //BRIGHTNESS command @@ -473,35 +483,35 @@ public: uint8_t briL = body.substring(body.indexOf("bri") +5).toInt(); if (briL == 255) { - devices[devId-1]->setValue(255); + devices[devId]->setValue(255); } else { - devices[devId-1]->setValue(briL+1); + devices[devId]->setValue(briL+1); } - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::bri); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::bri); } if (body.indexOf("xy") >0) //COLOR command (XY mode) { - devices[devId-1]->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat()); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::xy); + devices[devId]->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat()); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::xy); } if (body.indexOf("hue") >0) //COLOR command (HS mode) { - devices[devId-1]->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt()); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::hs); + devices[devId]->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt()); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::hs); } if (body.indexOf("ct") >0) //COLOR TEMP command (white spectrum) { - devices[devId-1]->setColor(body.substring(body.indexOf("ct") +4).toInt()); - devices[devId-1]->setPropertyChanged(EspalexaDeviceProperty::ct); + devices[devId]->setColor(body.substring(body.indexOf("ct") +4).toInt()); + devices[devId]->setPropertyChanged(EspalexaDeviceProperty::ct); } - devices[devId-1]->doCallback(); + devices[devId]->doCallback(); #ifdef ESPALEXA_DEBUG - if (devices[devId-1]->getLastChangedProperty() == EspalexaDeviceProperty::none) + if (devices[devId]->getLastChangedProperty() == EspalexaDeviceProperty::none) EA_DEBUGLN("STATE REQ WITHOUT BODY (likely Content-Type issue #6)"); #endif return true; @@ -519,7 +529,7 @@ public: String jsonTemp = "{"; for (int i = 0; isend(200, "application/json", jsonTemp); } else //client wants one light (devId) { - server->send(200, "application/json", deviceJsonString(devId)); + devId = decodeLightId(devId); + EA_DEBUGLN(devId); + if (devId > currentDeviceCount) + { + server->send(200, "application/json", "{}"); + } else { + server->send(200, "application/json", deviceJsonString(devId)); + } } return true; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 1b90af15..56ebeb08 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1905222 +#define VERSION 1906061 char versionString[] = "0.8.4"; @@ -491,6 +491,7 @@ bool oappendi(int i) //boot starts here void setup() { + pinMode(4, OUTPUT); digitalWrite(4, HIGH); wledInit(); } diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index f78ab818..2535672a 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -143,7 +143,7 @@ void wledInit() void beginStrip() { // Initialize NeoPixel Strip and button - strip.setColor(0); + strip.setColor(0, 0); strip.setBrightness(255); #ifdef BTNPIN diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index 60b69c5f..46c14074 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -34,7 +34,11 @@ void notify(byte callMode, bool followUp=false) udpOut[8] = effectCurrent; udpOut[9] = effectSpeed; udpOut[10] = col[3]; - udpOut[11] = 5; //compatibilityVersionByte: 0: old 1: supports white 2: supports secondary color 3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette + //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 tertiary color + udpOut[11] = 5; udpOut[12] = colSec[0]; udpOut[13] = colSec[1]; udpOut[14] = colSec[2]; @@ -43,6 +47,10 @@ void notify(byte callMode, bool followUp=false) udpOut[17] = (transitionDelay >> 0) & 0xFF; udpOut[18] = (transitionDelay >> 8) & 0xFF; udpOut[19] = effectPalette; + /*udpOut[20] = colTer[0]; + udpOut[21] = colTer[1]; + udpOut[22] = colTer[2]; + udpOut[23] = colTer[3];*/ IPAddress broadcastIp; broadcastIp = ~uint32_t(WiFi.subnetMask()) | uint32_t(WiFi.gatewayIP()); @@ -177,11 +185,18 @@ void handleNotifications() colSec[2] = udpIn[14]; colSec[3] = udpIn[15]; } + /*if (udpIn[11] > 5) + { + colTer[0] = udpIn[20]; + colTer[1] = udpIn[21]; + colTer[2] = udpIn[22]; + colSec[3] = udpIn[23]; + }*/ } } //apply effects from notification - if (receiveNotificationEffects || !someSel) + if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel)) { if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8]; effectSpeed = udpIn[9]; diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index c839e1fe..58399a22 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -35,8 +35,8 @@ void setAllLeds() { colorRGBtoRGBW(colT); colorRGBtoRGBW(colSecT); } - strip.setColor(colT[0], colT[1], colT[2], colT[3]); - strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], colSecT[3]); + strip.setColor(0, colT[0], colT[1], colT[2], colT[3]); + strip.setColor(1, colSecT[0], colSecT[1], colSecT[2], colSecT[3]); } diff --git a/wled00/wled18_server.ino b/wled00/wled18_server.ino index 2cfc0d5d..ba80702d 100644 --- a/wled00/wled18_server.ino +++ b/wled00/wled18_server.ino @@ -73,7 +73,7 @@ void initServer() AsyncCallbackJsonWebHandler* handler = new AsyncCallbackJsonWebHandler("/json", [](AsyncWebServerRequest *request, JsonVariant &json) { JsonObject& root = json.as(); if (!root.success()){request->send(500, "application/json", "{\"error\":\"Parsing failed\"}"); return;} - deserializeState(root); + if (deserializeState(root)) { serveJson(request); return; } //if JSON contains "v" (verbose response) request->send(200, "application/json", "{\"success\":true}"); }); server.addHandler(handler); diff --git a/wled00/wled19_json.ino b/wled00/wled19_json.ino index 0f07238c..c5e65d26 100644 --- a/wled00/wled19_json.ino +++ b/wled00/wled19_json.ino @@ -2,8 +2,10 @@ * JSON API (De)serialization */ -void deserializeState(JsonObject& root) +bool deserializeState(JsonObject& root) { + bool stateResponse = root["v"] | false; + bri = root["bri"] | bri; bool on = root["on"] | (bri > 0); @@ -32,6 +34,9 @@ void deserializeState(JsonObject& root) receiveNotifications = udpn["recv"] | receiveNotifications; bool noNotification = udpn["nn"]; //send no notification just for this request + int timein = root["time"] | -1; + if (timein != -1) setTime(timein); + int it = 0; JsonArray& segs = root["seg"]; for (JsonObject& elem : segs) @@ -40,14 +45,14 @@ void deserializeState(JsonObject& root) if (id < strip.getMaxSegments()) { WS2812FX::Segment& seg = strip.getSegment(id); - /*uint16_t start = elem["start"] | seg.start; + uint16_t start = elem["start"] | seg.start; int stop = elem["stop"] | -1; if (stop < 0) { uint16_t len = elem["len"]; stop = (len > 0) ? start + len : seg.stop; } - strip.setSegment(id, start, stop);*/ + strip.setSegment(id, start, stop); JsonArray& colarr = elem["col"]; if (colarr.success()) @@ -63,31 +68,37 @@ void deserializeState(JsonObject& root) byte cp = colX.copyTo(rgbw); seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF))); if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0; - //temporary - if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];} - if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];} + if (id == 0) //temporary + { + if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];} + if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];} + } } } } byte fx = elem["fx"] | seg.mode; - if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(fx); + if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx); seg.speed = elem["sx"] | seg.speed; seg.intensity = elem["ix"] | seg.intensity; - byte pal = elem["pal"] | seg.palette; - if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal); - seg.setOption(0, elem["sel"] | seg.getOption(0)); - seg.setOption(1, elem["rev"] | seg.getOption(1)); + seg.palette = elem["pal"] | seg.palette; + //if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal); + seg.setOption(0, elem["sel"] | seg.getOption(0)); //selected + seg.setOption(1, elem["rev"] | seg.getOption(1)); //reverse //int cln = seg_0["cln"]; //temporary - effectCurrent = seg.mode; - effectSpeed = seg.speed; - effectIntensity = seg.intensity; - effectPalette = seg.palette; + if (id == 0) { + effectCurrent = seg.mode; + effectSpeed = seg.speed; + effectIntensity = seg.intensity; + effectPalette = seg.palette; + } } it++; } colorUpdated(noNotification ? 5:1); + + return stateResponse; } void serializeState(JsonObject& root) @@ -110,15 +121,20 @@ void serializeState(JsonObject& root) udpn["recv"] = receiveNotifications; JsonArray& seg = root.createNestedArray("seg"); - JsonObject& seg0 = seg.createNestedObject(); - serializeSegment(seg0); + for (byte s = 0; s < strip.getMaxSegments(); s++) + { + WS2812FX::Segment sg = strip.getSegment(s); + if (sg.isActive()) + { + JsonObject& seg0 = seg.createNestedObject(); + serializeSegment(seg0, sg, s); + } + } } -void serializeSegment(JsonObject& root) +void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id) { - WS2812FX::Segment seg = strip.getSegment(0); - - //root["id"] = i; + root["id"] = id; root["start"] = seg.start; root["stop"] = seg.stop; root["len"] = seg.stop - seg.start; @@ -139,7 +155,7 @@ void serializeSegment(JsonObject& root) root["sx"] = seg.speed; root["ix"] = seg.intensity; root["pal"] = seg.palette; - root["sel"] = true; //seg.getOption(0); + root["sel"] = seg.isSelected(); root["rev"] = seg.getOption(1); root["cln"] = -1; }