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. Sonoff 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 \*********************************************************************************************/