diff --git a/README.md b/README.md index 4b9968144..b4fba8882 100644 --- a/README.md +++ b/README.md @@ -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.9** - See ```sonoff/_releasenotes.ino``` for change information. +Current version is **3.9.10** - 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```. diff --git a/api/arduino/sonoff.ino.bin b/api/arduino/sonoff.ino.bin index 788244233..7851241f7 100644 Binary files a/api/arduino/sonoff.ino.bin and b/api/arduino/sonoff.ino.bin differ diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index e76539ba8..1f4efe801 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,8 @@ -/* 3.9.9 20170130 +/* 3.9.10 20170130 + * Add WS2812 Color Type selection (RGB or GRB) to user_config.h (#7) + * Hue api changes to support HUE App(s) (#8) + * + * 3.9.9 20170130 * Add command status 10 showing sensor data * Fix hlw status messages if hlw is disabled * diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 3587de366..b8e3dc509 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -10,7 +10,7 @@ * ==================================================== */ -#define VERSION 0x03090900 // 3.9.9 +#define VERSION 0x03090A00 // 3.9.10 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}; diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 2edb63c08..fae221352 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -127,6 +127,7 @@ #define USE_HTU // Add I2C code for HTU21 sensor #define USE_WS2812 // WS2812 Led string support (+8k code, +1k mem) + #define USE_WS2812_CTYPE 1 // WS2812 Color type (0 - RGB, 1 - GRB) // #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial TXD) (+1k mem) // When USE_WS2812_DMA is enabled expect Exceptions on Pow diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 7689ada06..15a20465e 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -164,8 +164,8 @@ const char HTTP_FORM_OTHER2[] PROGMEM = #ifdef USE_EMULATION const char HTTP_FORM_OTHER3[] PROGMEM = "
 Emulation " - "
None
" - "
Belkin WeMo
" + "
None" + "
Belkin WeMo" "
Hue Bridge
"; #endif // USE_EMULATION const char HTTP_FORM_END[] PROGMEM = @@ -288,6 +288,28 @@ const char HUE_LIGHT_STATUS_JSON[] PROGMEM = "}"; const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = "{\"success\":{\"{api}/{id}/{cmd}\":{res}}}"; +const char HUE_CONFIG_RESPONSE_JSON[] PROGMEM = + "{\"name\":\"Philips hue\"," + "\"mac\":\"{mac}\"," + "\"dhcp\":true," + "\"ipaddress\":\"{ip}\"," + "\"netmask\":\"{mask}\"," + "\"gateway\":\"{gw}\"," + "\"proxyaddress\":\"\"," + "\"proxyport\":0," + "\"UTC\":\"{dt}\"," + "\"whitelist\":{\"{id}\":{" + "\"last use date\":\"{dt}\"," + "\"create date\":\"{dt}\"," + "\"name\":\"Remote\"}}," + "\"swversion\":\"01036659\"," + "\"apiversion\":\"1.16.0\"," + "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," + "\"linkbutton\":false," + "\"portalservices\":false" + "}"; +const char HUE_NO_AUTH_JSON[] PROGMEM = + "[{\"error\":{\"type\":101,\"address\":\"/\",\"description\":\"link button not pressed\"}}]"; #endif // USE_EMULATION #define DNS_PORT 53 @@ -1286,8 +1308,8 @@ void handleUPnPevent() addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle WeMo basic event")); String request = webServer->arg(0); - if(request.indexOf("State>1 0) do_cmnd_power(1, 1); - if(request.indexOf("State>0 0) do_cmnd_power(1, 0); + if (request.indexOf("State>1 0) do_cmnd_power(1, 1); + if (request.indexOf("State>0 0) do_cmnd_power(1, 0); webServer->send(200, "text/plain", ""); } @@ -1339,6 +1361,76 @@ void hue_todo(String *path) addLog(LOG_LEVEL_DEBUG_MORE, log); } +void hue_config_response(String *response) +{ + char buffer[21]; + + *response += FPSTR(HUE_CONFIG_RESPONSE_JSON); + response->replace("{mac}", WiFi.macAddress()); + response->replace("{ip}", WiFi.localIP().toString()); + response->replace("{mask}", WiFi.subnetMask().toString()); + response->replace("{gw}", WiFi.gatewayIP().toString()); + snprintf_P(buffer, sizeof(buffer), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), + rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second); + response->replace("{dt}", String(buffer)); +} + +void hue_global_cfg(String *path) +{ + String response; + + path->remove(0,1); // cut leading / to get + response = "{\"lights\":{\""; + for (uint8_t i = 1; i <= Maxdevice; i++) + { + response += i; + response += "\":"; + response += FPSTR(HUE_LIGHT_STATUS_JSON); + if (i < Maxdevice) response += ",\""; + 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); +#endif // USE_WS2812 + } else + { + response.replace("{h}", "0"); + response.replace("{s}", "0"); + response.replace("{b}", "0"); + } + } + response += F("},\"groups\":{},\"schedules\":{},\"config\":"); + + hue_config_response(&response); + response.replace("{id}", *path); + response += "}"; + webServer->send(200, "application/json", response); +} + +void hue_auth(String *path) +{ + String response; + char uid[7]; + + snprintf_P(uid, sizeof(uid), PSTR("%03x"), ESP.getChipId()); + response="[{\"success\":{\"username\":\""; + response+=String(uid); + response+="\"}}]"; + webServer->send(200, "application/json", response); +} + +void hue_config(String *path) +{ + String response = ""; + + path->remove(0,1); // cut leading / to get + hue_config_response(&response); + response.replace("{id}", *path); + webServer->send(200, "application/json", response); +} + void hue_lights(String *path) { String response; @@ -1347,7 +1439,7 @@ void hue_lights(String *path) uint8_t bri = 0; char id[4]; - path->remove(0,path->indexOf("/lights")); // Remove until /lights + path->remove(0,path->indexOf("/lights")); // Remove until /lights if (path->endsWith("/lights")) // Got /lights { response = "{\""; @@ -1388,7 +1480,8 @@ void hue_lights(String *path) if (webServer->args() == 1) { String json = webServer->arg(0); -// Serial.print("HUE API: POST "); Serial.println(json.c_str()); + json.replace(" ",""); // remove blanks + if (json.indexOf("\"on\":") >= 0) // Got "on" command { if (json.indexOf("false") >= 0) // false -> turn device off @@ -1408,7 +1501,7 @@ void hue_lights(String *path) } #ifdef USE_WS2812 if ((pin[GPIO_WS2812] < 99) && ((pos=json.indexOf("\"bri\":")) >= 0)) { - bri=atoi(json.substring(pos+6).c_str()); + bri = atoi(json.substring(pos+6).c_str()); ws2812_changeBrightness(bri); response += ","; response += FPSTR(HUE_LIGHT_RESPONSE_JSON); @@ -1456,22 +1549,34 @@ void handle_hue_api(String *path) */ char log[LOGSZ]; + uint8_t args = 0; path->remove(0, 4); // remove /api + snprintf_P(log, sizeof(log), PSTR("HTTP: Handle Hue API (%s)"), path->c_str()); + addLog(LOG_LEVEL_DEBUG_MORE, log); + for (args = 0; args < webServer->args(); args++) { + String json = webServer->arg(args); + snprintf_P(log, sizeof(log), PSTR("HTTP: Hue POST args (%s)"), json.c_str()); + addLog(LOG_LEVEL_DEBUG_MORE, log); + } + if (path->endsWith("/invalid/")) {} // Just ignore - else if (path->endsWith("/config")) hue_todo(path); - else if(path->indexOf("/lights") >= 0) hue_lights(path); - else if(path->endsWith("/groups")) hue_todo(path); - else if(path->endsWith("/schedules")) hue_todo(path); - else if(path->endsWith("/sensors")) hue_todo(path); - else if(path->endsWith("/scenes")) hue_todo(path); - else if(path->endsWith("/rules")) hue_todo(path); - else + else if (path->endsWith("/")) hue_auth(path); // New HUE App setup + else if (path->endsWith("/config")) hue_config(path); + else if (path->indexOf("/lights") >= 0) hue_lights(path); + else if (path->endsWith("/groups")) hue_todo(path); + else if (path->endsWith("/schedules")) hue_todo(path); + else if (path->endsWith("/sensors")) hue_todo(path); + else if (path->endsWith("/scenes")) hue_todo(path); + else if (path->endsWith("/rules")) hue_todo(path); + else hue_global_cfg(path); +/* { snprintf_P(log, sizeof(log), PSTR("HTTP: Handle Hue API (%s)"),path->c_str()); addLog(LOG_LEVEL_DEBUG_MORE, log); webServer->send(406, "application/json", "{}"); } +*/ } #endif // USE_EMULATION diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 38d379c48..b143b1746 100644 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -138,7 +138,6 @@ void hue_respondToMSearch() response.replace("{r3}", hue_UUID()); portUDP.write(response.c_str()); portUDP.endPacket(); - snprintf_P(message, sizeof(message), PSTR("Response1 sent")); // addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); response = FPSTR(HUE_RESPONSE); @@ -150,7 +149,6 @@ void hue_respondToMSearch() response.replace("{r3}", hue_UUID()); portUDP.write(response.c_str()); portUDP.endPacket(); - snprintf_P(message, sizeof(message), PSTR("Response2 sent")); // addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); response = FPSTR(HUE_RESPONSE); @@ -161,7 +159,8 @@ void hue_respondToMSearch() response.replace("{r3}", hue_UUID()); portUDP.write(response.c_str()); portUDP.endPacket(); - snprintf_P(message, sizeof(message), PSTR("Response3 sent")); + + snprintf_P(message, sizeof(message), PSTR("3 response packets sent")); // addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); } else { diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index d56cfb7d2..da64bde0d 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -31,9 +31,17 @@ POSSIBILITY OF SUCH DAMAGE. #include #ifdef USE_WS2812_DMA +#if (USE_WS2812_CTYPE == 1) NeoPixelBus *strip = NULL; -#else +#else // USE_WS2812_CTYPE + NeoPixelBus *strip = NULL; +#endif // USE_WS2812_CTYPE +#else // USE_WS2812_DMA +#if (USE_WS2812_CTYPE == 1) NeoPixelBus *strip = NULL; +#else // USE_WS2812_CTYPE + NeoPixelBus *strip = NULL; +#endif // USE_WS2812_CTYPE #endif // USE_WS2812_DMA #define COLOR_SATURATION 254.0f @@ -457,9 +465,17 @@ void ws2812_pixels() void ws2812_init() { #ifdef USE_WS2812_DMA +#if (USE_WS2812_CTYPE == 1) strip = new NeoPixelBus(WS2812_MAX_LEDS); // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. -#else +#else // USE_WS2812_CTYPE + strip = new NeoPixelBus(WS2812_MAX_LEDS); // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. +#endif // USE_WS2812_CTYPE +#else // USE_WS2812_DMA +#if (USE_WS2812_CTYPE == 1) strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); +#else // USE_WS2812_CTYPE + strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); +#endif // USE_WS2812_CTYPE #endif // USE_WS2812_DMA strip->Begin(); ws2812_pixels();