2017-02-21 23:59:47 +01:00
|
|
|
|
void alexaOn();
|
|
|
|
|
void alexaOff();
|
2017-12-28 00:37:13 +01:00
|
|
|
|
void alexaDim();
|
2017-02-21 23:59:47 +01:00
|
|
|
|
|
|
|
|
|
void alexaInit()
|
|
|
|
|
{
|
|
|
|
|
if (alexaEnabled && WiFi.status() == WL_CONNECTED)
|
|
|
|
|
{
|
2018-01-07 22:52:48 +01:00
|
|
|
|
prepareIds();
|
|
|
|
|
|
|
|
|
|
udpConnected = connectUDP();
|
|
|
|
|
|
|
|
|
|
if (udpConnected) alexaInitPages();
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleAlexa()
|
|
|
|
|
{
|
|
|
|
|
if (alexaEnabled && WiFi.status() == WL_CONNECTED)
|
|
|
|
|
{
|
2018-01-07 22:52:48 +01:00
|
|
|
|
if(udpConnected){
|
|
|
|
|
// if there’s data available, read a packet
|
|
|
|
|
int packetSize = UDP.parsePacket();
|
|
|
|
|
if(packetSize) {
|
|
|
|
|
IPAddress remote = UDP.remoteIP();
|
|
|
|
|
int len = UDP.read(packetBuffer, 255);
|
|
|
|
|
if (len > 0) {
|
|
|
|
|
packetBuffer[len] = 0;
|
|
|
|
|
}
|
|
|
|
|
String request = packetBuffer;
|
|
|
|
|
|
|
|
|
|
if(request.indexOf("M-SEARCH") >= 0) {
|
|
|
|
|
if((request.indexOf("urn:Belkin:device:**") > 0) || (request.indexOf("ssdp:all") > 0) || (request.indexOf("upnp:rootdevice") > 0)) {
|
|
|
|
|
Serial.println("Responding to search request ...");
|
|
|
|
|
respondToSearch();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void alexaOn()
|
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
if (alexaOnMacro == 255)
|
2017-02-21 23:59:47 +01:00
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN");
|
2017-02-21 23:59:47 +01:00
|
|
|
|
} else
|
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
applyMacro(alexaOnMacro);
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
2018-01-07 22:52:48 +01:00
|
|
|
|
|
|
|
|
|
String body =
|
|
|
|
|
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>\r\n"
|
|
|
|
|
"<u:SetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">\r\n"
|
|
|
|
|
"<BinaryState>1</BinaryState>\r\n"
|
|
|
|
|
"</u:SetBinaryStateResponse>\r\n"
|
|
|
|
|
"</s:Body> </s:Envelope>";
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/xml", body.c_str());
|
|
|
|
|
|
|
|
|
|
Serial.print("Sending :");
|
|
|
|
|
Serial.println(body);
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void alexaOff()
|
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
if (alexaOffMacro == 255)
|
2017-02-21 23:59:47 +01:00
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN");
|
2017-02-21 23:59:47 +01:00
|
|
|
|
} else
|
|
|
|
|
{
|
2017-12-28 00:37:13 +01:00
|
|
|
|
applyMacro(alexaOffMacro);
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
2018-01-07 22:52:48 +01:00
|
|
|
|
|
|
|
|
|
String body =
|
|
|
|
|
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>\r\n"
|
|
|
|
|
"<u:SetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">\r\n"
|
|
|
|
|
"<BinaryState>0</BinaryState>\r\n"
|
|
|
|
|
"</u:SetBinaryStateResponse>\r\n"
|
|
|
|
|
"</s:Body> </s:Envelope>";
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/xml", body.c_str());
|
|
|
|
|
|
|
|
|
|
Serial.print("Sending :");
|
|
|
|
|
Serial.println(body);
|
2017-02-21 23:59:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 00:37:13 +01:00
|
|
|
|
void alexaDim(uint8_t bri)
|
|
|
|
|
{
|
|
|
|
|
String ct = (alexaNotify)?"win&IN&A=":"win&NN&IN&A=";
|
|
|
|
|
ct = ct + bri;
|
|
|
|
|
handleSet(ct);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-07 22:52:48 +01:00
|
|
|
|
void prepareIds() {
|
|
|
|
|
escapedMac = WiFi.macAddress();
|
|
|
|
|
escapedMac.replace(":", "");
|
|
|
|
|
escapedMac.toLowerCase();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void respondToSearch() {
|
|
|
|
|
Serial.println("");
|
|
|
|
|
Serial.print("Sending response to ");
|
|
|
|
|
Serial.println(UDP.remoteIP());
|
|
|
|
|
Serial.print("Port : ");
|
|
|
|
|
Serial.println(UDP.remotePort());
|
|
|
|
|
|
|
|
|
|
IPAddress localIP = WiFi.localIP();
|
|
|
|
|
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"
|
|
|
|
|
"EXT:\r\n"
|
|
|
|
|
"CACHE-CONTROL: max-age=%u\r\n" // SSDP_INTERVAL
|
|
|
|
|
"LOCATION: http://"+ String(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"
|
|
|
|
|
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
|
|
|
|
"USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::upnp:rootdevice\r\n" // _uuid::_deviceType
|
|
|
|
|
"\r\n";
|
|
|
|
|
|
|
|
|
|
UDP.beginPacket(UDP.remoteIP(), UDP.remotePort());
|
|
|
|
|
UDP.write(response.c_str());
|
|
|
|
|
UDP.endPacket();
|
|
|
|
|
|
|
|
|
|
Serial.println("Response sent !");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void alexaInitPages() {
|
|
|
|
|
server.on("/upnp/control/basicevent1", HTTP_POST, []() {
|
|
|
|
|
Serial.println("########## Responding to /upnp/control/basicevent1 ... ##########");
|
|
|
|
|
|
|
|
|
|
String request = server.arg(0);
|
|
|
|
|
Serial.print("request:");
|
|
|
|
|
Serial.println(request);
|
|
|
|
|
|
|
|
|
|
if(request.indexOf("SetBinaryState") >= 0) {
|
|
|
|
|
if(request.indexOf("<BinaryState>1</BinaryState>") >= 0) {
|
|
|
|
|
Serial.println("Got Turn on request");
|
|
|
|
|
alexaOn();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(request.indexOf("<BinaryState>0</BinaryState>") >= 0) {
|
|
|
|
|
Serial.println("Got Turn off request");
|
|
|
|
|
alexaOff();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(request.indexOf("GetBinaryState") >= 0) {
|
|
|
|
|
Serial.println("Got binary state request");
|
|
|
|
|
sendState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/plain", "");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.on("/eventservice.xml", HTTP_GET, [](){
|
|
|
|
|
Serial.println(" ########## Responding to eventservice.xml ... ########\n");
|
|
|
|
|
|
|
|
|
|
String eventservice_xml = "<scpd xmlns=\"urn:Belkin:service-1-0\">"
|
|
|
|
|
"<actionList>"
|
|
|
|
|
"<action>"
|
|
|
|
|
"<name>SetBinaryState</name>"
|
|
|
|
|
"<argumentList>"
|
|
|
|
|
"<argument>"
|
|
|
|
|
"<retval/>"
|
|
|
|
|
"<name>BinaryState</name>"
|
|
|
|
|
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
|
|
|
|
"<direction>in</direction>"
|
|
|
|
|
"</argument>"
|
|
|
|
|
"</argumentList>"
|
|
|
|
|
"</action>"
|
|
|
|
|
"<action>"
|
|
|
|
|
"<name>GetBinaryState</name>"
|
|
|
|
|
"<argumentList>"
|
|
|
|
|
"<argument>"
|
|
|
|
|
"<retval/>"
|
|
|
|
|
"<name>BinaryState</name>"
|
|
|
|
|
"<relatedStateVariable>BinaryState</relatedStateVariable>"
|
|
|
|
|
"<direction>out</direction>"
|
|
|
|
|
"</argument>"
|
|
|
|
|
"</argumentList>"
|
|
|
|
|
"</action>"
|
|
|
|
|
"</actionList>"
|
|
|
|
|
"<serviceStateTable>"
|
|
|
|
|
"<stateVariable sendEvents=\"yes\">"
|
|
|
|
|
"<name>BinaryState</name>"
|
|
|
|
|
"<dataType>Boolean</dataType>"
|
|
|
|
|
"<defaultValue>0</defaultValue>"
|
|
|
|
|
"</stateVariable>"
|
|
|
|
|
"<stateVariable sendEvents=\"yes\">"
|
|
|
|
|
"<name>level</name>"
|
|
|
|
|
"<dataType>string</dataType>"
|
|
|
|
|
"<defaultValue>0</defaultValue>"
|
|
|
|
|
"</stateVariable>"
|
|
|
|
|
"</serviceStateTable>"
|
|
|
|
|
"</scpd>\r\n"
|
|
|
|
|
"\r\n";
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/plain", eventservice_xml.c_str());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.on("/description.xml", HTTP_GET, [](){
|
|
|
|
|
Serial.println(" ########## Responding to setup.xml ... ########\n");
|
|
|
|
|
|
|
|
|
|
IPAddress localIP = WiFi.localIP();
|
|
|
|
|
char s[16];
|
|
|
|
|
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
|
|
|
|
|
|
|
|
|
String setup_xml = "<?xml version=\"1.0\" ?>"
|
|
|
|
|
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
|
|
|
|
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
|
|
|
|
"<URLBase>http://"+ String(s) +":80/</URLBase>"
|
|
|
|
|
"<device>"
|
|
|
|
|
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
|
|
|
|
"<friendlyName>Philips hue ("+ String(s) +")</friendlyName>"
|
|
|
|
|
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
|
|
|
|
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
|
|
|
|
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
|
|
|
|
"<modelName>Philips hue bridge 2012</modelName>"
|
|
|
|
|
"<modelNumber>929000226503</modelNumber>"
|
|
|
|
|
"<modelURL>http://www.meethue.com</modelURL>"
|
|
|
|
|
"<serialNumber>"+ escapedMac +"</serialNumber>"
|
|
|
|
|
"<UDN>uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"</UDN>"
|
|
|
|
|
"<presentationURL>index.html</presentationURL>"
|
|
|
|
|
"<iconList>"
|
|
|
|
|
" <icon>"
|
|
|
|
|
" <mimetype>image/png</mimetype>"
|
|
|
|
|
" <height>48</height>"
|
|
|
|
|
" <width>48</width>"
|
|
|
|
|
" <depth>24</depth>"
|
|
|
|
|
" <url>hue_logo_0.png</url>"
|
|
|
|
|
" </icon>"
|
|
|
|
|
" <icon>"
|
|
|
|
|
" <mimetype>image/png</mimetype>"
|
|
|
|
|
" <height>120</height>"
|
|
|
|
|
" <width>120</width>"
|
|
|
|
|
" <depth>24</depth>"
|
|
|
|
|
" <url>hue_logo_3.png</url>"
|
|
|
|
|
" </icon>"
|
|
|
|
|
"</iconList>"
|
|
|
|
|
"</device>"
|
|
|
|
|
"</root>";
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/xml", setup_xml.c_str());
|
|
|
|
|
|
|
|
|
|
Serial.print("Sending :");
|
|
|
|
|
Serial.println(setup_xml);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// openHAB support
|
|
|
|
|
server.on("/on.html", HTTP_GET, [](){
|
|
|
|
|
Serial.println("on req");
|
|
|
|
|
server.send(200, "text/plain", "turned on");
|
|
|
|
|
alexaOn();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.on("/off.html", HTTP_GET, [](){
|
|
|
|
|
Serial.println("off req");
|
|
|
|
|
server.send(200, "text/plain", "turned off");
|
|
|
|
|
alexaOff();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.on("/status.html", HTTP_GET, [](){
|
|
|
|
|
Serial.println("Got status request");
|
|
|
|
|
|
|
|
|
|
String statrespone = "0";
|
|
|
|
|
if (bri > 0) {
|
|
|
|
|
statrespone = "1";
|
|
|
|
|
}
|
|
|
|
|
server.send(200, "text/plain", statrespone);
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean connectUDP(){
|
|
|
|
|
boolean state = false;
|
|
|
|
|
|
|
|
|
|
Serial.println("");
|
|
|
|
|
Serial.println("Con UDP");
|
|
|
|
|
|
|
|
|
|
if(UDP.beginMulticast(WiFi.localIP(), ipMulti, portMulti)) {
|
|
|
|
|
Serial.println("Con success");
|
|
|
|
|
state = true;
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
Serial.println("Con failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sendState() {
|
|
|
|
|
|
|
|
|
|
String body =
|
|
|
|
|
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>\r\n"
|
|
|
|
|
"<u:GetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">\r\n"
|
|
|
|
|
"<BinaryState>";
|
|
|
|
|
|
|
|
|
|
body += ((bri>0) ? "1" : "0");
|
|
|
|
|
|
|
|
|
|
body += "</BinaryState>\r\n"
|
|
|
|
|
"</u:GetBinaryStateResponse>\r\n"
|
|
|
|
|
"</s:Body> </s:Envelope>\r\n";
|
|
|
|
|
|
|
|
|
|
server.send(200, "text/xml", body.c_str());
|
|
|
|
|
}
|
|
|
|
|
|