diff --git a/CHANGELOG.md b/CHANGELOG.md index 8decb2fa..5dbfeeea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ### Development versions after 0.10.0 release +#### Build 2005100 + +- Update to Espalexa v2.4.6 (+1.6kB free heap memory) +- Added `m5atom` PlatformIO environment + #### Build 2005090 - Default to ESP8266 Arduino core v2.7.1 in PlatformIO diff --git a/platformio.ini b/platformio.ini index 32c438e3..dad6f950 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,6 +38,7 @@ default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev ; default_envs = esp8285_5CH_H801 ; default_envs = d1_mini_5CH_Shojo_PCB ; default_envs = wemos_shield_esp32 +; default_envs = m5atom [common] # ------------------------------------------------------------------------------ @@ -202,6 +203,7 @@ build_flags = ${common.build_flags_esp8266} [env:d1_mini] board = d1_mini platform = ${common.platform_latest} +upload_speed = 921500 board_build.ldscript = ${common.ldscript_4m1m} build_flags = ${common.build_flags_esp8266} @@ -315,3 +317,11 @@ build_flags = ${common.build_flags_esp32} -D LEDPIN=16 -D RLYPIN=19 -D BTNPIN=17 lib_ignore = ESPAsyncTCP ESPAsyncUDP + +[env:m5atom] +board = esp32dev +build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39 +lib_ignore = + ESPAsyncTCP + ESPAsyncUDP +platform = espressif32@1.11.2 \ No newline at end of file diff --git a/wled00/FX.h b/wled00/FX.h index e3d591f9..728ab224 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -220,7 +220,7 @@ class WS2812FX { uint8_t intensity; uint8_t palette; uint8_t mode; - uint8_t options; //bit pattern: msb first: transitional tbd tbd tbd tbd paused reverse selected + uint8_t options; //bit pattern: msb first: transitional needspixelstate tbd tbd (paused) on reverse selected uint8_t grouping, spacing; uint8_t opacity; uint32_t colors[NUM_COLORS]; diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 25e460e2..3843a350 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -72,6 +72,7 @@ void WS2812FX::service() { now = nowUp + timebase; if (nowUp - _lastShow < MIN_SHOW_DELAY) return; bool doShow = false; + for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++) { _segment_index = i; diff --git a/wled00/const.h b/wled00/const.h index 533a5f27..8a4a59dc 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -86,6 +86,8 @@ #define SEG_OPTION_SELECTED 0 #define SEG_OPTION_REVERSED 1 #define SEG_OPTION_ON 2 +#define SEG_OPTION_PAUSED 3 //unused +#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor #define SEG_OPTION_TRANSITIONAL 7 //EEPROM size diff --git a/wled00/src/dependencies/espalexa/Espalexa.h b/wled00/src/dependencies/espalexa/Espalexa.h index 7a1312f8..c088be60 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.5 + * @version 2.4.6 * @author Christian Schwinne * @license MIT * @contributors d-999 @@ -49,7 +49,7 @@ #include #ifdef ESPALEXA_DEBUG - #pragma message "Espalexa 2.4.5 debug mode" + #pragma message "Espalexa 2.4.6 debug mode" #define EA_DEBUG(x) Serial.print (x) #define EA_DEBUGLN(x) Serial.println (x) #else @@ -81,35 +81,29 @@ private: WiFiUDP espalexaUdp; IPAddress ipMulti; bool udpConnected = false; - char packetBuffer[255]; //buffer to hold incoming udp packet String escapedMac=""; //lowercase mac address //private member functions - String boolString(bool st) - { - return(st)?"true":"false"; - } - - String modeString(EspalexaColorMode m) + const char* modeString(EspalexaColorMode m) { if (m == EspalexaColorMode::xy) return "xy"; if (m == EspalexaColorMode::hs) return "hs"; return "ct"; } - String typeString(EspalexaDeviceType t) + const char* typeString(EspalexaDeviceType t) { switch (t) { - case EspalexaDeviceType::dimmable: return "Dimmable light"; - case EspalexaDeviceType::whitespectrum: return "Color temperature light"; - case EspalexaDeviceType::color: return "Color light"; - case EspalexaDeviceType::extendedcolor: return "Extended color light"; + case EspalexaDeviceType::dimmable: return PSTR("Dimmable light"); + case EspalexaDeviceType::whitespectrum: return PSTR("Color temperature light"); + case EspalexaDeviceType::color: return PSTR("Color light"); + case EspalexaDeviceType::extendedcolor: return PSTR("Extended color light"); } - return "Light"; + return ""; } - String modelidString(EspalexaDeviceType t) + const char* modelidString(EspalexaDeviceType t) { switch (t) { @@ -118,7 +112,7 @@ private: case EspalexaDeviceType::color: return "LST001"; case EspalexaDeviceType::extendedcolor: return "LCT015"; } - return "Plug"; + return ""; } //Workaround functions courtesy of Sonoff-Tasmota @@ -135,38 +129,38 @@ private: } //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) + void deviceJsonString(uint8_t deviceId, char* buf) { deviceId--; - if (deviceId >= currentDeviceCount) return "{}"; //error + if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error EspalexaDevice* dev = devices[deviceId]; - - String json = "{\"state\":{\"on\":"; - json += boolString(dev->getValue()); - if (dev->getType() != EspalexaDeviceType::onoff) //bri support - { - json += ",\"bri\":" + String(dev->getLastValue()-1); - if (static_cast(dev->getType()) > 2) //color support - { - json += ",\"hue\":" + String(dev->getHue()) + ",\"sat\":" + String(dev->getSat()); - json += ",\"effect\":\"none\",\"xy\":[" + String(dev->getX()) + "," + String(dev->getY()) + "]"; - } - if (static_cast(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color) //white spectrum support - { - json += ",\"ct\":" + String(dev->getCt()); - } - } - json += ",\"alert\":\"none"; - if (static_cast(dev->getType()) > 1) json += "\",\"colormode\":\"" + modeString(dev->getColorMode()); - json += "\",\"mode\":\"homeautomation\",\"reachable\":true},"; - json += "\"type\":\"" + typeString(dev->getType()); - json += "\",\"name\":\"" + dev->getName(); - json += "\",\"modelid\":\"" + modelidString(dev->getType()); - json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast(dev->getType())); - json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1)); - json += "\",\"swversion\":\"espalexa-2.4.5\"}"; - return json; + //char buf_bri[12] = ""; + //brightness support, add "bri" to JSON + //if (dev->getType() != EspalexaDeviceType::onoff) + // sprintf(buf_bri,",\"bri\":%u", dev->getLastValue()-1); + + char buf_col[80] = ""; + //color support + if (static_cast(dev->getType()) > 2) + sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]") + ,dev->getHue(), dev->getSat(), dev->getX(), dev->getY()); + + char buf_ct[16] = ""; + //white spectrum support + if (static_cast(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color) + sprintf(buf_ct, ",\"ct\":%u", dev->getCt()); + + char buf_cm[20] = ""; + if (static_cast(dev->getType()) > 1) + sprintf(buf_cm,PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode())); + + 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\":\"%u\",\"swversion\":\"espalexa-2.4.6\"}") + + , (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()), encodeLightId(deviceId+1)); } //Espalexa status page /espalexa @@ -181,14 +175,14 @@ private: res += "Value of device " + String(i+1) + " (" + dev->getName() + "): " + String(dev->getValue()) + " (" + typeString(dev->getType()); if (static_cast(dev->getType()) > 1) //color support { - res += ", colormode=" + modeString(dev->getColorMode()) + ", r=" + String(dev->getR()) + ", g=" + String(dev->getG()) + ", b=" + String(dev->getB()); + res += ", colormode=" + String(modeString(dev->getColorMode())) + ", r=" + String(dev->getR()) + ", g=" + String(dev->getG()) + ", b=" + String(dev->getB()); res +=", ct=" + String(dev->getCt()) + ", hue=" + String(dev->getHue()) + ", sat=" + String(dev->getSat()) + ", x=" + String(dev->getX()) + ", y=" + String(dev->getY()); } res += ")\r\n"; } res += "\r\nFree Heap: " + (String)ESP.getFreeHeap(); res += "\r\nUptime: " + (String)millis(); - res += "\r\n\r\nEspalexa library v2.4.5 by Christian Schwinne 2020"; + res += "\r\n\r\nEspalexa library v2.4.6 by Christian Schwinne 2020"; server->send(200, "text/plain", res); } #endif @@ -206,7 +200,7 @@ private: EA_DEBUGLN("Body: " + body); if(!handleAlexaApiCall(server)) #endif - server->send(404, "text/plain", "Not Found (espalexa-internal)"); + server->send(404, "text/plain", "Not Found (espalexa)"); } //send description.xml device property page @@ -216,30 +210,31 @@ private: IPAddress localIP = WiFi.localIP(); char s[16]; sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); - - String setup_xml = "" + char buf[1024]; + + sprintf_P(buf,PSTR("" "" "10" - "http://"+ String(s) +":80/" + "http://%s:80/" "" "urn:schemas-upnp-org:device:Basic:1" - "Espalexa ("+ String(s) +")" + "Espalexa (%s)" "Royal Philips Electronics" "http://www.philips.com" "Philips hue Personal Wireless Lighting" "Philips hue bridge 2012" "929000226503" "http://www.meethue.com" - ""+ escapedMac +"" - "uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"" + "%s" + "uuid:2f402f80-da50-11e1-9b23-%s" "index.html" "" - ""; + ""),s,s,escapedMac.c_str(),escapedMac.c_str()); - server->send(200, "text/xml", setup_xml.c_str()); + server->send(200, "text/xml", buf); - EA_DEBUG("Sending :"); - EA_DEBUGLN(setup_xml); + EA_DEBUG("Send setup.xml"); + //EA_DEBUGLN(setup_xml); } //init the server @@ -290,22 +285,23 @@ private: char s[16]; sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); - String response = - "HTTP/1.1 200 OK\r\n" + char buf[1024]; + + sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n" "EXT:\r\n" "CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL - "LOCATION: http://"+ String(s) +":80/description.xml\r\n" + "LOCATION: http://%s:80/description.xml\r\n" "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber - "hue-bridgeid: "+ escapedMac +"\r\n" + "hue-bridgeid: %s\r\n" "ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType - "USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::ssdp:all\r\n" // _uuid::_deviceType - "\r\n"; + "USN: uuid:2f402f80-da50-11e1-9b23-%s::ssdp:all\r\n" // _uuid::_deviceType + "\r\n"),s,escapedMac.c_str(),escapedMac.c_str()); espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort()); #ifdef ARDUINO_ARCH_ESP32 - espalexaUdp.write((uint8_t*)response.c_str(), response.length()); + espalexaUdp.write((uint8_t*)buf, strlen(buf)); #else - espalexaUdp.write(response.c_str()); + espalexaUdp.write(buf); #endif espalexaUdp.endPacket(); } @@ -362,7 +358,8 @@ public: if (!packetSize) return; //no new udp packet EA_DEBUGLN("Got UDP!"); - int len = espalexaUdp.read(packetBuffer, 254); + char packetBuffer[255]; //buffer to hold incoming udp packet + uint16_t len = espalexaUdp.read(packetBuffer, 254); if (len > 0) { packetBuffer[len] = 0; } @@ -370,10 +367,9 @@ public: if (!discoverable) return; //do not reply to M-SEARCH if not discoverable String request = packetBuffer; - if(request.indexOf("M-SEA") >= 0) { //M-SEARCH + if(request.indexOf("M-SEARCH") >= 0) { EA_DEBUGLN(request); - //match upnp:rootdevice, device:basic:1, ssdp:all and ssdp:discover - if(request.indexOf("np:rootd") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("dp:all") > 0 || request.indexOf("dp:dis") > 0) { + if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) { EA_DEBUGLN("Responding search req..."); respondToSearch(); } @@ -448,13 +444,13 @@ public: { EA_DEBUGLN("devType"); body = ""; - server->send(200, "application/json", "[{\"success\":{\"username\":\"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]"); + server->send(200, "application/json", F("[{\"success\":{\"username\":\"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]")); return true; } if (req.indexOf("state") > 0) //client wants to control light { - server->send(200, "application/json", "[{\"success\":{\"/lights/1/state/\": true}}]"); + 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); @@ -531,7 +527,9 @@ public: for (int i = 0; isend(200, "application/json", "{}"); } else { - server->send(200, "application/json", deviceJsonString(devId)); + char buf[512]; + deviceJsonString(devId, buf); + server->send(200, "application/json", buf); } } diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp index 520cf441..8bdd780d 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.cpp +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.cpp @@ -28,6 +28,7 @@ EspalexaDevice::EspalexaDevice(String deviceName, DeviceCallbackFunction gnCallb _callbackDev = gnCallback; _type = t; if (t == EspalexaDeviceType::onoff) _type = EspalexaDeviceType::dimmable; //on/off is broken, so make dimmable device instead + if (t == EspalexaDeviceType::whitespectrum) _mode = EspalexaColorMode::ct; _val = initialValue; _val_last = _val; } diff --git a/wled00/src/dependencies/espalexa/EspalexaDevice.h b/wled00/src/dependencies/espalexa/EspalexaDevice.h index 4ebdd2b8..0653a418 100644 --- a/wled00/src/dependencies/espalexa/EspalexaDevice.h +++ b/wled00/src/dependencies/espalexa/EspalexaDevice.h @@ -1,6 +1,6 @@ #ifndef EspalexaDevice_h #define EspalexaDevice_h -#include + #include "Arduino.h" #include diff --git a/wled00/wled.h b/wled00/wled.h index a2f4288d..b98b979c 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2005090 +#define VERSION 2005100 // ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).