From 9d57e2cbc706c503e71acc651ed47e6e09496614 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Mon, 3 Jun 2019 23:23:39 +0200 Subject: [PATCH] (2.4.3) Fixed Alexa apps and groups issue --- library.properties | 2 +- readme.md | 2 +- src/Espalexa.h | 89 +++++++++++++++++++++++++++------------------- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/library.properties b/library.properties index cf6a0c5..1e98d6e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Espalexa -version=2.4.2 +version=2.4.3 author=Christian Schwinne maintainer=Christian Schwinne sentence=Library to control an ESP module with the Alexa voice assistant diff --git a/readme.md b/readme.md index 499f172..980fd14 100644 --- a/readme.md +++ b/readme.md @@ -96,7 +96,7 @@ Here is an overview of the devices (light types) Espalexa can emulate: | EspalexaDeviceType::whitespectrum | Color temperature adjustment not working on Dot | | EspalexaDeviceType::color | Works as intended (dimming + color) | | EspalexaDeviceType::extendedcolor | Color temperature adjustment not working on Dot | -| EspalexaDeviceType::onoff (experimental) | No control from app possible, only voice | +| EspalexaDeviceType::onoff (experimental) | Works, but is treated as dimmable by Alexa | See the example `EspalexaFullyFeatured` to learn how to define each device type and use the new EspalexaDevice pointer callback function type! diff --git a/src/Espalexa.h b/src/Espalexa.h index 997fada..64e7e41 100644 --- a/src/Espalexa.h +++ b/src/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 @@ class Espalexa { 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 @@ class Espalexa { 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 @@ class Espalexa { } 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 @@ class Espalexa { ""+ escapedMac +"" "uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"" "index.html" - "" - " " - " image/png" - " 48" - " 48" - " 24" - " hue_logo_0.png" - " " - "" "" ""; @@ -450,22 +455,27 @@ class Espalexa { { 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 @@ class Espalexa { 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 @@ class Espalexa { 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;