3.9.7 20170129
* Fix possible WS2812 exceptions when using emulation
* Add command Emulation to dynamic configure Belkin WeMo and Hue Bridge
for Alexa
This commit is contained in:
arendst 2017-01-29 21:36:12 +01:00
parent c0d98c8945
commit 7d7d14ae38
8 changed files with 152 additions and 132 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **3.9.6** - See ```sonoff/_releasenotes.ino``` for change information.
Current version is **3.9.7** - See ```sonoff/_releasenotes.ino``` for change information.
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.

Binary file not shown.

View File

@ -1,4 +1,8 @@
/* 3.9.6 20170129
/* 3.9.7 20170129
* Fix possible WS2812 exceptions when using emulation
* Add command Emulation to dynamic configure Belkin WeMo and Hue Bridge for Alexa
*
* 3.9.6 20170129
* Add dynamic sleep for WS2812 animation (#1)
*
* 3.9.5 20170128

View File

@ -10,7 +10,7 @@
* ====================================================
*/
#define VERSION 0x03090600 // 3.9.6
#define VERSION 0x03090700 // 3.9.7
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth};
@ -19,6 +19,7 @@ enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, MAX_WIFI_OPTION};
enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, MAX_SWITCH_OPTION};
enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION};
enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
#include "sonoff_template.h"
@ -311,6 +312,8 @@ struct SYSCFG {
uint8_t led_width;
uint16_t led_wakeup;
uint8_t emulation;
} sysCfg;
struct TIME_T {
@ -422,7 +425,7 @@ void CFG_DefaultSet()
sysCfg.model = 0;
sysCfg.timezone = APP_TIMEZONE;
strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl));
strlcpy(sysCfg.ex_friendlyname, FRIENDLY_NAME1, sizeof(sysCfg.ex_friendlyname));
strlcpy(sysCfg.ex_friendlyname, FRIENDLY_NAME, sizeof(sysCfg.ex_friendlyname));
sysCfg.seriallog_level = SERIAL_LOG_LEVEL;
sysCfg.sta_active = 0;
@ -506,10 +509,10 @@ void CFG_DefaultSet()
sysCfg.ws_width = 1;
sysCfg.ws_wakeup = 0;
strlcpy(sysCfg.friendlyname[0], FRIENDLY_NAME1, sizeof(sysCfg.friendlyname[0]));
strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME2, sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME3, sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME4, sizeof(sysCfg.friendlyname[3]));
strlcpy(sysCfg.friendlyname[0], FRIENDLY_NAME, sizeof(sysCfg.friendlyname[0]));
strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3]));
for (byte i = 0; i < MAX_GPIO_PIN; i++) sysCfg.my_module.gp.io[i] = 0;
@ -526,6 +529,8 @@ void CFG_DefaultSet()
strlcpy(sysCfg.switch_topic, "0", sizeof(sysCfg.switch_topic));
sysCfg.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
sysCfg.mqtt_enabled = MQTT_USE;
sysCfg.emulation = EMULATION;
}
@ -678,9 +683,9 @@ void CFG_Delta()
}
if (sysCfg.version < 0x03020500) { // 3.2.5 - Add parameter
strlcpy(sysCfg.friendlyname[0], sysCfg.ex_friendlyname, sizeof(sysCfg.friendlyname[0]));
strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME2, sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME3, sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME4, sizeof(sysCfg.friendlyname[3]));
strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3]));
}
if (sysCfg.version < 0x03020800) { // 3.2.8 - Add parameter
strlcpy(sysCfg.switch_topic, sysCfg.button_topic, sizeof(sysCfg.switch_topic));
@ -707,6 +712,9 @@ void CFG_Delta()
sysCfg.led_width = 0;
sysCfg.led_wakeup = 0;
}
if (sysCfg.version < 0x03090700) { // 3.9.7 - Add parameter
sysCfg.emulation = EMULATION;
}
sysCfg.version = VERSION;
}
@ -1003,9 +1011,9 @@ void mqtt_reconnect()
mqtt_connected();
return;
}
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
if (mqttflag > 1) {
#ifdef USE_MQTT_TLS
addLog_P(LOG_LEVEL_INFO, PSTR("MQTT: Verify TLS fingerprint..."));
@ -1389,14 +1397,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
else if (!strcmp(type,"FRIENDLYNAME") && (index > 0) && (index <= 4)) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.friendlyname[0]))) {
if (index == 1)
strlcpy(sysCfg.friendlyname[0], (payload == 1) ? FRIENDLY_NAME1 : dataBuf, sizeof(sysCfg.friendlyname[0]));
else if (index == 2)
strlcpy(sysCfg.friendlyname[1], (payload == 1) ? FRIENDLY_NAME2 : dataBuf, sizeof(sysCfg.friendlyname[1]));
else if (index == 3)
strlcpy(sysCfg.friendlyname[2], (payload == 1) ? FRIENDLY_NAME3 : dataBuf, sizeof(sysCfg.friendlyname[2]));
else if (index == 4)
strlcpy(sysCfg.friendlyname[3], (payload == 1) ? FRIENDLY_NAME4 : dataBuf, sizeof(sysCfg.friendlyname[3]));
if (index == 1) {
snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME));
} else {
snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), index);
}
strlcpy(sysCfg.friendlyname[index -1], (payload == 1) ? stemp1 : dataBuf, sizeof(sysCfg.friendlyname[index -1]));
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"FriendlyName%d\":\"%s\"}"), index, sysCfg.friendlyname[index -1]);
}
@ -1424,6 +1430,15 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebLog\":%d}"), sysCfg.weblog_level);
}
#ifdef USE_EMULATION
else if (!strcmp(type,"EMULATION")) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
sysCfg.emulation = payload;
restartflag = 2;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Emulation\":%d}"), sysCfg.emulation);
}
#endif // USE_EMULATION
#endif // USE_WEBSERVER
else if (!strcmp(type,"UNITS")) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
@ -1669,7 +1684,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"%s%s, PulseTime, BlinkTime, BlinkCount"), (Maxdevice == 1) ? "Power, Light" : "Power1, Power2, Light1 Light2", (sysCfg.module != MOTOR) ? ", PowerOnState" : "");
#ifdef USE_WEBSERVER
snprintf_P(svalue, sizeof(svalue), PSTR("%s, Weblog, Webserver"), svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("%s, Weblog, Webserver, Emulation"), svalue);
#endif
if (swt_flg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, SwitchMode"), svalue);
#ifdef USE_I2C
@ -2521,9 +2536,9 @@ void loop()
pollDnsWeb();
#endif // USE_WEBSERVER
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
pollUDP();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#ifdef USE_EMULATION
if (sysCfg.emulation) pollUDP();
#endif // USE_EMULATION
if (millis() >= timerxs) stateloop();
if (sysCfg.mqtt_enabled) mqttClient.loop();

View File

@ -375,9 +375,9 @@ void WIFI_config(uint8_t type)
{
if (!_wificonfigflag) {
if (type == WIFI_RETRY) return;
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
WiFi.disconnect(); // Solve possible Wifi hangs
_wificonfigflag = type;
_wifiConfigCounter = WIFI_CONFIG_SEC; // Allow up to WIFI_CONFIG_SECS seconds for phone to provide ssid/pswd
@ -412,9 +412,9 @@ void WIFI_begin(uint8_t flag)
const char PhyMode[] = " BGN";
char log[LOGSZ];
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
if (!strncmp(ESP.getSdkVersion(),"1.5.3",5)) {
addLog_P(LOG_LEVEL_DEBUG, "Wifi: Patch issue 2186");
WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186
@ -541,14 +541,14 @@ void WIFI_Check(uint8_t param)
} else {
stopWebserver();
}
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
UDP_Connect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#ifdef USE_EMULATION
if (sysCfg.emulation) UDP_Connect();
#endif // USE_EMULATION
#endif // USE_WEBSERVER
} else {
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
mDNSbegun = false;
}
}

View File

@ -79,13 +79,10 @@
// -- HTTP ----------------------------------------
#define USE_WEBSERVER // Enable web server and wifi manager (+43k code, +2k mem) - Disable by //
#define FRIENDLY_NAME1 "Sonoff" // [FriendlyName1] Friendlyname up to 32 characters used by webpages and Alexa
#define FRIENDLY_NAME2 "Sonoff2" // [FriendlyName2] Friendlyname up to 32 characters used by Alexa
#define FRIENDLY_NAME3 "Sonoff3" // [FriendlyName3] Friendlyname up to 32 characters used by Alexa
#define FRIENDLY_NAME4 "Sonoff4" // [FriendlyName4] Friendlyname up to 32 characters used by Alexa
#define FRIENDLY_NAME "Sonoff" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa
#define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin)
// #define USE_WEMO_EMULATION // Enable Belkin WeMo PowerSwitch emulation for Alexa (+4k code, +2k mem)
// #define USE_HUE_EMULATION // Enable Hue Bridge emulation for Alexa (+5k code, +2k mem)
#define USE_EMULATION // Enable Belkin WeMo and Hue Bridge emulation for Alexa (+11k code, +2k mem)
#define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo or Hue Bridge emulation (EMUL_NONE, EMUL_WEMO or EMUL_HUE)
// -- mDNS ----------------------------------------
#define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem)

View File

@ -158,7 +158,16 @@ const char HTTP_FORM_LOG3[] PROGMEM =
const char HTTP_FORM_OTHER[] PROGMEM =
"<fieldset><legend><b>&nbsp;Other parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<input id='w' name='w' value='5' hidden><input id='r' name='r' value='1' hidden>"
"<br/><input style='width:10%;float:left' id='r1' name='r1' type='checkbox'{r1}><b>MQTT enable</b><br/>";
"<br/><input style='width:10%;float:left' id='b1' name='b1' type='checkbox'{r1}><b>MQTT enable</b><br/>";
const char HTTP_FORM_OTHER2[] PROGMEM =
"<br/><b>Friendly Name {1</b> ({2)<br/><input id='a{1' name='a{1' length=32 placeholder='{2' value='{3'><br/>";
#ifdef USE_EMULATION
const char HTTP_FORM_OTHER3[] PROGMEM =
"<br/><fieldset><legend><b>&nbsp;Emulation&nbsp;</b></legend>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='0'{r2}><b>None</b><br/>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='1'{r3}><b>Belkin WeMo</b><br/>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='2'{r4}><b>Hue Bridge</b><br/>";
#endif // USE_EMULATION
const char HTTP_FORM_END[] PROGMEM =
"<br/><button type='submit'>Save</button></form></fieldset>";
const char HTTP_FORM_UPG[] PROGMEM =
@ -188,7 +197,7 @@ const char HTTP_END[] PROGMEM =
"</div>"
"</body>"
"</html>";
#ifdef USE_WEMO_EMULATION
#ifdef USE_EMULATION
const char WEMO_EVENTSERVICE_XML[] PROGMEM =
"<?scpd xmlns=\"urn:Belkin:service-1-0\"?>"
"<actionList>"
@ -241,8 +250,6 @@ const char WEMO_SETUP_XML[] PROGMEM =
"</device>"
"</root>\r\n"
"\r\n";
#endif // USE_WEMO_EMULATION
#ifdef USE_HUE_EMULATION
const char HUE_DESCRIPTION_XML[] PROGMEM =
"<?xml version=\"1.0\"?>"
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
@ -261,7 +268,6 @@ const char HUE_DESCRIPTION_XML[] PROGMEM =
"</device>"
"</root>\r\n"
"\r\n";
const char HUE_LIGHT_STATUS_JSON[] PROGMEM =
"{\"state\":"
"{\"on\":{state},"
@ -280,10 +286,9 @@ const char HUE_LIGHT_STATUS_JSON[] PROGMEM =
"\"uniqueid\":\"{j2}\","
"\"swversion\":\"66012040\""
"}";
const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM =
"{\"success\":{\"{api}/{id}/{cmd}\":{res}}}";
#endif // USE_HUE_EMULATION
#endif // USE_EMULATION
#define DNS_PORT 53
enum http_t {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER};
@ -325,14 +330,14 @@ void startWebserver(int type, IPAddress ipweb)
webServer->on("/in", handleInfo);
webServer->on("/rb", handleRestart);
webServer->on("/fwlink", handleRoot); // Microsoft captive portal. Maybe not needed. Might be handled by notFound handler.
#ifdef USE_WEMO_EMULATION
webServer->on("/upnp/control/basicevent1", HTTP_POST, handleUPnPevent);
webServer->on("/eventservice.xml", handleUPnPservice);
webServer->on("/setup.xml", handleUPnPsetup);
#endif // USE_WEMO_EMULATION
#ifdef USE_HUE_EMULATION
webServer->on("/description.xml", handleUPnPsetup);
#endif // USE_HUE_EMULATION
#ifdef USE_EMULATION
if (sysCfg.emulation == EMUL_WEMO) {
webServer->on("/upnp/control/basicevent1", HTTP_POST, handleUPnPevent);
webServer->on("/eventservice.xml", handleUPnPservice);
webServer->on("/setup.xml", handleUPnPsetupWemo);
}
if (sysCfg.emulation == EMUL_HUE) webServer->on("/description.xml", handleUPnPsetupHue);
#endif // USE_EMULATION
webServer->onNotFound(handleNotFound);
}
webServer->begin(); // Web server start
@ -572,9 +577,9 @@ void handleWifi(boolean scan)
page.replace("{v}", "Configure Wifi");
if (scan) {
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
int n = WiFi.scanNetworks();
addLog_P(LOG_LEVEL_DEBUG, PSTR("Wifi: Scan done"));
@ -748,20 +753,30 @@ void handleOther()
return;
}
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle other config"));
char stemp[40];
String page = FPSTR(HTTP_HEAD);
page.replace("{v}", "Configure Other");
page += FPSTR(HTTP_FORM_OTHER);
page.replace("{r1}", (sysCfg.mqtt_enabled) ? " checked" : "");
for (int i = 0; i < Maxdevice; i++) {
page += F("<br/><b>Friendly Name {1</b> ({2)<br/><input id='a{1' name='a{1' length=32 placeholder='{2' value='{3'><br/>");
page += FPSTR(HTTP_FORM_OTHER2);
page.replace("{1", "1");
page.replace("{2", FRIENDLY_NAME);
page.replace("{3", String(sysCfg.friendlyname[0]));
#ifdef USE_EMULATION
page += FPSTR(HTTP_FORM_OTHER3);
page.replace("{r2}", (sysCfg.emulation == EMUL_NONE) ? " checked" : "");
page.replace("{r3}", (sysCfg.emulation == EMUL_WEMO) ? " checked" : "");
page.replace("{r4}", (sysCfg.emulation == EMUL_HUE) ? " checked" : "");
for (int i = 1; i < Maxdevice; i++) {
page += FPSTR(HTTP_FORM_OTHER2);
page.replace("{1", String(i +1));
if (i == 0) page.replace("{2", FRIENDLY_NAME1);
else if (i == 1) page.replace("{2", FRIENDLY_NAME2);
else if (i == 2) page.replace("{2", FRIENDLY_NAME3);
else if (i == 3) page.replace("{2", FRIENDLY_NAME4);
snprintf_P(stemp, sizeof(stemp), PSTR(FRIENDLY_NAME"%d"), i +1);
page.replace("{2", stemp);
page.replace("{3", String(sysCfg.friendlyname[i]));
}
page += F("<br/></fieldset>");
#endif // USE_EMULATION
page += FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
showPage(page);
@ -823,13 +838,16 @@ void handleSave()
break;
#endif // USE_DOMOTICZ
case 5:
sysCfg.mqtt_enabled = webServer->hasArg("r1");
strlcpy(sysCfg.friendlyname[0], (!strlen(webServer->arg("a1").c_str())) ? FRIENDLY_NAME1 : webServer->arg("a1").c_str(), sizeof(sysCfg.friendlyname[0]));
strlcpy(sysCfg.friendlyname[1], (!strlen(webServer->arg("a2").c_str())) ? FRIENDLY_NAME2 : webServer->arg("a2").c_str(), sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], (!strlen(webServer->arg("a3").c_str())) ? FRIENDLY_NAME3 : webServer->arg("a3").c_str(), sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], (!strlen(webServer->arg("a4").c_str())) ? FRIENDLY_NAME4 : webServer->arg("a4").c_str(), sizeof(sysCfg.friendlyname[3]));
snprintf_P(log, sizeof(log), PSTR("HTTP: Other MQTT Enable %s, Friendly Names %s, %s, %s and %s"),
(sysCfg.mqtt_enabled) ? MQTT_STATUS_ON : MQTT_STATUS_OFF, sysCfg.friendlyname[0], sysCfg.friendlyname[1], sysCfg.friendlyname[2], sysCfg.friendlyname[3]);
sysCfg.mqtt_enabled = webServer->hasArg("b1");
#ifdef USE_EMULATION
sysCfg.emulation = (!strlen(webServer->arg("b2").c_str())) ? 0 : atoi(webServer->arg("b2").c_str());
#endif // USE_EMULATION
strlcpy(sysCfg.friendlyname[0], (!strlen(webServer->arg("a1").c_str())) ? FRIENDLY_NAME : webServer->arg("a1").c_str(), sizeof(sysCfg.friendlyname[0]));
strlcpy(sysCfg.friendlyname[1], (!strlen(webServer->arg("a2").c_str())) ? FRIENDLY_NAME"2" : webServer->arg("a2").c_str(), sizeof(sysCfg.friendlyname[1]));
strlcpy(sysCfg.friendlyname[2], (!strlen(webServer->arg("a3").c_str())) ? FRIENDLY_NAME"3" : webServer->arg("a3").c_str(), sizeof(sysCfg.friendlyname[2]));
strlcpy(sysCfg.friendlyname[3], (!strlen(webServer->arg("a4").c_str())) ? FRIENDLY_NAME"4" : webServer->arg("a4").c_str(), sizeof(sysCfg.friendlyname[3]));
snprintf_P(log, sizeof(log), PSTR("HTTP: Other MQTT Enable %s, Emulation %d, Friendly Names %s, %s, %s and %s"),
(sysCfg.mqtt_enabled) ? MQTT_STATUS_ON : MQTT_STATUS_OFF, sysCfg.emulation, sysCfg.friendlyname[0], sysCfg.friendlyname[1], sysCfg.friendlyname[2], sysCfg.friendlyname[3]);
addLog(LOG_LEVEL_INFO, log);
break;
case 6:
@ -1007,9 +1025,9 @@ void handleUploadLoop()
_uploaderror = 1;
return;
}
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
UDP_Disconnect();
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION
if (sysCfg.mqtt_enabled) mqttClient.disconnect();
snprintf_P(log, sizeof(log), PSTR("Upload: File %s ..."), upload.filename.c_str());
@ -1262,7 +1280,7 @@ void handleRestart()
/********************************************************************************************/
#ifdef USE_WEMO_EMULATION
#ifdef USE_EMULATION
void handleUPnPevent()
{
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle WeMo basic event"));
@ -1281,7 +1299,7 @@ void handleUPnPservice()
webServer->send(200, "text/plain", eventservice_xml);
}
void handleUPnPsetup()
void handleUPnPsetupWemo()
{
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle WeMo setup"));
@ -1292,11 +1310,9 @@ void handleUPnPsetup()
setup_xml.replace("{x3}", wemo_serial());
webServer->send(200, "text/xml", setup_xml);
}
#endif // USE_WEMO_EMULATION
/********************************************************************************************/
#ifdef USE_HUE_EMULATION
String hue_deviceId(uint8_t id)
{
char deviceid[16];
@ -1305,7 +1321,7 @@ String hue_deviceId(uint8_t id)
return String(deviceid);
}
void handleUPnPsetup()
void handleUPnPsetupHue()
{
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle Hue Bridge setup"));
@ -1344,13 +1360,16 @@ void hue_lights(String *path)
response.replace("{state}", (power & (0x01 << (i-1))) ? "true" : "false");
response.replace("{j1}", sysCfg.friendlyname[i-1]);
response.replace("{j2}", hue_deviceId(i));
if (pin[GPIO_WS2812] < 99) {
#ifdef USE_WS2812
ws2812_replaceHSB(&response);
#else
response.replace("{h}", "0");
response.replace("{s}", "0");
response.replace("{b}", "0");
ws2812_replaceHSB(&response);
#endif // USE_WS2812
} else
{
response.replace("{h}", "0");
response.replace("{s}", "0");
response.replace("{b}", "0");
}
}
response += "}";
webServer->send(200, "application/json", response);
@ -1388,8 +1407,7 @@ void hue_lights(String *path)
}
}
#ifdef USE_WS2812
if ((pos=json.indexOf("\"bri\":")) >= 0)
{
if ((pin[GPIO_WS2812] < 99) && ((pos=json.indexOf("\"bri\":")) >= 0)) {
bri=atoi(json.substring(pos+6).c_str());
ws2812_changeBrightness(bri);
response += ",";
@ -1405,8 +1423,7 @@ void hue_lights(String *path)
}
else webServer->send(406, "application/json", "{}");
}
else if(path->indexOf("/lights/") >= 0) // Got /lights/ID
{
else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID
path->remove(0,8); // Remove /lights/
device = atoi(path->c_str());
if ((device < 1) || (device > Maxdevice)) device = 1;
@ -1414,13 +1431,16 @@ void hue_lights(String *path)
response.replace("{state}", (power & (0x01 << (device -1))) ? "true" : "false");
response.replace("{j1}", sysCfg.friendlyname[device -1]);
response.replace("{j2}", hue_deviceId(device));
if (pin[GPIO_WS2812] < 99) {
#ifdef USE_WS2812
ws2812_replaceHSB(&response);
#else
response.replace("{h}", "0");
response.replace("{s}", "0");
response.replace("{b}", "0");
ws2812_replaceHSB(&response);
#endif // USE_WS2812
} else
{
response.replace("{h}", "0");
response.replace("{s}", "0");
response.replace("{b}", "0");
}
webServer->send(200, "application/json", response);
}
else webServer->send(406, "application/json", "{}");
@ -1453,7 +1473,7 @@ void handle_hue_api(String *path)
webServer->send(406, "application/json", "{}");
}
}
#endif // USE_HUE_EMULATION
#endif // USE_EMULATION
/********************************************************************************************/
@ -1463,33 +1483,30 @@ void handleNotFound()
return;
}
#ifdef USE_HUE_EMULATION
#ifdef USE_EMULATION
String path = webServer->uri();
if (path.startsWith("/api"))
if ((sysCfg.emulation == EMUL_HUE) && (path.startsWith("/api"))) {
handle_hue_api(&path);
else {
#endif // USE_HUE_EMULATION
String message = "File Not Found\n\n";
message += "URI: ";
message += webServer->uri();
message += "\nMethod: ";
message += ( webServer->method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += webServer->args();
message += "\n";
for ( uint8_t i = 0; i < webServer->args(); i++ ) {
message += " " + webServer->argName ( i ) + ": " + webServer->arg ( i ) + "\n";
}
} else
#endif // USE_EMULATION
{
String message = "File Not Found\n\n";
message += "URI: ";
message += webServer->uri();
message += "\nMethod: ";
message += ( webServer->method() == HTTP_GET ) ? "GET" : "POST";
message += "\nArguments: ";
message += webServer->args();
message += "\n";
for ( uint8_t i = 0; i < webServer->args(); i++ ) {
message += " " + webServer->argName ( i ) + ": " + webServer->arg ( i ) + "\n";
}
webServer->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
webServer->sendHeader("Pragma", "no-cache");
webServer->sendHeader("Expires", "-1");
webServer->send(404, "text/plain", message);
#ifdef USE_HUE_EMULATION
addLog_P(LOG_LEVEL_DEBUG_MORE, message.c_str());
webServer->sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
webServer->sendHeader("Pragma", "no-cache");
webServer->sendHeader("Expires", "-1");
webServer->send(404, "text/plain", message);
}
#endif // USE_HUE_EMULATION
}
/* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */
@ -1517,5 +1534,4 @@ boolean isIp(String str)
}
return true;
}
#endif // USE_WEBSERVER

View File

@ -23,7 +23,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
#ifdef USE_EMULATION
#define UDP_BUFFER_SIZE 200 // Max UDP buffer size needed for M-SEARCH message
@ -33,7 +33,6 @@ char packetBuffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet
IPAddress ipMulticast(239, 255, 255, 250); // Simple Service Discovery Protocol (SSDP)
uint32_t portMulticast = 1900; // Multicast address and port
#ifdef USE_WEMO_EMULATION
/*********************************************************************************************\
* WeMo UPNP support routines
\*********************************************************************************************/
@ -83,9 +82,7 @@ void wemo_respondToMSearch()
message, portUDP.remoteIP().toString().c_str(), portUDP.remotePort());
addLog(LOG_LEVEL_DEBUG, log);
}
#endif // USE_WEMO_EMULATION
#ifdef USE_HUE_EMULATION
/*********************************************************************************************\
* Hue Bridge UPNP support routines
* Need to send 3 response packets with varying ST and USN
@ -174,11 +171,9 @@ void hue_respondToMSearch()
message, portUDP.remoteIP().toString().c_str(), portUDP.remotePort());
addLog(LOG_LEVEL_DEBUG, log);
}
#endif // USE_HUE_EMULATION
/********************************************************************************************/
#if defined(USE_WEMO_EMULATION) || defined(USE_HUE_EMULATION)
boolean UDP_Disconnect()
{
if (udpConnected) {
@ -212,22 +207,15 @@ void pollUDP()
String request = packetBuffer;
// addLog_P(LOG_LEVEL_DEBUG_MORE, packetBuffer);
if (request.indexOf("M-SEARCH") >= 0) {
#ifdef USE_WEMO_EMULATION
if (request.indexOf("urn:Belkin:device:**") > 0) {
if ((sysCfg.emulation == EMUL_WEMO) &&(request.indexOf("urn:Belkin:device:**") > 0)) {
wemo_respondToMSearch();
}
#endif // USE_WEMO_EMULATION
#ifdef USE_HUE_EMULATION
if (request.indexOf("ST: urn:schemas-upnp-org:device:basic:1") > 0 ||
request.indexOf("ST: upnp:rootdevice") > 0 ||
request.indexOf("ST: ssdp:all") > 0) {
else if ((sysCfg.emulation == EMUL_HUE) && ((request.indexOf("ST: urn:schemas-upnp-org:device:basic:1") > 0) || (request.indexOf("ST: upnp:rootdevice") > 0) || (request.indexOf("ST: ssdp:all") > 0))) {
hue_respondToMSearch();
}
#endif // USE_HUE_EMULATION
}
}
}
}
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_WEMO_EMULATION || USE_HUE_EMULATION
#endif // USE_EMULATION