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();