Skip to content

Commit c277ebb

Browse files
committed
Fixed Alexa discovery
1 parent c9cd7b0 commit c277ebb

File tree

3 files changed

+52
-40
lines changed

3 files changed

+52
-40
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
### Development versions after 0.11.0 release
44

5+
#### Build 2012160
6+
7+
- Bump Espalexa to 2.5.0, fixing discovery (PR Espalexa/#152, originally PR #1497)
8+
59
#### Build 2012150
610

711
- Added Blends FX (PR #1491)

wled00/src/dependencies/espalexa/Espalexa.h

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
/*
1212
* @title Espalexa library
13-
* @version 2.4.6
13+
* @version 2.5.0
1414
* @author Christian Schwinne
1515
* @license MIT
1616
* @contributors d-999
@@ -50,7 +50,7 @@
5050
#include "../network/Network.h"
5151

5252
#ifdef ESPALEXA_DEBUG
53-
#pragma message "Espalexa 2.4.6 debug mode"
53+
#pragma message "Espalexa 2.5.0 debug mode"
5454
#define EA_DEBUG(x) Serial.print (x)
5555
#define EA_DEBUGLN(x) Serial.println (x)
5656
#else
@@ -60,6 +60,7 @@
6060

6161
#include "EspalexaDevice.h"
6262

63+
#define DEVICE_UNIQUE_ID_LENGTH 12
6364

6465
class Espalexa {
6566
private:
@@ -116,17 +117,24 @@ class Espalexa {
116117
return "";
117118
}
118119

119-
//Workaround functions courtesy of Sonoff-Tasmota
120-
uint32_t encodeLightId(uint8_t idx)
120+
void encodeLightId(uint8_t idx, char* out)
121121
{
122+
//Unique id must be 12 character len
123+
//use the last 10 characters of the MAC followed by the device id in hex value
124+
//uniqueId: aabbccddeeii
125+
122126
uint8_t mac[6];
123127
WiFi.macAddress(mac);
124-
uint32_t id = (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (idx & 0xF);
125-
return id;
126-
}
127128

128-
uint32_t decodeLightId(uint32_t id) {
129-
return id & 0xF;
129+
//shift the mac address to the left (discard first byte)
130+
for (uint8_t i = 0; i < 5; i++) {
131+
mac[i] = mac[i+1];
132+
}
133+
mac[5] = idx;
134+
135+
for (uint8_t i = 0; i < 6; i++) {
136+
sprintf(out + i*2, "%.2x", mac[i]);
137+
}
130138
}
131139

132140
//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 @@ class Espalexa {
136144
if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error
137145
EspalexaDevice* dev = devices[deviceId];
138146

139-
//char buf_bri[12] = "";
140-
//brightness support, add "bri" to JSON
141-
//if (dev->getType() != EspalexaDeviceType::onoff)
142-
// sprintf(buf_bri,",\"bri\":%u", dev->getLastValue()-1);
147+
char buf_lightid[13];
148+
encodeLightId(deviceId + 1, buf_lightid);
143149

144150
char buf_col[80] = "";
145151
//color support
@@ -161,10 +167,10 @@ class Espalexa {
161167

162168
sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
163169
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
164-
"\",\"uniqueid\":\"%u\",\"swversion\":\"espalexa-2.4.6\"}")
170+
"\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.5.0\"}")
165171

166172
, (dev->getValue())?"true":"false", dev->getLastValue()-1, buf_col, buf_ct, buf_cm, typeString(dev->getType()),
167-
dev->getName().c_str(), modelidString(dev->getType()), static_cast<uint8_t>(dev->getType()), encodeLightId(deviceId+1));
173+
dev->getName().c_str(), modelidString(dev->getType()), static_cast<uint8_t>(dev->getType()), buf_lightid);
168174
}
169175

170176
//Espalexa status page /espalexa
@@ -186,7 +192,7 @@ class Espalexa {
186192
}
187193
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
188194
res += "\r\nUptime: " + (String)millis();
189-
res += "\r\n\r\nEspalexa library v2.4.6 by Christian Schwinne 2020";
195+
res += "\r\n\r\nEspalexa library v2.5.0 by Christian Schwinne 2020";
190196
server->send(200, "text/plain", res);
191197
}
192198
#endif
@@ -222,7 +228,7 @@ class Espalexa {
222228
"<URLBase>http://%s:80/</URLBase>"
223229
"<device>"
224230
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
225-
"<friendlyName>Espalexa (%s)</friendlyName>"
231+
"<friendlyName>Espalexa (%s:80)</friendlyName>"
226232
"<manufacturer>Royal Philips Electronics</manufacturer>"
227233
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
228234
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
@@ -237,8 +243,8 @@ class Espalexa {
237243

238244
server->send(200, "text/xml", buf);
239245

240-
EA_DEBUG("Send setup.xml");
241-
//EA_DEBUGLN(setup_xml);
246+
EA_DEBUGLN("Send setup.xml");
247+
EA_DEBUGLN(buf);
242248
}
243249

244250
//init the server
@@ -290,15 +296,15 @@ class Espalexa {
290296
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
291297

292298
char buf[1024];
293-
299+
294300
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
295301
"EXT:\r\n"
296302
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
297303
"LOCATION: http://%s:80/description.xml\r\n"
298304
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
299305
"hue-bridgeid: %s\r\n"
300306
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
301-
"USN: uuid:2f402f80-da50-11e1-9b23-%s::ssdp:all\r\n" // _uuid::_deviceType
307+
"USN: uuid:2f402f80-da50-11e1-9b23-%s::upnp:rootdevice\r\n" // _uuid::_deviceType
302308
"\r\n"),s,escapedMac.c_str(),escapedMac.c_str());
303309

304310
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
@@ -359,24 +365,28 @@ class Espalexa {
359365

360366
if (!udpConnected) return;
361367
int packetSize = espalexaUdp.parsePacket();
362-
if (!packetSize) return; //no new udp packet
368+
if (packetSize < 1) return; //no new udp packet
363369

364370
EA_DEBUGLN("Got UDP!");
365-
char packetBuffer[255]; //buffer to hold incoming udp packet
366-
uint16_t len = espalexaUdp.read(packetBuffer, 254);
367-
if (len > 0) {
368-
packetBuffer[len] = 0;
369-
}
371+
372+
unsigned char packetBuffer[packetSize+1]; //buffer to hold incoming udp packet
373+
espalexaUdp.read(packetBuffer, packetSize);
374+
packetBuffer[packetSize] = 0;
375+
370376
espalexaUdp.flush();
371377
if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
372-
373-
String request = packetBuffer;
374-
if(request.indexOf("M-SEARCH") >= 0) {
375-
EA_DEBUGLN(request);
376-
if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) {
377-
EA_DEBUGLN("Responding search req...");
378-
respondToSearch();
379-
}
378+
379+
const char* request = (const char *) packetBuffer;
380+
if (strstr(request, "M-SEARCH") == nullptr) return;
381+
382+
EA_DEBUGLN(request);
383+
if (strstr(request, "ssdp:disc") != nullptr && //short for "ssdp:discover"
384+
(strstr(request, "upnp:rootd") != nullptr || //short for "upnp:rootdevice"
385+
strstr(request, "ssdp:all") != nullptr ||
386+
strstr(request, "asic:1") != nullptr )) //short for "device:basic:1"
387+
{
388+
EA_DEBUGLN("Responding search req...");
389+
respondToSearch();
380390
}
381391
}
382392

@@ -452,13 +462,12 @@ class Espalexa {
452462
return true;
453463
}
454464

455-
if (req.indexOf("state") > 0) //client wants to control light
465+
if ((req.indexOf("state") > 0) && (body.length() > 0)) //client wants to control light
456466
{
457467
server->send(200, "application/json", F("[{\"success\":{\"/lights/1/state/\": true}}]"));
458468

459469
uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
460470
EA_DEBUG("ls"); EA_DEBUGLN(devId);
461-
devId = decodeLightId(devId);
462471
EA_DEBUGLN(devId);
463472
devId--; //zero-based for devices array
464473
if (devId >= currentDeviceCount) return true; //return if invalid ID
@@ -530,7 +539,7 @@ class Espalexa {
530539
String jsonTemp = "{";
531540
for (int i = 0; i<currentDeviceCount; i++)
532541
{
533-
jsonTemp += "\"" + String(encodeLightId(i+1)) + "\":";
542+
jsonTemp += "\"" + String(i+1) + "\":";
534543
char buf[512];
535544
deviceJsonString(i+1, buf);
536545
jsonTemp += buf;
@@ -540,7 +549,6 @@ class Espalexa {
540549
server->send(200, "application/json", jsonTemp);
541550
} else //client wants one light (devId)
542551
{
543-
devId = decodeLightId(devId);
544552
EA_DEBUGLN(devId);
545553
if (devId > currentDeviceCount)
546554
{

wled00/wled.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*/
99

1010
// version code in format yymmddb (b = daily build)
11-
#define VERSION 2012150
11+
#define VERSION 2012160
1212

1313
//uncomment this if you have a "my_config.h" file you'd like to use
1414
//#define WLED_USE_MY_CONFIG

0 commit comments

Comments
 (0)