diff --git a/README.md b/README.md
index 684385c8e..2cab6eb16 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,11 @@
## 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.4** - See ```_releasenotes.ino``` for change information.
+Current version is **3.9.5** - 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```.
- After reboot select config menu again or use commands ```GPIOs``` and ```GPIO``` to change GPIO with desired sensor.
-- Some features still need to be ironed out.
See [Wiki](wiki) for more information.
diff --git a/api/arduino/sonoff.ino.bin b/api/arduino/sonoff.ino.bin
index 4f5a63e87..ee5225f79 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 f81ae8d25..7ea36323e 100644
--- a/sonoff/_releasenotes.ino
+++ b/sonoff/_releasenotes.ino
@@ -1,4 +1,7 @@
-/* 3.9.4 20170127
+/* 3.9.5 2017018
+ * Fix error message in case of wrong Domoticz command
+ *
+ * 3.9.4 20170127
* Fix Sonoff Dual Relay switching (#287)
*
* 3.9.3 20170127
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 3dc393b4b..3c4dff6a8 100644
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -10,7 +10,7 @@
* ====================================================
*/
-#define VERSION 0x03090400 // 3.9.4
+#define VERSION 0x03090500 // 3.9.5
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};
@@ -31,12 +31,6 @@ enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, L
//#define USE_SPIFFS // Switch persistent configuration from flash to spiffs (+24k code, +0.6k mem)
-/*********************************************************************************************\
- * Not released yet
-\*********************************************************************************************/
-
-#define FEATURE_POWER_LIMIT
-
/*********************************************************************************************\
* No user configurable items below
\*********************************************************************************************/
@@ -410,20 +404,6 @@ uint8_t i2c_flg = 0; // I2C configured
boolean mDNSbegun = false;
-byte hlw_pminflg = 0;
-byte hlw_pmaxflg = 0;
-byte hlw_uminflg = 0;
-byte hlw_umaxflg = 0;
-byte hlw_iminflg = 0;
-byte hlw_imaxflg = 0;
-byte power_steady_cntr;
-#ifdef FEATURE_POWER_LIMIT
- byte hlw_mkwh_state = 0;
- byte hlw_mplr_counter = 0;
- uint16_t hlw_mplh_counter = 0;
- uint16_t hlw_mplw_counter = 0;
-#endif // FEATURE_POWER_LIMIT
-
/********************************************************************************************/
void CFG_DefaultSet()
@@ -776,7 +756,7 @@ void setRelay(uint8_t power)
}
}
}
- power_steady_cntr = 2;
+ hlw_setPowerSteadyCounter(2);
}
void setLed(uint8_t state)
@@ -1578,11 +1558,6 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MqttPassword\":\"%s\"}"), sysCfg.mqtt_pwd);
}
-#ifdef USE_DOMOTICZ
- else if (sysCfg.mqtt_enabled && !strncmp(type,"DOMOTICZ...",8)) {
- domoticz_commands(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue));
- }
-#endif // USE_DOMOTICZ
else if (sysCfg.mqtt_enabled && !strcmp(type,"GROUPTOPIC")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_grptopic))) {
for(i = 0; i <= data_len; i++)
@@ -1661,209 +1636,19 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), (!strcmp(sysCfg.mqtt_subtopic,"POWER")) ? "Power" : "Light");
snprintf_P(svalue, sizeof(svalue), PSTR("{\"%sRetain\":\"%s\"}"), stemp1, (sysCfg.mqtt_power_retain) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
}
-
-/*** HLW Power management Commands ***********************************************************/
-
- else if (hlw_flg && !strcmp(type,"POWERLOW")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_pmin = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PowerLow\":\"%d%s\"}"), sysCfg.hlw_pmin, (sysCfg.value_units) ? " W" : "");
- }
- else if (hlw_flg && !strcmp(type,"POWERHIGH")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_pmax = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PowerHigh\":\"%d%s\"}"), sysCfg.hlw_pmax, (sysCfg.value_units) ? " W" : "");
- }
- else if (hlw_flg && !strcmp(type,"VOLTAGELOW")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
- sysCfg.hlw_umin = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"VoltageLow\":\"%d%s\"}"), sysCfg.hlw_umin, (sysCfg.value_units) ? " V" : "");
- }
- else if (hlw_flg && !strcmp(type,"VOLTAGEHIGH")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
- sysCfg.hlw_umax = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("[\"VoltageHigh\":\"%d%s\"}"), sysCfg.hlw_umax, (sysCfg.value_units) ? " V" : "");
- }
- else if (hlw_flg && !strcmp(type,"CURRENTLOW")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
- sysCfg.hlw_imin = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"CurrentLow\":\"%d%s\"}"), sysCfg.hlw_imin, (sysCfg.value_units) ? " mA" : "");
- }
- else if (hlw_flg && !strcmp(type,"CURRENTHIGH")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
- sysCfg.hlw_imax = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"CurrentHigh\":\"%d%s\"}"), sysCfg.hlw_imax, (sysCfg.value_units) ? " mA" : "");
- }
- else if (hlw_flg && !strcmp(type,"HLWPCAL")) {
- if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
- sysCfg.hlw_pcal = (payload == 1) ? HLW_PREF_PULSE : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("(\"HlwPcal\":\"%d%s\"}"), sysCfg.hlw_pcal, (sysCfg.value_units) ? " uS" : "");
- }
- else if (hlw_flg && !strcmp(type,"HLWUCAL")) {
- if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
- sysCfg.hlw_ucal = (payload == 1) ? HLW_UREF_PULSE : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"HlwUcal\":\"%d%s\"}"), sysCfg.hlw_ucal, (sysCfg.value_units) ? " uS" : "");
- }
- else if (hlw_flg && !strcmp(type,"HLWICAL")) {
- if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
- sysCfg.hlw_ical = (payload == 1) ? HLW_IREF_PULSE : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"HlwIcal\":\"%d%s\"}"), sysCfg.hlw_ical, (sysCfg.value_units) ? " uS" : "");
- }
-#ifdef FEATURE_POWER_LIMIT
- else if (hlw_flg && !strcmp(type,"MAXPOWER")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_mpl = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPower\":\"%d%s\"}"), sysCfg.hlw_mpl, (sysCfg.value_units) ? " W" : "");
- }
- else if (hlw_flg && !strcmp(type,"MAXPOWERHOLD")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_mplh = (payload == 1) ? MAX_POWER_HOLD : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerHold\":\"%d%s\"}"), sysCfg.hlw_mplh, (sysCfg.value_units) ? " Sec" : "");
- }
- else if (hlw_flg && !strcmp(type,"MAXPOWERWINDOW")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_mplw = (payload == 1) ? MAX_POWER_WINDOW : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerWindow\":\"%d%s\"}"), sysCfg.hlw_mplw, (sysCfg.value_units) ? " Sec" : "");
- }
- else if (hlw_flg && !strcmp(type,"SAFEPOWER")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_mspl = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SafePower\":\"%d%s\"}"), sysCfg.hlw_mspl, (sysCfg.value_units) ? " W" : "");
- }
- else if (hlw_flg && !strcmp(type,"SAFEPOWERHOLD")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_msplh = (payload == 1) ? SAFE_POWER_HOLD : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SafePowerHold\":\"%d%s\"}"), sysCfg.hlw_msplh, (sysCfg.value_units) ? " Sec" : "");
- }
- else if (hlw_flg && !strcmp(type,"SAFEPOWERWINDOW")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 1440)) {
- sysCfg.hlw_msplw = (payload == 1) ? SAFE_POWER_WINDOW : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SafePowerWindow\":\"%d%s\"}"), sysCfg.hlw_msplw, (sysCfg.value_units) ? " Min" : "");
- }
- else if (hlw_flg && !strcmp(type,"MAXENERGY")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
- sysCfg.hlw_mkwh = payload;
- hlw_mkwh_state = 3;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxEnergy\":\"%d%s\"}"), sysCfg.hlw_mkwh, (sysCfg.value_units) ? " Wh" : "");
- }
- else if (hlw_flg && !strcmp(type,"MAXENERGYSTART")) {
- if ((data_len > 0) && (payload >= 0) && (payload < 24)) {
- sysCfg.hlw_mkwhs = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxEnergyStart\":\"%d%s\"}"), sysCfg.hlw_mkwhs, (sysCfg.value_units) ? " Hr" : "");
- }
-#endif // FEATURE_POWER_LIMIT
-
-/*** WS2812 Commands *************************************************************************/
-
-#ifdef USE_WS2812
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"PIXELS")) {
- if ((data_len > 0) && (payload > 0) && (payload <= WS2812_MAX_LEDS)) {
- sysCfg.ws_pixels = payload;
- ws2812_pixels();
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Pixels\":%d}"), sysCfg.ws_pixels);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"LED") && (index > 0) && (index <= sysCfg.ws_pixels)) {
- if (data_len == 6) {
- ws2812_setColor(index, dataBufUc);
- }
- ws2812_getColor(index, svalue, sizeof(svalue));
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"COLOR")) {
- if (data_len == 6) {
- ws2812_setColor(0, dataBufUc);
- power = 1;
- }
- ws2812_getColor(0, svalue, sizeof(svalue));
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"DIMMER")) {
- if ((data_len > 0) && (payload >= 0) && (payload <= 100)) {
- sysCfg.ws_dimmer = payload;
- power = 1;
#ifdef USE_DOMOTICZ
- mqtt_publishDomoticzPowerState(index);
+ else if (sysCfg.mqtt_enabled && domoticz_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
+ // Serviced
+ }
#endif // USE_DOMOTICZ
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Dimmer\":%d}"), sysCfg.ws_dimmer);
+ else if (hlw_flg && hlw_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
+ // Serviced
}
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"LEDTABLE")) {
- if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
- switch (payload) {
- case 0: // Off
- case 1: // On
- sysCfg.ws_ledtable = payload;
- break;
- case 2: // Toggle
- sysCfg.ws_ledtable ^= 1;
- break;
- }
- ws2812_update();
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedTable\":\"%s\"}"), (sysCfg.ws_ledtable) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"FADE")) {
- if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
- switch (payload) {
- case 0: // Off
- case 1: // On
- sysCfg.ws_fade = payload;
- break;
- case 2: // Toggle
- sysCfg.ws_fade ^= 1;
- break;
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Fade\":\"%s\"}"), (sysCfg.ws_fade) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"SPEED")) { // 1 - fast, 5 - slow
- if ((data_len > 0) && (payload > 0) && (payload <= 5)) {
- sysCfg.ws_speed = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Speed\":%d}"), sysCfg.ws_speed);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"WIDTH")) {
- if ((data_len > 0) && (payload >= 0) && (payload <= 4)) {
- sysCfg.ws_width = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Width\":%d}"), sysCfg.ws_width);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"WAKEUP")) {
- if ((data_len > 0) && (payload > 0) && (payload < 3601)) {
- sysCfg.ws_wakeup = payload;
- if (sysCfg.ws_scheme == 1) sysCfg.ws_scheme = 0;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WakeUp\":%d}"), sysCfg.ws_wakeup);
- }
- else if ((pin[GPIO_WS2812] < 99) && !strcmp(type,"SCHEME")) {
- if ((data_len > 0) && (payload >= 0) && (payload <= 9)) {
- sysCfg.ws_scheme = payload;
- if (sysCfg.ws_scheme == 1) ws2812_resetWakupState();
- power = 1;
- ws2812_resetStripTimer();
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Scheme\":%d}"), sysCfg.ws_scheme);
+#ifdef USE_WS2812
+ else if ((pin[GPIO_WS2812] < 99) && ws2812_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
+ // Serviced
}
#endif // USE_WS2812
-
-/*********************************************************************************************/
-
else {
type = NULL;
}
@@ -1895,16 +1680,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
#ifdef USE_DOMOTICZ
mqtt_publish(stopic, svalue);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"DomoticzInTopic, DomoticzOutTopic, DomoticzIdx, DomoticzKeyIdx, DomoticzSwitchIdx, DomoticzSensorIdx, DomoticzUpdateTimer\"}"));
+ domoticz_commands(svalue, sizeof(svalue));
#endif // USE_DOMOTICZ
if (hlw_flg) {
mqtt_publish(stopic, svalue);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"PowerLow, PowerHigh, VoltageLow, VoltageHigh, CurrentLow, CurrentHigh"));
-#ifdef FEATURE_POWER_LIMIT
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, SafePower, SafePowerHold, SafePowerWindow, MaxPower, MaxPowerHold, MaxPowerWindow, MaxEnergy, MaxEnergyStart"), svalue);
-#endif // FEATURE_POWER_LIMIT
- snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
+ hlw_commands(svalue, sizeof(svalue));
}
}
mqtt_publish(stopic, svalue);
@@ -2116,16 +1897,6 @@ void every_second_cb()
// 1 second rtc interrupt routine
// Keep this code small (every_second is to large - it'll trip exception)
-#ifdef FEATURE_POWER_LIMIT
- if (rtcTime.Valid) {
- if (rtc_loctime() == rtc_midnight()) {
- hlw_mkwh_state = 3;
- }
- if ((rtcTime.Hour == sysCfg.hlw_mkwhs) && (hlw_mkwh_state == 3)) {
- hlw_mkwh_state = 0;
- }
- }
-#endif // FEATURE_POWER_LIMIT
}
void every_second()
diff --git a/sonoff/xdrv_domoticz.ino b/sonoff/xdrv_domoticz.ino
index b00c5c217..259313798 100644
--- a/sonoff/xdrv_domoticz.ino
+++ b/sonoff/xdrv_domoticz.ino
@@ -182,8 +182,10 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin
* Commands
\*********************************************************************************************/
-void domoticz_commands(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue)
+boolean domoticz_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue)
{
+ boolean serviced = true;
+
if (!strcmp(type,"DOMOTICZINTOPIC")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.domoticz_in_topic))) {
strlcpy(sysCfg.domoticz_in_topic, (payload == 1) ? DOMOTICZ_IN_TOPIC : dataBuf, sizeof(sysCfg.domoticz_in_topic));
@@ -229,6 +231,15 @@ void domoticz_commands(char *type, uint16_t index, char *dataBuf, uint16_t data_
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzUpdateTimer\":%d}"), sysCfg.domoticz_update_timer);
}
+ else {
+ serviced = false;
+ }
+ return serviced;
+}
+
+void domoticz_commands(char *svalue, uint16_t ssvalue)
+{
+ snprintf_P(svalue, ssvalue, PSTR("{\"Commands\":\"DomoticzInTopic, DomoticzOutTopic, DomoticzIdx, DomoticzKeyIdx, DomoticzSwitchIdx, DomoticzSensorIdx, DomoticzUpdateTimer\"}"));
}
boolean domoticz_button(byte key, byte device, byte state, byte svalflg)
diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino
index cddd8c66e..acb560021 100644
--- a/sonoff/xdrv_ws2812.ino
+++ b/sonoff/xdrv_ws2812.ino
@@ -462,4 +462,107 @@ void ws2812_init()
strip->Begin();
ws2812_pixels();
}
+
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
+
+boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue)
+{
+ boolean serviced = true;
+
+ if (!strcmp(type,"PIXELS")) {
+ if ((data_len > 0) && (payload > 0) && (payload <= WS2812_MAX_LEDS)) {
+ sysCfg.ws_pixels = payload;
+ ws2812_pixels();
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Pixels\":%d}"), sysCfg.ws_pixels);
+ }
+ else if (!strcmp(type,"LED") && (index > 0) && (index <= sysCfg.ws_pixels)) {
+ if (data_len == 6) {
+// ws2812_setColor(index, dataBufUc);
+ ws2812_setColor(index, dataBuf);
+ }
+ ws2812_getColor(index, svalue, ssvalue);
+ }
+ else if (!strcmp(type,"COLOR")) {
+ if (data_len == 6) {
+// ws2812_setColor(0, dataBufUc);
+ ws2812_setColor(0, dataBuf);
+ power = 1;
+ }
+ ws2812_getColor(0, svalue, ssvalue);
+ }
+ else if (!strcmp(type,"DIMMER")) {
+ if ((data_len > 0) && (payload >= 0) && (payload <= 100)) {
+ sysCfg.ws_dimmer = payload;
+ power = 1;
+#ifdef USE_DOMOTICZ
+ mqtt_publishDomoticzPowerState(index);
+#endif // USE_DOMOTICZ
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Dimmer\":%d}"), sysCfg.ws_dimmer);
+ }
+ else if (!strcmp(type,"LEDTABLE")) {
+ if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
+ switch (payload) {
+ case 0: // Off
+ case 1: // On
+ sysCfg.ws_ledtable = payload;
+ break;
+ case 2: // Toggle
+ sysCfg.ws_ledtable ^= 1;
+ break;
+ }
+ ws2812_update();
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"LedTable\":\"%s\"}"), (sysCfg.ws_ledtable) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
+ }
+ else if (!strcmp(type,"FADE")) {
+ if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
+ switch (payload) {
+ case 0: // Off
+ case 1: // On
+ sysCfg.ws_fade = payload;
+ break;
+ case 2: // Toggle
+ sysCfg.ws_fade ^= 1;
+ break;
+ }
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Fade\":\"%s\"}"), (sysCfg.ws_fade) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
+ }
+ else if (!strcmp(type,"SPEED")) { // 1 - fast, 5 - slow
+ if ((data_len > 0) && (payload > 0) && (payload <= 5)) {
+ sysCfg.ws_speed = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Speed\":%d}"), sysCfg.ws_speed);
+ }
+ else if (!strcmp(type,"WIDTH")) {
+ if ((data_len > 0) && (payload >= 0) && (payload <= 4)) {
+ sysCfg.ws_width = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Width\":%d}"), sysCfg.ws_width);
+ }
+ else if (!strcmp(type,"WAKEUP")) {
+ if ((data_len > 0) && (payload > 0) && (payload < 3601)) {
+ sysCfg.ws_wakeup = payload;
+ if (sysCfg.ws_scheme == 1) sysCfg.ws_scheme = 0;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"WakeUp\":%d}"), sysCfg.ws_wakeup);
+ }
+ else if (!strcmp(type,"SCHEME")) {
+ if ((data_len > 0) && (payload >= 0) && (payload <= 9)) {
+ sysCfg.ws_scheme = payload;
+ if (sysCfg.ws_scheme == 1) ws2812_resetWakupState();
+ power = 1;
+ ws2812_resetStripTimer();
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"Scheme\":%d}"), sysCfg.ws_scheme);
+ }
+ else {
+ serviced = false;
+ }
+ return serviced;
+}
#endif // USE_WS2812
diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_hlw8012.ino
index de4f0e8cb..9b1b7484f 100644
--- a/sonoff/xsns_hlw8012.ino
+++ b/sonoff/xsns_hlw8012.ino
@@ -29,10 +29,30 @@ POSSIBILITY OF SUCH DAMAGE.
* Based on Source: Shenzhen Heli Technology Co., Ltd
\*********************************************************************************************/
+#define FEATURE_POWER_LIMIT false
+
+/*********************************************************************************************/
+
#define HLW_PREF 10000 // 1000.0W
#define HLW_UREF 2200 // 220.0V
#define HLW_IREF 4545 // 4.545A
+byte hlw_pminflg = 0;
+byte hlw_pmaxflg = 0;
+byte hlw_uminflg = 0;
+byte hlw_umaxflg = 0;
+byte hlw_iminflg = 0;
+byte hlw_imaxflg = 0;
+
+byte power_steady_cntr;
+byte hlw_mkwh_state = 0;
+
+#if FEATURE_POWER_LIMIT
+ byte hlw_mplr_counter = 0;
+ uint16_t hlw_mplh_counter = 0;
+ uint16_t hlw_mplw_counter = 0;
+#endif // FEATURE_POWER_LIMIT
+
byte hlw_SELflag, hlw_cf_timer, hlw_cf1_timer, hlw_fifth_second, hlw_startup;
unsigned long hlw_cf_plen, hlw_cf_last;
unsigned long hlw_cf1_plen, hlw_cf1_last, hlw_cf1_ptot, hlw_cf1_pcnt, hlw_cf1u_plen, hlw_cf1i_plen;
@@ -83,13 +103,19 @@ void hlw_200mS()
hlw_temp = (HLW_PREF * sysCfg.hlw_pcal) / hlw_len;
hlw_kWhtoday += (hlw_temp * 100) / 36;
}
- if (rtc_loctime() == rtc_midnight()) {
- sysCfg.hlw_kWhyesterday = hlw_kWhtoday;
- hlw_kWhtoday = 0;
- }
- if (hlw_startup && rtcTime.Valid && (rtcTime.DayOfYear == sysCfg.hlw_kWhdoy)) {
- hlw_kWhtoday = sysCfg.hlw_kWhtoday;
- hlw_startup = 0;
+ if (rtcTime.Valid) {
+ if (rtc_loctime() == rtc_midnight()) {
+ sysCfg.hlw_kWhyesterday = hlw_kWhtoday;
+ hlw_kWhtoday = 0;
+ hlw_mkwh_state = 3;
+ }
+ if ((rtcTime.Hour == sysCfg.hlw_mkwhs) && (hlw_mkwh_state == 3)) {
+ hlw_mkwh_state = 0;
+ }
+ if (hlw_startup && (rtcTime.DayOfYear == sysCfg.hlw_kWhdoy)) {
+ hlw_kWhtoday = sysCfg.hlw_kWhtoday;
+ hlw_startup = 0;
+ }
}
}
@@ -246,6 +272,11 @@ boolean hlw_margin(byte type, uint16_t margin, uint16_t value, byte &flag, byte
return (change != saveflag);
}
+void hlw_setPowerSteadyCounter(byte value)
+{
+ power_steady_cntr = 2;
+}
+
void hlw_margin_chk()
{
char log[LOGSZ], stopic[TOPSZ], svalue[MESSZ];
@@ -298,7 +329,7 @@ void hlw_margin_chk()
}
}
-#ifdef FEATURE_POWER_LIMIT
+#if FEATURE_POWER_LIMIT
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
// Max Power
if (sysCfg.hlw_mpl) {
@@ -360,6 +391,131 @@ void hlw_margin_chk()
#endif // FEATURE_POWER_LIMIT
}
+/*********************************************************************************************\
+ * Commands
+\*********************************************************************************************/
+
+boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue)
+{
+ boolean serviced = true;
+
+ if (!strcmp(type,"POWERLOW")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_pmin = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"PowerLow\":\"%d%s\"}"), sysCfg.hlw_pmin, (sysCfg.value_units) ? " W" : "");
+ }
+ else if (!strcmp(type,"POWERHIGH")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_pmax = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"PowerHigh\":\"%d%s\"}"), sysCfg.hlw_pmax, (sysCfg.value_units) ? " W" : "");
+ }
+ else if (!strcmp(type,"VOLTAGELOW")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
+ sysCfg.hlw_umin = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"VoltageLow\":\"%d%s\"}"), sysCfg.hlw_umin, (sysCfg.value_units) ? " V" : "");
+ }
+ else if (!strcmp(type,"VOLTAGEHIGH")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
+ sysCfg.hlw_umax = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("[\"VoltageHigh\":\"%d%s\"}"), sysCfg.hlw_umax, (sysCfg.value_units) ? " V" : "");
+ }
+ else if (!strcmp(type,"CURRENTLOW")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
+ sysCfg.hlw_imin = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"CurrentLow\":\"%d%s\"}"), sysCfg.hlw_imin, (sysCfg.value_units) ? " mA" : "");
+ }
+ else if (!strcmp(type,"CURRENTHIGH")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
+ sysCfg.hlw_imax = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"CurrentHigh\":\"%d%s\"}"), sysCfg.hlw_imax, (sysCfg.value_units) ? " mA" : "");
+ }
+ else if (!strcmp(type,"HLWPCAL")) {
+ if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
+ sysCfg.hlw_pcal = (payload == 1) ? HLW_PREF_PULSE : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("(\"HlwPcal\":\"%d%s\"}"), sysCfg.hlw_pcal, (sysCfg.value_units) ? " uS" : "");
+ }
+ else if (!strcmp(type,"HLWUCAL")) {
+ if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
+ sysCfg.hlw_ucal = (payload == 1) ? HLW_UREF_PULSE : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"HlwUcal\":\"%d%s\"}"), sysCfg.hlw_ucal, (sysCfg.value_units) ? " uS" : "");
+ }
+ else if (!strcmp(type,"HLWICAL")) {
+ if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
+ sysCfg.hlw_ical = (payload == 1) ? HLW_IREF_PULSE : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"HlwIcal\":\"%d%s\"}"), sysCfg.hlw_ical, (sysCfg.value_units) ? " uS" : "");
+ }
+#if FEATURE_POWER_LIMIT
+ else if (!strcmp(type,"MAXPOWER")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_mpl = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"MaxPower\":\"%d%s\"}"), sysCfg.hlw_mpl, (sysCfg.value_units) ? " W" : "");
+ }
+ else if (!strcmp(type,"MAXPOWERHOLD")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_mplh = (payload == 1) ? MAX_POWER_HOLD : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"MaxPowerHold\":\"%d%s\"}"), sysCfg.hlw_mplh, (sysCfg.value_units) ? " Sec" : "");
+ }
+ else if (!strcmp(type,"MAXPOWERWINDOW")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_mplw = (payload == 1) ? MAX_POWER_WINDOW : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"MaxPowerWindow\":\"%d%s\"}"), sysCfg.hlw_mplw, (sysCfg.value_units) ? " Sec" : "");
+ }
+ else if (!strcmp(type,"SAFEPOWER")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_mspl = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"SafePower\":\"%d%s\"}"), sysCfg.hlw_mspl, (sysCfg.value_units) ? " W" : "");
+ }
+ else if (!strcmp(type,"SAFEPOWERHOLD")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_msplh = (payload == 1) ? SAFE_POWER_HOLD : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"SafePowerHold\":\"%d%s\"}"), sysCfg.hlw_msplh, (sysCfg.value_units) ? " Sec" : "");
+ }
+ else if (!strcmp(type,"SAFEPOWERWINDOW")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 1440)) {
+ sysCfg.hlw_msplw = (payload == 1) ? SAFE_POWER_WINDOW : payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"SafePowerWindow\":\"%d%s\"}"), sysCfg.hlw_msplw, (sysCfg.value_units) ? " Min" : "");
+ }
+ else if (!strcmp(type,"MAXENERGY")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
+ sysCfg.hlw_mkwh = payload;
+ hlw_mkwh_state = 3;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"MaxEnergy\":\"%d%s\"}"), sysCfg.hlw_mkwh, (sysCfg.value_units) ? " Wh" : "");
+ }
+ else if (!strcmp(type,"MAXENERGYSTART")) {
+ if ((data_len > 0) && (payload >= 0) && (payload < 24)) {
+ sysCfg.hlw_mkwhs = payload;
+ }
+ snprintf_P(svalue, ssvalue, PSTR("{\"MaxEnergyStart\":\"%d%s\"}"), sysCfg.hlw_mkwhs, (sysCfg.value_units) ? " Hr" : "");
+ }
+#endif // FEATURE_POWER_LIMIT
+ else {
+ serviced = false;
+ }
+ return serviced;
+}
+
+void hlw_commands(char *svalue, uint16_t ssvalue)
+{
+ snprintf_P(svalue, ssvalue, PSTR("{\"Commands\":\"PowerLow, PowerHigh, VoltageLow, VoltageHigh, CurrentLow, CurrentHigh%s\"}"),
+ (FEATURE_POWER_LIMIT)?"SafePower, SafePowerHold, SafePowerWindow, MaxPower, MaxPowerHold, MaxPowerWindow, MaxEnergy, MaxEnergyStart":"");
+}
+
/*********************************************************************************************\
* Presentation
\*********************************************************************************************/