Fixed Alexa discovery
This commit is contained in:
parent
c9cd7b087a
commit
c277ebb43e
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
### Development versions after 0.11.0 release
|
### Development versions after 0.11.0 release
|
||||||
|
|
||||||
|
#### Build 2012160
|
||||||
|
|
||||||
|
- Bump Espalexa to 2.5.0, fixing discovery (PR Espalexa/#152, originally PR #1497)
|
||||||
|
|
||||||
#### Build 2012150
|
#### Build 2012150
|
||||||
|
|
||||||
- Added Blends FX (PR #1491)
|
- Added Blends FX (PR #1491)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* @title Espalexa library
|
* @title Espalexa library
|
||||||
* @version 2.4.6
|
* @version 2.5.0
|
||||||
* @author Christian Schwinne
|
* @author Christian Schwinne
|
||||||
* @license MIT
|
* @license MIT
|
||||||
* @contributors d-999
|
* @contributors d-999
|
||||||
@ -50,7 +50,7 @@
|
|||||||
#include "../network/Network.h"
|
#include "../network/Network.h"
|
||||||
|
|
||||||
#ifdef ESPALEXA_DEBUG
|
#ifdef ESPALEXA_DEBUG
|
||||||
#pragma message "Espalexa 2.4.6 debug mode"
|
#pragma message "Espalexa 2.5.0 debug mode"
|
||||||
#define EA_DEBUG(x) Serial.print (x)
|
#define EA_DEBUG(x) Serial.print (x)
|
||||||
#define EA_DEBUGLN(x) Serial.println (x)
|
#define EA_DEBUGLN(x) Serial.println (x)
|
||||||
#else
|
#else
|
||||||
@ -60,6 +60,7 @@
|
|||||||
|
|
||||||
#include "EspalexaDevice.h"
|
#include "EspalexaDevice.h"
|
||||||
|
|
||||||
|
#define DEVICE_UNIQUE_ID_LENGTH 12
|
||||||
|
|
||||||
class Espalexa {
|
class Espalexa {
|
||||||
private:
|
private:
|
||||||
@ -116,17 +117,24 @@ private:
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
//Workaround functions courtesy of Sonoff-Tasmota
|
void encodeLightId(uint8_t idx, char* out)
|
||||||
uint32_t encodeLightId(uint8_t idx)
|
|
||||||
{
|
{
|
||||||
|
//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];
|
uint8_t mac[6];
|
||||||
WiFi.macAddress(mac);
|
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) {
|
//shift the mac address to the left (discard first byte)
|
||||||
return id & 0xF;
|
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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
||||||
@ -136,10 +144,8 @@ private:
|
|||||||
if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error
|
if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error
|
||||||
EspalexaDevice* dev = devices[deviceId];
|
EspalexaDevice* dev = devices[deviceId];
|
||||||
|
|
||||||
//char buf_bri[12] = "";
|
char buf_lightid[13];
|
||||||
//brightness support, add "bri" to JSON
|
encodeLightId(deviceId + 1, buf_lightid);
|
||||||
//if (dev->getType() != EspalexaDeviceType::onoff)
|
|
||||||
// sprintf(buf_bri,",\"bri\":%u", dev->getLastValue()-1);
|
|
||||||
|
|
||||||
char buf_col[80] = "";
|
char buf_col[80] = "";
|
||||||
//color support
|
//color support
|
||||||
@ -161,10 +167,10 @@ private:
|
|||||||
|
|
||||||
sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
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"
|
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
|
||||||
"\",\"uniqueid\":\"%u\",\"swversion\":\"espalexa-2.4.6\"}")
|
"\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.5.0\"}")
|
||||||
|
|
||||||
, (dev->getValue())?"true":"false", dev->getLastValue()-1, buf_col, buf_ct, buf_cm, typeString(dev->getType()),
|
, (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<uint8_t>(dev->getType()), encodeLightId(deviceId+1));
|
dev->getName().c_str(), modelidString(dev->getType()), static_cast<uint8_t>(dev->getType()), buf_lightid);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Espalexa status page /espalexa
|
//Espalexa status page /espalexa
|
||||||
@ -186,7 +192,7 @@ private:
|
|||||||
}
|
}
|
||||||
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
|
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
|
||||||
res += "\r\nUptime: " + (String)millis();
|
res += "\r\nUptime: " + (String)millis();
|
||||||
res += "\r\n\r\nEspalexa library v2.4.6 by Christian Schwinne 2020";
|
res += "\r\n\r\nEspalexa library v2.5.0 by Christian Schwinne 2020";
|
||||||
server->send(200, "text/plain", res);
|
server->send(200, "text/plain", res);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -222,7 +228,7 @@ private:
|
|||||||
"<URLBase>http://%s:80/</URLBase>"
|
"<URLBase>http://%s:80/</URLBase>"
|
||||||
"<device>"
|
"<device>"
|
||||||
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
||||||
"<friendlyName>Espalexa (%s)</friendlyName>"
|
"<friendlyName>Espalexa (%s:80)</friendlyName>"
|
||||||
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
||||||
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
||||||
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
||||||
@ -237,8 +243,8 @@ private:
|
|||||||
|
|
||||||
server->send(200, "text/xml", buf);
|
server->send(200, "text/xml", buf);
|
||||||
|
|
||||||
EA_DEBUG("Send setup.xml");
|
EA_DEBUGLN("Send setup.xml");
|
||||||
//EA_DEBUGLN(setup_xml);
|
EA_DEBUGLN(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
//init the server
|
//init the server
|
||||||
@ -290,7 +296,7 @@ private:
|
|||||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
|
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
|
||||||
"EXT:\r\n"
|
"EXT:\r\n"
|
||||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||||
@ -298,7 +304,7 @@ private:
|
|||||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
||||||
"hue-bridgeid: %s\r\n"
|
"hue-bridgeid: %s\r\n"
|
||||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
||||||
"USN: uuid:2f402f80-da50-11e1-9b23-%s::ssdp:all\r\n" // _uuid::_deviceType
|
"USN: uuid:2f402f80-da50-11e1-9b23-%s::upnp:rootdevice\r\n" // _uuid::_deviceType
|
||||||
"\r\n"),s,escapedMac.c_str(),escapedMac.c_str());
|
"\r\n"),s,escapedMac.c_str(),escapedMac.c_str());
|
||||||
|
|
||||||
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
|
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
|
||||||
@ -359,24 +365,28 @@ public:
|
|||||||
|
|
||||||
if (!udpConnected) return;
|
if (!udpConnected) return;
|
||||||
int packetSize = espalexaUdp.parsePacket();
|
int packetSize = espalexaUdp.parsePacket();
|
||||||
if (!packetSize) return; //no new udp packet
|
if (packetSize < 1) return; //no new udp packet
|
||||||
|
|
||||||
EA_DEBUGLN("Got UDP!");
|
EA_DEBUGLN("Got UDP!");
|
||||||
char packetBuffer[255]; //buffer to hold incoming udp packet
|
|
||||||
uint16_t len = espalexaUdp.read(packetBuffer, 254);
|
unsigned char packetBuffer[packetSize+1]; //buffer to hold incoming udp packet
|
||||||
if (len > 0) {
|
espalexaUdp.read(packetBuffer, packetSize);
|
||||||
packetBuffer[len] = 0;
|
packetBuffer[packetSize] = 0;
|
||||||
}
|
|
||||||
espalexaUdp.flush();
|
espalexaUdp.flush();
|
||||||
if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
|
if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
|
||||||
|
|
||||||
String request = packetBuffer;
|
const char* request = (const char *) packetBuffer;
|
||||||
if(request.indexOf("M-SEARCH") >= 0) {
|
if (strstr(request, "M-SEARCH") == nullptr) return;
|
||||||
EA_DEBUGLN(request);
|
|
||||||
if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) {
|
EA_DEBUGLN(request);
|
||||||
EA_DEBUGLN("Responding search req...");
|
if (strstr(request, "ssdp:disc") != nullptr && //short for "ssdp:discover"
|
||||||
respondToSearch();
|
(strstr(request, "upnp:rootd") != nullptr || //short for "upnp:rootdevice"
|
||||||
}
|
strstr(request, "ssdp:all") != nullptr ||
|
||||||
|
strstr(request, "asic:1") != nullptr )) //short for "device:basic:1"
|
||||||
|
{
|
||||||
|
EA_DEBUGLN("Responding search req...");
|
||||||
|
respondToSearch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,13 +462,12 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.indexOf("state") > 0) //client wants to control light
|
if ((req.indexOf("state") > 0) && (body.length() > 0)) //client wants to control light
|
||||||
{
|
{
|
||||||
server->send(200, "application/json", F("[{\"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();
|
uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
|
||||||
EA_DEBUG("ls"); EA_DEBUGLN(devId);
|
EA_DEBUG("ls"); EA_DEBUGLN(devId);
|
||||||
devId = decodeLightId(devId);
|
|
||||||
EA_DEBUGLN(devId);
|
EA_DEBUGLN(devId);
|
||||||
devId--; //zero-based for devices array
|
devId--; //zero-based for devices array
|
||||||
if (devId >= currentDeviceCount) return true; //return if invalid ID
|
if (devId >= currentDeviceCount) return true; //return if invalid ID
|
||||||
@ -530,7 +539,7 @@ public:
|
|||||||
String jsonTemp = "{";
|
String jsonTemp = "{";
|
||||||
for (int i = 0; i<currentDeviceCount; i++)
|
for (int i = 0; i<currentDeviceCount; i++)
|
||||||
{
|
{
|
||||||
jsonTemp += "\"" + String(encodeLightId(i+1)) + "\":";
|
jsonTemp += "\"" + String(i+1) + "\":";
|
||||||
char buf[512];
|
char buf[512];
|
||||||
deviceJsonString(i+1, buf);
|
deviceJsonString(i+1, buf);
|
||||||
jsonTemp += buf;
|
jsonTemp += buf;
|
||||||
@ -540,7 +549,6 @@ public:
|
|||||||
server->send(200, "application/json", jsonTemp);
|
server->send(200, "application/json", jsonTemp);
|
||||||
} else //client wants one light (devId)
|
} else //client wants one light (devId)
|
||||||
{
|
{
|
||||||
devId = decodeLightId(devId);
|
|
||||||
EA_DEBUGLN(devId);
|
EA_DEBUGLN(devId);
|
||||||
if (devId > currentDeviceCount)
|
if (devId > currentDeviceCount)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2012150
|
#define VERSION 2012160
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
|
Loading…
Reference in New Issue
Block a user