diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ccf3061..a4a7e5d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ### Development versions after 0.11.1 release +#### Build 2103220 + +- Version bump to 0.12.0-b2 "Hikari" +- Worked around an issue causing a critical decrease in framerate (wled.cpp l.240 block) +- Bump to Espalexa v2.7.0, fixing discovery + #### Build 2103210 - Version bump to 0.12.0-b1 "Hikari" diff --git a/package.json b/package.json index 959cdc30..3d32c8cf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wled", - "version": "0.12.0-b1", + "version": "0.12.0-b2", "description": "Tools for WLED project", "main": "tools/cdata.js", "directories": { diff --git a/platformio.ini b/platformio.ini index 8e7988a0..65497f90 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,10 +9,10 @@ # ------------------------------------------------------------------------------ # Travis CI binaries (comment this out with a ';' when building for your own board) -default_envs = travis_esp8266, travis_esp32 +;default_envs = travis_esp8266, travis_esp32 # Release binaries -; default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth +default_envs = nodemcuv2, esp01_1m_full, esp32dev, esp32_eth # Single binaries (uncomment your board) ; default_envs = nodemcuv2 diff --git a/wled00/html_other.h b/wled00/html_other.h index aa4d7c7e..977d450e 100644 --- a/wled00/html_other.h +++ b/wled00/html_other.h @@ -42,7 +42,7 @@ function B(){window.history.back()}function U(){document.getElementById("uf").st .bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}#msg{display:none}

WLED Software Update

-Installed version: 0.12.0-b1
Download the latest binary: Download the latest binary:

diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 98516f66..69a86881 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -375,7 +375,7 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form

Software Update


Enable ArduinoOTA:

About

WLED - version 0.12.0-b1


Contributors, dependencies and special thanks
A huge thank you to everyone who helped me create WLED!

diff --git a/wled00/set.cpp b/wled00/set.cpp index ff43c866..10973169 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -116,6 +116,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (busConfigs[s] != nullptr) delete busConfigs[s]; busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder, request->hasArg(cv)); + doInitBusses = true; } ledCount = request->arg(F("LC")).toInt(); diff --git a/wled00/src/dependencies/espalexa/Espalexa.h b/wled00/src/dependencies/espalexa/Espalexa.h index 5e7dc837..3bbfb44c 100644 --- a/wled00/src/dependencies/espalexa/Espalexa.h +++ b/wled00/src/dependencies/espalexa/Espalexa.h @@ -10,7 +10,7 @@ */ /* * @title Espalexa library - * @version 2.5.0 + * @version 2.7.0 * @author Christian Schwinne * @license MIT * @contributors d-999 @@ -25,7 +25,7 @@ //#define ESPALEXA_NO_SUBPAGE #ifndef ESPALEXA_MAXDEVICES - #define ESPALEXA_MAXDEVICES 10 //this limit only has memory reasons, set it higher should you need to + #define ESPALEXA_MAXDEVICES 10 //this limit only has memory reasons, set it higher should you need to, max 128 #endif //#define ESPALEXA_DEBUG @@ -50,7 +50,7 @@ #include "../network/Network.h" #ifdef ESPALEXA_DEBUG - #pragma message "Espalexa 2.5.0 debug mode" + #pragma message "Espalexa 2.7.0 debug mode" #define EA_DEBUG(x) Serial.print (x) #define EA_DEBUGLN(x) Serial.println (x) #else @@ -76,13 +76,14 @@ private: #endif uint8_t currentDeviceCount = 0; bool discoverable = true; + bool udpConnected = false; EspalexaDevice* devices[ESPALEXA_MAXDEVICES] = {}; //Keep in mind that Device IDs go from 1 to DEVICES, cpp arrays from 0 to DEVICES-1!! WiFiUDP espalexaUdp; IPAddress ipMulti; - bool udpConnected = false; + uint32_t mac24; //bottom 24 bits of mac String escapedMac=""; //lowercase mac address //private member functions @@ -119,33 +120,32 @@ private: void encodeLightId(uint8_t idx, char* out) { - //Unique id must be 12 character len - //use the last 10 characters of the MAC followed by the device id in hex value - //uniqueId: aabbccddeeii - uint8_t mac[6]; WiFi.macAddress(mac); - //shift the mac address to the left (discard first byte) - for (uint8_t i = 0; i < 5; i++) { - mac[i] = mac[i+1]; - } - mac[5] = idx; - - for (uint8_t i = 0; i < 6; i++) { - sprintf(out + i*2, "%.2x", mac[i]); - } + sprintf_P(out, PSTR("%02X:%02X:%02X:%02X:%02X:%02X:00:11-%02X"), mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], idx); } - - //device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001) - void deviceJsonString(uint8_t deviceId, char* buf) + + // construct 'globally unique' Json dict key fitting into signed int + inline int encodeLightKey(uint8_t idx) { - deviceId--; - if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error - EspalexaDevice* dev = devices[deviceId]; - - char buf_lightid[13]; - encodeLightId(deviceId + 1, buf_lightid); + //return idx +1; + static_assert(ESPALEXA_MAXDEVICES <= 128, ""); + return (mac24<<7) | idx; + } + + // get device index from Json key + uint8_t decodeLightKey(int key) + { + //return key -1; + return (((uint32_t)key>>7) == mac24) ? (key & 127U) : 255U; + } + + //device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001) + void deviceJsonString(EspalexaDevice* dev, char* buf) + { + char buf_lightid[27]; + encodeLightId(dev->getId() + 1, buf_lightid); char buf_col[80] = ""; //color support @@ -167,7 +167,7 @@ private: sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true}," "\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u" - "\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.5.0\"}") + "\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.7.0\"}") , (dev->getValue())?"true":"false", dev->getLastValue()-1, buf_col, buf_ct, buf_cm, typeString(dev->getType()), dev->getName().c_str(), modelidString(dev->getType()), static_cast(dev->getType()), buf_lightid); @@ -192,7 +192,7 @@ private: } res += "\r\nFree Heap: " + (String)ESP.getFreeHeap(); res += "\r\nUptime: " + (String)millis(); - res += "\r\n\r\nEspalexa library v2.5.0 by Christian Schwinne 2020"; + res += "\r\n\r\nEspalexa library v2.7.0 by Christian Schwinne 2021"; server->send(200, "text/plain", res); } #endif @@ -335,6 +335,9 @@ public: escapedMac.replace(":", ""); escapedMac.toLowerCase(); + String macSubStr = escapedMac.substring(6, 12); + mac24 = strtol(macSubStr.c_str(), 0, 16); + #ifdef ESPALEXA_ASYNC serverAsync = externalServer; #else @@ -390,48 +393,55 @@ public: } } - bool addDevice(EspalexaDevice* d) + // returns device index or 0 on failure + uint8_t addDevice(EspalexaDevice* d) { EA_DEBUG("Adding device "); EA_DEBUGLN((currentDeviceCount+1)); - if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false; - if (d == nullptr) return false; + if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0; + if (d == nullptr) return 0; d->setId(currentDeviceCount); devices[currentDeviceCount] = d; - currentDeviceCount++; - return true; + return ++currentDeviceCount; } //brightness-only callback - bool addDevice(String deviceName, BrightnessCallbackFunction callback, uint8_t initialValue = 0) + uint8_t addDevice(String deviceName, BrightnessCallbackFunction callback, uint8_t initialValue = 0) { EA_DEBUG("Constructing device "); EA_DEBUGLN((currentDeviceCount+1)); - if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false; + if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0; EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue); return addDevice(d); } //brightness-only callback - bool addDevice(String deviceName, ColorCallbackFunction callback, uint8_t initialValue = 0) + uint8_t addDevice(String deviceName, ColorCallbackFunction callback, uint8_t initialValue = 0) { EA_DEBUG("Constructing device "); EA_DEBUGLN((currentDeviceCount+1)); - if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false; + if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0; EspalexaDevice* d = new EspalexaDevice(deviceName, callback, initialValue); return addDevice(d); } - bool addDevice(String deviceName, DeviceCallbackFunction callback, EspalexaDeviceType t = EspalexaDeviceType::dimmable, uint8_t initialValue = 0) + uint8_t addDevice(String deviceName, DeviceCallbackFunction callback, EspalexaDeviceType t = EspalexaDeviceType::dimmable, uint8_t initialValue = 0) { EA_DEBUG("Constructing device "); EA_DEBUGLN((currentDeviceCount+1)); - if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return false; + if (currentDeviceCount >= ESPALEXA_MAXDEVICES) return 0; EspalexaDevice* d = new EspalexaDevice(deviceName, callback, t, initialValue); return addDevice(d); } - + + void renameDevice(uint8_t id, const String& deviceName) + { + unsigned int index = id - 1; + if (index < currentDeviceCount) + devices[index]->setName(deviceName); + } + //basic implementation of Philips hue api functions needed for basic Alexa control #ifdef ESPALEXA_ASYNC bool handleAlexaApiCall(AsyncWebServerRequest* request) @@ -450,6 +460,8 @@ public: bool handleAlexaApiCall(String req, String body) { #endif + EA_DEBUG("URL: "); + EA_DEBUGLN(req); EA_DEBUGLN("AlexaApiCall"); if (req.indexOf("api") <0) return false; //return if not an API call EA_DEBUGLN("ok"); @@ -458,34 +470,36 @@ public: { EA_DEBUGLN("devType"); body = ""; - server->send(200, "application/json", F("[{\"success\":{\"username\":\"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]")); + server->send(200, "application/json", F("[{\"success\":{\"username\":\"2BLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBGr\"}}]")); return true; } if ((req.indexOf("state") > 0) && (body.length() > 0)) //client wants to control light { - server->send(200, "application/json", F("[{\"success\":{\"/lights/1/state/\": true}}]")); - uint32_t devId = req.substring(req.indexOf("lights")+7).toInt(); EA_DEBUG("ls"); EA_DEBUGLN(devId); - EA_DEBUGLN(devId); - devId--; //zero-based for devices array - if (devId >= currentDeviceCount) return true; //return if invalid ID + unsigned idx = decodeLightKey(devId); + EA_DEBUGLN(idx); + char buf[50]; + sprintf_P(buf,PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId); + server->send(200, "application/json", buf); + if (idx >= currentDeviceCount) return true; //return if invalid ID + EspalexaDevice* dev = devices[idx]; - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::none); + dev->setPropertyChanged(EspalexaDeviceProperty::none); if (body.indexOf("false")>0) //OFF command { - devices[devId]->setValue(0); - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::off); - devices[devId]->doCallback(); + dev->setValue(0); + dev->setPropertyChanged(EspalexaDeviceProperty::off); + dev->doCallback(); return true; } if (body.indexOf("true") >0) //ON command { - devices[devId]->setValue(devices[devId]->getLastValue()); - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::on); + dev->setValue(dev->getLastValue()); + dev->setPropertyChanged(EspalexaDeviceProperty::on); } if (body.indexOf("bri") >0) //BRIGHTNESS command @@ -493,35 +507,35 @@ public: uint8_t briL = body.substring(body.indexOf("bri") +5).toInt(); if (briL == 255) { - devices[devId]->setValue(255); + dev->setValue(255); } else { - devices[devId]->setValue(briL+1); + dev->setValue(briL+1); } - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::bri); + dev->setPropertyChanged(EspalexaDeviceProperty::bri); } if (body.indexOf("xy") >0) //COLOR command (XY mode) { - devices[devId]->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat()); - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::xy); + dev->setColorXY(body.substring(body.indexOf("[") +1).toFloat(), body.substring(body.indexOf(",0") +1).toFloat()); + dev->setPropertyChanged(EspalexaDeviceProperty::xy); } if (body.indexOf("hue") >0) //COLOR command (HS mode) { - devices[devId]->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt()); - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::hs); + dev->setColor(body.substring(body.indexOf("hue") +5).toInt(), body.substring(body.indexOf("sat") +5).toInt()); + dev->setPropertyChanged(EspalexaDeviceProperty::hs); } if (body.indexOf("ct") >0) //COLOR TEMP command (white spectrum) { - devices[devId]->setColor(body.substring(body.indexOf("ct") +4).toInt()); - devices[devId]->setPropertyChanged(EspalexaDeviceProperty::ct); + dev->setColor(body.substring(body.indexOf("ct") +4).toInt()); + dev->setPropertyChanged(EspalexaDeviceProperty::ct); } - devices[devId]->doCallback(); + dev->doCallback(); #ifdef ESPALEXA_DEBUG - if (devices[devId]->getLastChangedProperty() == EspalexaDeviceProperty::none) + if (dev->getLastChangedProperty() == EspalexaDeviceProperty::none) EA_DEBUGLN("STATE REQ WITHOUT BODY (likely Content-Type issue #6)"); #endif return true; @@ -539,25 +553,31 @@ public: String jsonTemp = "{"; for (int i = 0; isend(200, "application/json", jsonTemp); } else //client wants one light (devId) { EA_DEBUGLN(devId); - if (devId > currentDeviceCount) - { + unsigned int idx = decodeLightKey(devId); + + if (idx >= currentDeviceCount) idx = 0; //send first device if invalid + if (currentDeviceCount == 0) { server->send(200, "application/json", "{}"); - } else { - char buf[512]; - deviceJsonString(devId, buf); - server->send(200, "application/json", buf); + return true; } + char buf[512]; + deviceJsonString(devices[idx], buf); + server->send(200, "application/json", buf); } return true; diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp index d7d0920f..fa643491 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp @@ -65,6 +65,11 @@ uint8_t EspalexaDevice::getValue() return _val; } +bool EspalexaDevice::getState() +{ + return _val; +} + uint8_t EspalexaDevice::getPercent() { uint16_t perc = _val * 100; @@ -111,7 +116,7 @@ uint32_t EspalexaDevice::getKelvin() uint32_t EspalexaDevice::getRGB() { if (_rgb != 0) return _rgb; //color has not changed - byte rgb[4]{0, 0, 0, 0}; + byte rgb[4]{0, 0, 0, 0}; if (_mode == EspalexaColorMode::none) return 0; @@ -277,6 +282,16 @@ void EspalexaDevice::setValue(uint8_t val) _val = val; } +void EspalexaDevice::setState(bool onoff) +{ + if (onoff) + { + setValue(_val_last); + } else { + setValue(0); + } +} + void EspalexaDevice::setPercent(uint8_t perc) { uint16_t val = perc * 255; diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.h b/wled00/src/dependencies/espalexa/EspalexaDevice.h index b7f2f184..3cf97fb6 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.h +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.h @@ -40,6 +40,8 @@ public: uint8_t getId(); EspalexaDeviceProperty getLastChangedProperty(); uint8_t getValue(); + uint8_t getLastValue(); //last value that was not off (1-255) + bool getState(); uint8_t getPercent(); uint8_t getDegrees(); uint16_t getHue(); @@ -59,6 +61,7 @@ public: void setId(uint8_t id); void setPropertyChanged(EspalexaDeviceProperty p); void setValue(uint8_t bri); + void setState(bool onoff); void setPercent(uint8_t perc); void setName(String name); void setColor(uint16_t ct); @@ -67,8 +70,6 @@ public: void setColor(uint8_t r, uint8_t g, uint8_t b); void doCallback(); - - uint8_t getLastValue(); //last value that was not off (1-255) }; #endif \ No newline at end of file diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 58e4a085..77de4200 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -236,7 +236,9 @@ void WLED::loop() } //LED settings have been saved, re-init busses - if (busConfigs[0] != nullptr) { + //This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate! + if (doInitBusses) { + doInitBusses = false; busses.removeAll(); uint32_t mem = 0; for (uint8_t i = 0; i < WLED_MAX_BUSSES; i++) { diff --git a/wled00/wled.h b/wled00/wled.h index b3eee5b8..3f74ef55 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -3,7 +3,7 @@ /* Main sketch, global variable declarations @title WLED project sketch - @version 0.12.0-b1 + @version 0.12.0-b2 @author Christian Schwinne */ @@ -174,7 +174,7 @@ #endif // Global Variable definitions -WLED_GLOBAL char versionString[] _INIT("0.12.0-b1"); +WLED_GLOBAL char versionString[] _INIT("0.12.0-b2"); #define WLED_CODENAME "Hikari" // AP and OTA default passwords (for maximum security change them!) @@ -560,7 +560,8 @@ WLED_GLOBAL bool e131NewData _INIT(false); // led fx library object WLED_GLOBAL BusManager busses _INIT(BusManager()); WLED_GLOBAL WS2812FX strip _INIT(WS2812FX()); -WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES]; //temporary, to remember values from network callback until after +WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after +WLED_GLOBAL bool doInitBusses _INIT(false); // Usermod manager WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());