Skip to content

Commit

Permalink
More Wemo tuning
Browse files Browse the repository at this point in the history
More Wemo tuning
  • Loading branch information
arendst committed Mar 26, 2019
1 parent bf8845c commit f83a5bb
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 44 deletions.
13 changes: 13 additions & 0 deletions sonoff/support.ino
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,19 @@ char* RemoveSpace(char* p)
return p;
}

char* LowerCase(char* dest, const char* source)
{
char* write = dest;
const char* read = source;
char ch = '.';

while (ch != '\0') {
ch = *read++;
*write++ = tolower(ch);
}
return dest;
}

char* UpperCase(char* dest, const char* source)
{
char* write = dest;
Expand Down
97 changes: 53 additions & 44 deletions sonoff/xplg_wemohue.ino
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,22 @@
#include <Ticker.h>
Ticker TickerMSearch;

bool udp_connected = false;

char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet
IPAddress ipMulticast(239,255,255,250); // Simple Service Discovery Protocol (SSDP)
uint32_t port_multicast = 1900; // Multicast address and port

bool udp_response_mutex = false; // M-Search response mutex to control re-entry
IPAddress udp_remote_ip; // M-Search remote IP address
uint16_t udp_remote_port; // M-Search remote port

bool udp_connected = false;
bool udp_response_mutex = false; // M-Search response mutex to control re-entry

/*********************************************************************************************\
* UPNP search targets
\*********************************************************************************************/

const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**";
const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice";
const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all";
const char SSDP_ALL[] PROGMEM = "ssdp:all";

/*********************************************************************************************\
* WeMo UPNP support routines
\*********************************************************************************************/
Expand All @@ -50,12 +56,12 @@ const char WEMO_MSEARCH[] PROGMEM =
"CACHE-CONTROL: max-age=86400\r\n"
"DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n"
"EXT:\r\n"
"LOCATION: http://{r1:80/setup.xml\r\n"
"LOCATION: http://%s:80/setup.xml\r\n"
"OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
"01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n"
"SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"
"ST: {r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
"USN: uuid:{r2::{r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
"ST: %s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
"USN: uuid:%s::%s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice
"X-User-Agent: redsonic\r\n"
"\r\n";

Expand All @@ -81,15 +87,15 @@ void WemoRespondToMSearch(int echo_type)

TickerMSearch.detach();
if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) {
String response = FPSTR(WEMO_MSEARCH);
response.replace("{r1", WiFi.localIP().toString());
response.replace("{r2", WemoUuid());
char type[24];
if (1 == echo_type) { // type1 echo 1g & dot 2g
response.replace("{r3", F("urn:Belkin:device:**"));
strcpy_P(type, URN_BELKIN_DEVICE);
} else { // type2 echo 2g (echo, plus, show)
response.replace("{r3", F("upnp:rootdevice"));
strcpy_P(type, UPNP_ROOTDEVICE);
}
PortUdp.write(response.c_str());
char response[400];
snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type);
PortUdp.write(response);
PortUdp.endPacket();
snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT));
} else {
Expand Down Expand Up @@ -208,7 +214,8 @@ bool UdpDisconnect(void)
bool UdpConnect(void)
{
if (!udp_connected) {
if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) {
// Simple Service Discovery Protocol (SSDP)
if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) {
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED));
udp_response_mutex = false;
udp_connected = true;
Expand Down Expand Up @@ -238,28 +245,30 @@ void PollUdp(void)
udp_remote_ip = PortUdp.remoteIP();
udp_remote_port = PortUdp.remotePort();

AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"),
udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer);
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"),
// udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer);

UpperCase(packet_buffer, packet_buffer);
uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec

LowerCase(packet_buffer, packet_buffer);
RemoveSpace(packet_buffer);
if (EMUL_WEMO == Settings.flag2.emulation) {
if (strstr_P(packet_buffer, PSTR("URN:BELKIN:DEVICE:**"))) { // type1 echo dot 2g, echo 1g's
TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 1);
if (strstr_P(packet_buffer, URN_BELKIN_DEVICE)) { // type1 echo dot 2g, echo 1g's
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1);
return;
}
else if (strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || // type2 Echo 2g (echo & echo plus)
strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) ||
strstr_P(packet_buffer, PSTR("SSDP:ALL"))) {
TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 2);
else if (strstr_P(packet_buffer, UPNP_ROOTDEVICE) || // type2 Echo 2g (echo & echo plus)
strstr_P(packet_buffer, SSDPSEARCH_ALL) ||
strstr_P(packet_buffer, SSDP_ALL)) {
TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2);
return;
}
} else {
if (strstr_P(packet_buffer, PSTR("URN:SCHEMAS-UPNP-ORG:DEVICE:BASIC:1")) ||
strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) ||
strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) ||
strstr_P(packet_buffer, PSTR("SSDP:ALL"))) {
TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch);
if (strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) ||
strstr_P(packet_buffer, UPNP_ROOTDEVICE) ||
strstr_P(packet_buffer, SSDPSEARCH_ALL) ||
strstr_P(packet_buffer, SSDP_ALL)) {
TickerMSearch.attach_ms(response_delay, HueRespondToMSearch);
return;
}
}
Expand Down Expand Up @@ -343,9 +352,9 @@ const char WEMO_METASERVICE_XML[] PROGMEM =
const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM =
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
"<s:Body>"
"<u:SetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
"<BinaryState>{x1</BinaryState>"
"</u:SetBinaryStateResponse>"
"<u:%cetBinaryStateResponse xmlns:u=\"urn:Belkin:service:basicevent:1\">"
"<BinaryState>%d</BinaryState>"
"</u:%cetBinaryStateResponse>"
"</s:Body>"
"</s:Envelope>\r\n";

Expand Down Expand Up @@ -386,30 +395,30 @@ void HandleUpnpEvent(void)
{
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT));

String request = WebServer->arg(0);
char event[500];
strlcpy(event, WebServer->arg(0).c_str(), sizeof(event));

// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), request.c_str());
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event);

String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP);
//differentiate get and set state
if (request.indexOf(F("SetBinaryState")) > 0) {
char state = 'G';
if (strstr_P(event, PSTR("SetBinaryState"))) {
state = 'S';
uint8_t power = POWER_TOGGLE;
if (request.indexOf(F("State>1</Binary")) > 0) {
if (strstr_P(event, PSTR("State>1</Binary"))) {
power = POWER_ON;
}
else if (request.indexOf(F("State>0</Binary")) > 0) {
else if (strstr_P(event, PSTR("State>0</Binary"))) {
power = POWER_OFF;
}
if (power != POWER_TOGGLE) {
uint8_t device = (light_type) ? devices_present : 1; // Select either a configured light or relay1
ExecuteCommandPower(device, power, SRC_WEMO);
}
}
else if(request.indexOf(F("GetBinaryState")) > 0){
state_xml.replace(F("Set"), F("Get"));
}
state_xml.replace("{x1", String(bitRead(power, devices_present -1)));
WSSend(200, CT_XML, state_xml);

snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state);
WSSend(200, CT_XML, event);
}

void HandleUpnpService(void)
Expand Down

0 comments on commit f83a5bb

Please sign in to comment.