kopia lustrzana https://github.com/Aircoookie/WLED
				
				
				
			Fixed Alexa discovery
							rodzic
							
								
									c9cd7b087a
								
							
						
					
					
						commit
						c277ebb43e
					
				| 
						 | 
				
			
			@ -2,6 +2,10 @@
 | 
			
		|||
 | 
			
		||||
### 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
 | 
			
		||||
 | 
			
		||||
-   Added Blends FX (PR #1491)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
 */
 | 
			
		||||
/*
 | 
			
		||||
 * @title Espalexa library
 | 
			
		||||
 * @version 2.4.6
 | 
			
		||||
 * @version 2.5.0
 | 
			
		||||
 * @author Christian Schwinne
 | 
			
		||||
 * @license MIT
 | 
			
		||||
 * @contributors d-999
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +50,7 @@
 | 
			
		|||
#include "../network/Network.h"
 | 
			
		||||
 | 
			
		||||
#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_DEBUGLN(x) Serial.println (x)
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +60,7 @@
 | 
			
		|||
 | 
			
		||||
#include "EspalexaDevice.h"
 | 
			
		||||
 | 
			
		||||
#define DEVICE_UNIQUE_ID_LENGTH 12
 | 
			
		||||
 | 
			
		||||
class Espalexa {
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			@ -116,17 +117,24 @@ private:
 | 
			
		|||
    return "";
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //Workaround functions courtesy of Sonoff-Tasmota
 | 
			
		||||
  uint32_t encodeLightId(uint8_t idx)
 | 
			
		||||
  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);
 | 
			
		||||
    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;
 | 
			
		||||
    //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]);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //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
 | 
			
		||||
    EspalexaDevice* dev = devices[deviceId];
 | 
			
		||||
    
 | 
			
		||||
    //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_lightid[13];
 | 
			
		||||
    encodeLightId(deviceId + 1, buf_lightid);
 | 
			
		||||
    
 | 
			
		||||
    char buf_col[80] = "";
 | 
			
		||||
    //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},"
 | 
			
		||||
                   "\"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->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
 | 
			
		||||
| 
						 | 
				
			
			@ -186,7 +192,7 @@ private:
 | 
			
		|||
    }
 | 
			
		||||
    res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
 | 
			
		||||
    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);
 | 
			
		||||
  }
 | 
			
		||||
  #endif
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +228,7 @@ private:
 | 
			
		|||
        "<URLBase>http://%s:80/</URLBase>"
 | 
			
		||||
        "<device>"
 | 
			
		||||
          "<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
 | 
			
		||||
          "<friendlyName>Espalexa (%s)</friendlyName>"
 | 
			
		||||
          "<friendlyName>Espalexa (%s:80)</friendlyName>"
 | 
			
		||||
          "<manufacturer>Royal Philips Electronics</manufacturer>"
 | 
			
		||||
          "<manufacturerURL>http://www.philips.com</manufacturerURL>"
 | 
			
		||||
          "<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
 | 
			
		||||
| 
						 | 
				
			
			@ -237,8 +243,8 @@ private:
 | 
			
		|||
          
 | 
			
		||||
    server->send(200, "text/xml", buf);
 | 
			
		||||
    
 | 
			
		||||
    EA_DEBUG("Send setup.xml");
 | 
			
		||||
    //EA_DEBUGLN(setup_xml);
 | 
			
		||||
    EA_DEBUGLN("Send setup.xml");
 | 
			
		||||
    EA_DEBUGLN(buf);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  //init the server
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +296,7 @@ private:
 | 
			
		|||
    sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			@ -298,7 +304,7 @@ private:
 | 
			
		|||
      "SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
 | 
			
		||||
      "hue-bridgeid: %s\r\n"
 | 
			
		||||
      "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());
 | 
			
		||||
 | 
			
		||||
    espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
 | 
			
		||||
| 
						 | 
				
			
			@ -359,24 +365,28 @@ public:
 | 
			
		|||
    
 | 
			
		||||
    if (!udpConnected) return;   
 | 
			
		||||
    int packetSize = espalexaUdp.parsePacket();    
 | 
			
		||||
    if (!packetSize) return; //no new udp packet
 | 
			
		||||
    if (packetSize < 1) return; //no new udp packet
 | 
			
		||||
    
 | 
			
		||||
    EA_DEBUGLN("Got UDP!");
 | 
			
		||||
    char packetBuffer[255]; //buffer to hold incoming udp packet
 | 
			
		||||
    uint16_t len = espalexaUdp.read(packetBuffer, 254);
 | 
			
		||||
    if (len > 0) {
 | 
			
		||||
      packetBuffer[len] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned char packetBuffer[packetSize+1]; //buffer to hold incoming udp packet
 | 
			
		||||
    espalexaUdp.read(packetBuffer, packetSize);
 | 
			
		||||
    packetBuffer[packetSize] = 0;
 | 
			
		||||
  
 | 
			
		||||
    espalexaUdp.flush();
 | 
			
		||||
    if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
 | 
			
		||||
    
 | 
			
		||||
    String request = packetBuffer;
 | 
			
		||||
    if(request.indexOf("M-SEARCH") >= 0) {
 | 
			
		||||
      EA_DEBUGLN(request);
 | 
			
		||||
      if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) {
 | 
			
		||||
        EA_DEBUGLN("Responding search req...");
 | 
			
		||||
        respondToSearch();
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
    const char* request = (const char *) packetBuffer;
 | 
			
		||||
    if (strstr(request, "M-SEARCH") == nullptr) return;
 | 
			
		||||
 | 
			
		||||
    EA_DEBUGLN(request);
 | 
			
		||||
    if (strstr(request, "ssdp:disc")  != nullptr &&  //short for "ssdp:discover"
 | 
			
		||||
        (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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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}}]"));
 | 
			
		||||
 | 
			
		||||
      uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
 | 
			
		||||
      EA_DEBUG("ls"); EA_DEBUGLN(devId);
 | 
			
		||||
      devId = decodeLightId(devId);
 | 
			
		||||
      EA_DEBUGLN(devId);
 | 
			
		||||
      devId--; //zero-based for devices array
 | 
			
		||||
      if (devId >= currentDeviceCount) return true; //return if invalid ID
 | 
			
		||||
| 
						 | 
				
			
			@ -530,7 +539,7 @@ public:
 | 
			
		|||
        String jsonTemp = "{";
 | 
			
		||||
        for (int i = 0; i<currentDeviceCount; i++)
 | 
			
		||||
        {
 | 
			
		||||
          jsonTemp += "\"" + String(encodeLightId(i+1)) + "\":";
 | 
			
		||||
          jsonTemp += "\"" + String(i+1) + "\":";
 | 
			
		||||
          char buf[512];
 | 
			
		||||
          deviceJsonString(i+1, buf);
 | 
			
		||||
          jsonTemp += buf;
 | 
			
		||||
| 
						 | 
				
			
			@ -540,7 +549,6 @@ public:
 | 
			
		|||
        server->send(200, "application/json", jsonTemp);
 | 
			
		||||
      } else //client wants one light (devId)
 | 
			
		||||
      {
 | 
			
		||||
        devId = decodeLightId(devId);
 | 
			
		||||
        EA_DEBUGLN(devId);
 | 
			
		||||
        if (devId > currentDeviceCount)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
//#define WLED_USE_MY_CONFIG
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue