diff --git a/README.md b/README.md
index 3e87b01cc..301b1def6 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 **5.11.1c** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
+Current version is **5.11.1e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions
diff --git a/arduino/version 2.4.0/platform.txt b/arduino/version 2.4.0/platform.txt
index faa549ac5..d284f64da 100644
--- a/arduino/version 2.4.0/platform.txt
+++ b/arduino/version 2.4.0/platform.txt
@@ -18,12 +18,13 @@ compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
build.lwip_lib=-llwip_gcc
+build.lwip_include=lwip/include
build.lwip_flags=-DLWIP_OPEN_SRC
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
-compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/lwip/include" "-I{compiler.libc.path}/include" "-I{build.path}/core"
+compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections
@@ -31,7 +32,8 @@ compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implici
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
-compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
+# compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
+compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lmesh -lwpa2 -lstdc++ -lm -lc -lgcc
diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino
index 7f23be9cc..02b23f821 100644
--- a/sonoff/_releasenotes.ino
+++ b/sonoff/_releasenotes.ino
@@ -1,4 +1,22 @@
-/* 5.11.1c
+/* 5.11.1e
+ * Replaced command Ina219Mode with command Sensor13
+ * Add chunked webserver pages for large pages saving memory
+ * Fix Non-English JSON temperature unit attachement
+ * Add command Sensor15 2 to start MHZ19(B) Zero Point Calibration (#1643)
+ * Fix Sonoff Pow Energy Today and Energy Total reading after restart (#1648)
+ * Rewrite function pointers to save code space and memory (#1683)
+ * Add option define HOME_ASSISTANT_DISCOVERY_ENABLE in user_config.h (#1685)
+ * Fix SOnoff Pow Energy Period roll-over (#1688)
+ *
+ * 5.11.1d
+ * Add locale Decimal Separator to Web sensor page
+ * Add command State to retrieve device state information (same data as teleperiod state and status 11 in slightly different JSON format)
+ * Extent state information with Light parameters
+ * Fix IRSend parameter translation (#1636)
+ * Add optional login to Webserver AP mode (#1587, #1635)
+ * Fix BME680 teleperiod resistance measuring (#1647)
+ *
+ * 5.11.1c
* Make command color parameter input less strict to ease Hass support
* Add ColorTemperature to light status message
* Change PubSubClient.h define MQTT_MAX_PACKET_SIZE from 512 to 1000 for Hass support
diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index bcdf337ac..346e2d2e3 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -118,6 +118,7 @@
#define D_JSON_WIFI "Wifi"
#define D_JSON_WRONG "Wrong"
#define D_JSON_YESTERDAY "Yesterday"
+#define D_JSON_ZERO_POINT_CALIBRATION "Zero Point Calibration"
#define D_RSLT_ENERGY "ENERGY"
#define D_RSLT_INFO "INFO"
@@ -166,11 +167,13 @@
#define D_STATUS9_MARGIN "PTH"
#define D_STATUS10_SENSOR "SNS"
#define D_STATUS11_STATUS "STS"
+#define D_CMND_STATE "State"
#define D_CMND_POWER "Power"
#define D_CMND_POWERONSTATE "PowerOnState"
#define D_CMND_PULSETIME "PulseTime"
#define D_CMND_BLINKTIME "BlinkTime"
#define D_CMND_BLINKCOUNT "BlinkCount"
+#define D_CMND_SENSOR "Sensor"
#define D_CMND_SAVEDATA "SaveData"
#define D_CMND_SETOPTION "SetOption"
#define D_CMND_TEMPERATURE_RESOLUTION "TempRes"
@@ -236,7 +239,6 @@
#define D_CMND_LEDSTATE "LedState"
#define D_CMND_CFGDUMP "CfgDump"
#define D_CMND_I2CSCAN "I2CScan"
-#define D_CMND_INA219MODE "Ina219Mode"
#define D_CMND_EXCEPTION "Exception"
// Commands xdrv_01_light.ino
@@ -255,7 +257,18 @@
// Commands xdrv_02_irremote.ino
#define D_CMND_IRSEND "IRSend"
+ #define D_JSON_INVALID_JSON "Invalid JSON"
+ #define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol not supported"
+ #define D_JSON_IR_PROTOCOL "PROTOCOL"
+ #define D_JSON_IR_BITS "BITS"
+ #define D_JSON_IR_DATA "DATA"
#define D_CMND_IRHVAC "IRHVAC"
+ #define D_JSON_IRHVAC_VENDOR "VENDOR"
+ #define D_JSON_IRHVAC_POWER "POWER"
+ #define D_JSON_IRHVAC_MODE "MODE"
+ #define D_JSON_IRHVAC_FANSPEED "FANSPEED"
+ #define D_JSON_IRHVAC_TEMP "TEMP"
+#define D_JSON_IRRECEIVED "IrReceived"
// Commands xdrv_03_energy.ino
#define D_CMND_POWERLOW "PowerLow"
@@ -384,6 +397,9 @@ const char S_JSON_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"%s%d\":%d}";
const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}";
const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}";
+const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}";
+const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}";
+
const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}";
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
index 244a036b4..db6ee314f 100644
--- a/sonoff/language/de-DE.h
+++ b/sonoff/language/de-DE.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "."
#define D_MONTH_DAY_SEPARATOR "."
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "ungültiger JSON"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protokoll nicht unterstützt"
-#define D_JSON_IR_PROTOCOL "PROTOKOLL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATEN"
-#define D_JSON_IRHVAC_VENDOR "HERSTELLER"
-#define D_JSON_IRHVAC_POWER "STROM"
-#define D_JSON_IRHVAC_MODE "MODUS"
-#define D_JSON_IRHVAC_FANSPEED "LÜFTERGESCHWINDIGKEIT"
-#define D_JSON_IRHVAC_TEMP "TEMPERATUR"
-#define D_JSON_IRRECEIVED "IR empfangen"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h
index c8ef6f223..018923612 100644
--- a/sonoff/language/en-GB.h
+++ b/sonoff/language/en-GB.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "Invalid JSON"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol not supported"
-#define D_JSON_IR_PROTOCOL "PROTOCOL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h
index 99e142d4c..1d70b4230 100644
--- a/sonoff/language/es-AR.h
+++ b/sonoff/language/es-AR.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "JSON no válido"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocolo no soportado"
-#define D_JSON_IR_PROTOCOL "PROTOCOLO"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h
index bfb31d519..8d130f8f3 100644
--- a/sonoff/language/fr-FR.h
+++ b/sonoff/language/fr-FR.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 paquets response envoyés"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "JSON Invalide"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocole non supporté"
-#define D_JSON_IR_PROTOCOL "PROTOCOL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h
index be9e97911..e97a61895 100644
--- a/sonoff/language/it-IT.h
+++ b/sonoff/language/it-IT.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST argomenti"
#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "JSON non valido"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocollo non supportato"
-#define D_JSON_IR_PROTOCOL "PROTOCOL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h
index 9850c8b0e..155e05de6 100644
--- a/sonoff/language/nl-NL.h
+++ b/sonoff/language/nl-NL.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST argumenten"
#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "Ongeldig JSON"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol wordt niet ondersteund"
-#define D_JSON_IR_PROTOCOL "PROTOCOL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h
index 79e2afbe5..6c9679e2e 100644
--- a/sonoff/language/pl-PL.h
+++ b/sonoff/language/pl-PL.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysylane"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "Invalid JSON"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protokol nie jest obslugiwany"
-#define D_JSON_IR_PROTOCOL "PROTOCOL"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "DATA"
-#define D_JSON_IRHVAC_VENDOR "VENDOR"
-#define D_JSON_IRHVAC_POWER "POWER"
-#define D_JSON_IRHVAC_MODE "MODE"
-#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
-#define D_JSON_IRHVAC_TEMP "TEMP"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h
index c1a5ec75b..510f96f51 100644
--- a/sonoff/language/zh-CN.h
+++ b/sonoff/language/zh-CN.h
@@ -30,6 +30,8 @@
*
\*********************************************************************/
+//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
+
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST 参数"
#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送"
-// xdrv_02_irremote.ino
-#define D_JSON_INVALID_JSON "无效的JSON"
-#define D_JSON_PROTOCOL_NOT_SUPPORTED "协议不支持"
-#define D_JSON_IR_PROTOCOL "协议"
-#define D_JSON_IR_BITS "BITS"
-#define D_JSON_IR_DATA "数据"
-#define D_JSON_IRHVAC_VENDOR "供应商"
-#define D_JSON_IRHVAC_POWER "电源"
-#define D_JSON_IRHVAC_MODE "模式"
-#define D_JSON_IRHVAC_FANSPEED "风扇转速"
-#define D_JSON_IRHVAC_TEMP "温度"
-#define D_JSON_IRRECEIVED "IrReceived"
-
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz 设置"
#define D_DOMOTICZ_IDX "Idx"
diff --git a/sonoff/settings.ino b/sonoff/settings.ino
index 2b1a6acc8..0e8937a43 100644
--- a/sonoff/settings.ino
+++ b/sonoff/settings.ino
@@ -430,6 +430,7 @@ void SettingsDefaultSet2()
Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN;
Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN;
Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
+ Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE;
Settings.flag2.emulation = EMULATION;
diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h
index 2186a1aff..2b5348f7a 100644
--- a/sonoff/sonoff.h
+++ b/sonoff/sonoff.h
@@ -86,7 +86,7 @@ typedef unsigned long power_t; // Power (Relay) type
#define CMDSZ 24 // Max number of characters in command
#define TOPSZ 100 // Max number of characters in topic string
#define LOGSZ 400 // Max number of characters in log
-#define MIN_MESSZ 893 // Min number of characters in MQTT message
+#define MIN_MESSZ 893 // Min number of characters in MQTT message
#ifdef USE_MQTT_TLS
#define MAX_LOG_LINES 10 // Max number of lines in weblog
#else
@@ -128,6 +128,10 @@ enum EmulationOptions {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESULT_OR_TELE };
+enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, power_nu1, POWER_OFF_NO_STATE, POWER_ON_NO_STATE, power_nu2, POWER_SHOW_STATE };
+
+enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON };
+
enum ButtonStates {PRESSED, NOT_PRESSED};
enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8};
@@ -145,4 +149,10 @@ enum XsnsFunctions {FUNC_INIT, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PR
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
+/*********************************************************************************************\
+ * Extern global variables
+\*********************************************************************************************/
+
+extern uint8_t light_device; // Light device number
+
#endif // _SONOFF_H_
\ No newline at end of file
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 51552591b..80e37d80d 100644
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -25,10 +25,10 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
-#define VERSION 0x050B0103 // 5.11.1c
+#define VERSION 0x050B0105 // 5.11.1e
// Location specific includes
-#include "sonoff.h" // Enumaration used in user_config.h
+#include "sonoff.h" // Enumeration used in user_config.h
#include "user_config.h" // Fixed user configurable options
#include "user_config_override.h" // Configuration overrides for user_config.h
#include "i18n.h" // Language support configured by user_config.h
@@ -67,25 +67,25 @@
#include "settings.h"
enum TasmotaCommands {
- CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_POWERONSTATE, CMND_PULSETIME,
- CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION,
+ CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME,
+ CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SENSOR, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION,
CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION, CMND_MODULE, CMND_MODULES,
CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE,
CMND_COUNTERDEBOUNCE, CMND_SLEEP, CMND_UPGRADE, CMND_UPLOAD, CMND_OTAURL, CMND_SERIALLOG, CMND_SYSLOG,
CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME,
CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION,
CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE,
- CMND_CFGDUMP, CMND_I2CSCAN, CMND_INA219MODE, CMND_EXCEPTION };
+ CMND_CFGDUMP, CMND_I2CSCAN, CMND_EXCEPTION };
const char kTasmotaCommands[] PROGMEM =
- D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
- D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
+ D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
+ D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|"
D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|"
D_CMND_COUNTERDEBOUNCE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_SYSLOG "|"
D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|"
D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|"
D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|"
- D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_INA219MODE
+ D_CMND_CFGDUMP "|" D_CMND_I2CSCAN
#ifdef DEBUG_THEO
"|" D_CMND_EXCEPTION
#endif
@@ -186,21 +186,12 @@ uint8_t light_type = 0; // Light types
boolean mdns_begun = false;
-uint8_t xdrv_present = 0; // Number of drivers found
-boolean (*xdrv_func_ptr[XDRV_MAX])(byte); // Driver Function Pointers
-uint8_t xsns_present = 0; // Number of External Sensors found
-boolean (*xsns_func_ptr[XSNS_MAX])(byte); // External Sensor Function Pointers for simple implementation of sensors
char my_version[33]; // Composed version string
char my_hostname[33]; // Composed Wifi hostname
char mqtt_client[33]; // Composed MQTT Clientname
char serial_in_buffer[INPUT_BUFFER_SIZE + 2]; // Receive buffer
-
-//char mqtt_data[MESSZ + TOPSZ]; // MQTT publish buffer (MESSZ) and web page ajax buffer (MESSZ + TOPSZ)
char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer
-
-//char log_data[TOPSZ + MESSZ]; // Logging
char log_data[LOGSZ]; // Logging
-
String web_log[MAX_LOG_LINES]; // Web log buffer
String backlog[MAX_BACKLOG]; // Command backlog
@@ -298,7 +289,7 @@ void SetDevicePower(power_t rpower)
{
uint8_t state;
- if (4 == Settings.poweronstate) { // All on and stay on
+ if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on
power = (1 << devices_present) -1;
rpower = power;
}
@@ -317,7 +308,7 @@ void SetDevicePower(power_t rpower)
}
}
- XdrvSetPower(bitRead(rpower, devices_present -1));
+ XdrvSetPower(rpower);
if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) {
Serial.write(0xA0);
@@ -938,6 +929,10 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
fallback_topic_flag = 0;
return;
}
+ else if (CMND_STATE == command_code) {
+ mqtt_data[0] = '\0';
+ MqttShowState();
+ }
else if ((CMND_POWERONSTATE == command_code) && (Settings.module != MOTOR)) {
/* 0 = Keep relays off after power on
* 1 = Turn relays on after power on, if PulseTime set wait for PulseTime seconds, and turn relays off
@@ -946,11 +941,11 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
* 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power)
* 5 = Keep relays off after power on, if PulseTime set wait for PulseTime seconds, and turn relays on
*/
- if ((payload >= 0) && (payload <= 5)) {
+ if ((payload >= POWER_ALL_OFF) && (payload <= POWER_ALL_OFF_PULSETIME_ON)) {
Settings.poweronstate = payload;
- if (4 == Settings.poweronstate) {
+ if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
for (byte i = 1; i <= devices_present; i++) {
- ExecuteCommandPower(i, 1);
+ ExecuteCommandPower(i, POWER_ON);
}
}
}
@@ -992,6 +987,17 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data));
}
+ else if (CMND_SENSOR == command_code) {
+ XdrvMailbox.topic = command;
+ XdrvMailbox.index = index;
+ XdrvMailbox.payload = payload;
+ XdrvMailbox.data_len = data_len;
+ XdrvMailbox.data = dataBuf;
+ XsnsCall(FUNC_COMMAND);
+// if (!XsnsCall(FUNC_COMMAND)) {
+// type = NULL;
+// }
+ }
else if ((CMND_SETOPTION == command_code) && ((index >= 0) && (index <= 19)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
if (index <= 31) {
ptype = 0; // SetOption0 .. 31
@@ -1494,15 +1500,6 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
I2cScan(mqtt_data, sizeof(mqtt_data));
}
#endif // USE_I2C
-#ifdef USE_INA219
- else if (CMND_INA219MODE == command_code) {
- if ((payload >= 0) && (payload <= 2)) {
- Settings.ina219_mode = payload;
- restart_flag = 2;
- }
- snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ina219_mode);
- }
-#endif // USE_INA219
else if (Settings.flag.mqtt_enabled && MqttCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) {
// Serviced
}
@@ -1589,7 +1586,7 @@ void ExecuteCommandPower(byte device, byte state)
// state 9 = Show power state
uint8_t publish_power = 1;
- if ((6 == state) || (7 == state)) {
+ if ((POWER_OFF_NO_STATE == state) || (POWER_ON_NO_STATE == state)) {
state &= 1;
publish_power = 0;
}
@@ -1600,7 +1597,7 @@ void ExecuteCommandPower(byte device, byte state)
pulse_timer[(device -1)] = 0;
}
power_t mask = 1 << (device -1);
- if (state <= 2) {
+ if (state <= POWER_TOGGLE) {
if ((blink_mask & mask)) {
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
MqttPublishPowerBlinkState(device);
@@ -1610,19 +1607,19 @@ void ExecuteCommandPower(byte device, byte state)
for (byte i = 0; i < devices_present; i++) {
power_t imask = 1 << i;
if ((power & imask) && (mask != imask)) {
- ExecuteCommandPower(i +1, 0);
+ ExecuteCommandPower(i +1, POWER_OFF);
}
}
interlock_mutex = 0;
}
switch (state) {
- case 0: { // Off
+ case POWER_OFF: {
power &= (POWER_MASK ^ mask);
break; }
- case 1: // On
+ case POWER_ON:
power |= mask;
break;
- case 2: // Toggle
+ case POWER_TOGGLE:
power ^= mask;
}
SetDevicePower(power);
@@ -1631,10 +1628,10 @@ void ExecuteCommandPower(byte device, byte state)
#endif // USE_DOMOTICZ
if (device <= MAX_PULSETIMERS) {
// pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0;
- pulse_timer[(device -1)] = (((5 == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1)] : 0;
+ pulse_timer[(device -1)] = (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1)] : 0;
}
}
- else if (3 == state) { // Blink
+ else if (POWER_BLINK == state) {
if (!(blink_mask & mask)) {
blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state
blink_power = (power >> (device -1))&1; // Prep to Toggle
@@ -1645,7 +1642,7 @@ void ExecuteCommandPower(byte device, byte state)
MqttPublishPowerBlinkState(device);
return;
}
- else if (4 == state) { // No Blink
+ else if (POWER_BLINK_STOP == state) {
byte flag = (blink_mask & mask);
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
MqttPublishPowerBlinkState(device);
@@ -1796,9 +1793,15 @@ void MqttShowState()
dtostrfd((double)ESP.getVcc()/1000, 3, stemp1);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1);
#endif
+
for (byte i = 0; i < devices_present; i++) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1)), GetStateText(bitRead(power, i)));
+ if (i == light_device -1) {
+ LightState(1);
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1)), GetStateText(bitRead(power, i)));
+ }
}
+
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"),
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
}
@@ -1815,7 +1818,7 @@ boolean MqttShowSensor()
}
XsnsCall(FUNC_JSON_APPEND);
boolean json_data_available = (strlen(mqtt_data) - json_data_start);
- if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) {
+ if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit());
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
@@ -1957,7 +1960,7 @@ void ButtonHandler()
}
if (button_pressed) {
if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
- ExecuteCommandPower(i +1, 2); // Execute Toggle command internally
+ ExecuteCommandPower(i +1, POWER_TOGGLE); // Execute Toggle command internally
}
}
} else {
@@ -1966,7 +1969,7 @@ void ButtonHandler()
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_IMMEDIATE), i +1);
AddLog(LOG_LEVEL_DEBUG);
if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
- ExecuteCommandPower(i +1, 2); // Execute Toggle command internally
+ ExecuteCommandPower(i +1, POWER_TOGGLE); // Execute Toggle command internally
}
} else {
multipress[i] = (multiwindow[i]) ? multipress[i] +1 : 1;
@@ -2021,7 +2024,7 @@ void ButtonHandler()
if (WifiState()) { // WPSconfig, Smartconfig or Wifimanager active
restart_flag = 1;
} else {
- ExecuteCommandPower(i + multipress[i], 2); // Execute Toggle command internally
+ ExecuteCommandPower(i + multipress[i], POWER_TOGGLE); // Execute Toggle command internally
}
} else { // 3 - 7 press
if (!Settings.flag.button_restrict) {
@@ -2109,7 +2112,7 @@ void SwitchHandler()
if (switchflag < 3) {
if (!send_button_power(1, i +1, switchflag)) { // Execute command via MQTT
- ExecuteCommandPower(i +1, switchflag); // Execute command internally (if i < devices_present)
+ ExecuteCommandPower(i +1, switchflag); // Execute command internally (if i < devices_present)
}
}
@@ -2160,8 +2163,8 @@ void StateLoop()
if ((pulse_timer[i] > 0) && (pulse_timer[i] < 112)) {
pulse_timer[i]--;
if (!pulse_timer[i]) {
-// ExecuteCommandPower(i +1, 0);
- ExecuteCommandPower(i +1, (5 == Settings.poweronstate) ? 1: 0);
+// ExecuteCommandPower(i +1, POWER_OFF);
+ ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF);
}
}
}
@@ -2640,7 +2643,7 @@ void GpioInit()
}
SetLedPower(Settings.ledstate &8);
- XDrvInit();
+ XdrvCall(FUNC_INIT);
}
extern "C" {
@@ -2700,29 +2703,29 @@ void setup()
GetMqttClient(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client));
if (MOTOR == Settings.module) {
- Settings.poweronstate = 1; // Needs always on else in limbo!
+ Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo!
}
- if (4 == Settings.poweronstate) { // Allways on
+ if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
SetDevicePower(1);
} else {
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
switch (Settings.poweronstate) {
- case 0: // All off
- case 5: // All off but on after PulseTime
+ case POWER_ALL_OFF:
+ case POWER_ALL_OFF_PULSETIME_ON:
power = 0;
SetDevicePower(power);
break;
- case 1: // All on
+ case POWER_ALL_ON: // All on
power = (1 << devices_present) -1;
SetDevicePower(power);
break;
- case 2: // All saved state toggle
+ case POWER_ALL_SAVED_TOGGLE:
power = Settings.power & ((1 << devices_present) -1) ^ POWER_MASK;
if (Settings.flag.save_state) {
SetDevicePower(power);
}
break;
- case 3: // All saved state
+ case POWER_ALL_SAVED:
power = Settings.power & ((1 << devices_present) -1);
if (Settings.flag.save_state) {
SetDevicePower(power);
@@ -2742,8 +2745,7 @@ void setup()
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i));
}
-// if ((i < MAX_PULSETIMERS) && bitRead(power, i)) {
- if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (5 == Settings.poweronstate))) {
+ if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) {
pulse_timer[i] = Settings.pulse_timer[i];
}
}
@@ -2759,7 +2761,7 @@ void setup()
#endif // BE_MINIMAL
RtcInit();
- XSnsInit();
+ XsnsCall(FUNC_INIT);
}
void loop()
diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
index 7e180ddf8..97ef8a0bb 100644
--- a/sonoff/sonoff_template.h
+++ b/sonoff/sonoff_template.h
@@ -885,6 +885,20 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
0, 0, 0
}
+ { "MagicHome v2.3", // Magic Home (aka Flux-light) (ESP8266) (#1353)
+ 0, 0,
+ GPIO_LED1_INV, // GPIO02 Blue onboard LED
+ 0,
+ GPIO_USER, // GPIO04 IR receiver (optional)
+ GPIO_PWM2, // GPIO05 RGB LED Green
+ 0, 0, 0, 0, 0, 0, // Flash connection
+ GPIO_PWM1, // GPIO12 RGB LED Red
+ GPIO_PWM3, // GPIO13 RGB LED Blue
+ 0,
+ GPIO_PWM4, // GPIO15 RGBW LED White
+ 0, 0
+ },
+
*/
#endif // _SONOFF_TEMPLATE_H_
\ No newline at end of file
diff --git a/sonoff/support.ino b/sonoff/support.ino
index 3bf651662..48b218386 100644
--- a/sonoff/support.ino
+++ b/sonoff/support.ino
@@ -148,83 +148,9 @@ Decoding 14 results
* General
\*********************************************************************************************/
-char* _dtostrf(double number, unsigned char prec, char *s, bool i18n)
+char* dtostrfd(double number, unsigned char prec, char *s)
{
- bool negative = false;
-
- if (isnan(number)) {
- strcpy_P(s, PSTR("nan"));
- return s;
- }
- if (isinf(number)) {
- strcpy_P(s, PSTR("inf"));
- return s;
- }
- char decimal = '.';
- if (i18n) {
- decimal = D_DECIMAL_SEPARATOR[0];
- }
-
- char* out = s;
-
- // Handle negative numbers
- if (number < 0.0) {
- negative = true;
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- // I optimized out most of the divisions
- double rounding = 2.0;
- for (uint8_t i = 0; i < prec; ++i) {
- rounding *= 10.0;
- }
- rounding = 1.0 / rounding;
- number += rounding;
-
- // Figure out how big our number really is
- double tenpow = 1.0;
- int digitcount = 1;
- while (number >= 10.0 * tenpow) {
- tenpow *= 10.0;
- digitcount++;
- }
- number /= tenpow;
-
- // Handle negative sign
- if (negative) {
- *out++ = '-';
- }
-
- // Print the digits, and if necessary, the decimal point
- digitcount += prec;
- int8_t digit = 0;
- while (digitcount-- > 0) {
- digit = (int8_t)number;
- if (digit > 9) {
- digit = 9; // insurance
- }
- *out++ = (char)('0' | digit);
- if ((digitcount == prec) && (prec > 0)) {
- *out++ = decimal;
- }
- number -= digit;
- number *= 10.0;
- }
-
- // make sure the string is terminated
- *out = 0;
- return s;
-}
-
-char* dtostrfd(double number, unsigned char prec, char *s) // Always decimal dot
-{
- return _dtostrf(number, prec, s, 0);
-}
-
-char* dtostrfi(double number, unsigned char prec, char *s) // Use localized decimal dot
-{
- return _dtostrf(number, prec, s, 1);
+ return dtostrf(number, 1, prec, s);
}
boolean ParseIp(uint32_t* addr, const char* str)
diff --git a/sonoff/user_config.h b/sonoff/user_config.h
index 471e912a1..225e11725 100644
--- a/sonoff/user_config.h
+++ b/sonoff/user_config.h
@@ -120,8 +120,9 @@
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional)
// -- MQTT - Home Assistant Discovery -------------
-#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery (+1k4 code)
+#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+1k4 code)
#define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix
+ #define HOME_ASSISTANT_DISCOVERY_ENABLE 0 // [SetOption19] Home Assistant Discovery (0 = Disable, 1 = Enable)
// -- HTTP ----------------------------------------
#define USE_WEBSERVER // Enable web server and wifi manager (+66k code, +8k mem) - Disable by //
diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino
index fa0f7dec0..b0c20c5a2 100644
--- a/sonoff/webserver.ino
+++ b/sonoff/webserver.ino
@@ -73,7 +73,9 @@ const char HTTP_HEAD[] PROGMEM =
"}"
"function lc(p){"
"la('?t='+p);"
- "}"
+ "}";
+
+const char HTTP_HEAD_STYLE[] PROGMEM =
""
"");
@@ -1580,6 +1677,7 @@ void HandleRestart()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_RESTART));
+ page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_MSG_RSTRT);
if (HTTP_MANAGER == webserver_state) {
webserver_state = HTTP_ADMIN;
@@ -1609,18 +1707,13 @@ void HandleNotFound()
} else
#endif // USE_EMULATION
{
- String message = F(D_FILE_NOT_FOUND "\n\nURI: ");
- message += WebServer->uri();
- message += F("\nMethod: ");
- message += (WebServer->method() == HTTP_GET) ? F("GET") : F("POST");
- message += F("\nArguments: ");
- message += WebServer->args();
- message += F("\n");
- for ( uint8_t i = 0; i < WebServer->args(); i++ ) {
- message += " " + WebServer->argName(i) + ": " + WebServer->arg(i) + "\n";
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"),
+ WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
+ for (uint8_t i = 0; i < WebServer->args(); i++) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str());
}
SetHeader();
- WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), message);
+ WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data);
}
}
diff --git a/sonoff/xdrv_01_light.ino b/sonoff/xdrv_01_light.ino
index 5b7dc0b7c..96f9c2f1d 100644
--- a/sonoff/xdrv_01_light.ino
+++ b/sonoff/xdrv_01_light.ino
@@ -99,6 +99,7 @@ uint8_t light_signal_color[5];
uint8_t light_wheel = 0;
uint8_t light_subtype = 0;
+uint8_t light_device = 0;
uint8_t light_power = 0;
uint8_t light_update = 1;
uint8_t light_wakeup_active = 0;
@@ -337,6 +338,7 @@ void LightInit()
{
uint8_t max_scheme = LS_MAX -1;
+ light_device = devices_present;
light_subtype = light_type &7;
if (light_type < LT_PWM6) { // PWM
@@ -526,35 +528,56 @@ char* LightGetColor(uint8_t type, char* scolor)
void LightPowerOn()
{
if (Settings.light_dimmer && !(light_power)) {
- ExecuteCommandPower(devices_present, 1);
+ ExecuteCommandPower(light_device, POWER_ON);
}
}
-void LightPreparePower()
+void LightState(uint8_t append)
{
char scolor[25];
char scommand[33];
- if (Settings.light_dimmer && !(light_power)) {
- ExecuteCommandPower(devices_present, 7); // No publishPowerState
+ if (append) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
}
- else if (!Settings.light_dimmer && light_power) {
- ExecuteCommandPower(devices_present, 6); // No publishPowerState
- }
-#ifdef USE_DOMOTICZ
- DomoticzUpdatePowerState(devices_present);
-#endif // USE_DOMOTICZ
-
- GetPowerDevice(scommand, devices_present, sizeof(scommand));
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"),
- scommand, GetStateText(light_power), Settings.light_dimmer);
+ GetPowerDevice(scommand, light_device, sizeof(scommand));
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"),
+ mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer);
if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
}
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp());
}
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
+ if (append) {
+ if (light_subtype >= LST_RGB) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_SCHEME "\":%d"), mqtt_data, Settings.light_scheme);
+ }
+ if (LT_WS2812 == light_type) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_WIDTH "\":%d"), mqtt_data, Settings.light_width);
+ }
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""),
+ mqtt_data, GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction));
+ } else {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
+ }
+}
+
+void LightPreparePower()
+{
+ if (Settings.light_dimmer && !(light_power)) {
+ ExecuteCommandPower(light_device, POWER_ON_NO_STATE);
+ }
+ else if (!Settings.light_dimmer && light_power) {
+ ExecuteCommandPower(light_device, POWER_OFF_NO_STATE);
+ }
+#ifdef USE_DOMOTICZ
+ DomoticzUpdatePowerState(light_device);
+#endif // USE_DOMOTICZ
+
+ LightState(0);
}
void LightFade()
@@ -638,7 +661,8 @@ void LightRandomColor()
void LightSetPower()
{
- light_power = XdrvMailbox.index;
+// light_power = XdrvMailbox.index;
+ light_power = bitRead(XdrvMailbox.index, light_device -1);
if (light_wakeup_active) {
light_wakeup_active--;
}
diff --git a/sonoff/xdrv_02_irremote.ino b/sonoff/xdrv_02_irremote.ino
index 11e95b7d8..3efca0ea3 100644
--- a/sonoff/xdrv_02_irremote.ino
+++ b/sonoff/xdrv_02_irremote.ino
@@ -309,21 +309,26 @@ boolean IrSendCommand()
data = ir_json[D_JSON_IR_DATA];
if (protocol && bits && data) {
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
+
+ snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %d, protocol_code %d"),
+ protocol_text, protocol, bits, data, protocol_code);
+ AddLog(LOG_LEVEL_DEBUG);
+
switch (protocol_code) {
case NEC:
- irsend->sendNEC(data, bits); break;
+ irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break;
case SONY:
- irsend->sendSony(data, bits); break;
+ irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break;
case RC5:
irsend->sendRC5(data, bits); break;
case RC6:
irsend->sendRC6(data, bits); break;
case DISH:
- irsend->sendDISH(data, bits); break;
+ irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break;
case JVC:
- irsend->sendJVC(data, bits, 1); break;
+ irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break;
case SAMSUNG:
- irsend->sendSAMSUNG(data, bits); break;
+ irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break;
case PANASONIC:
irsend->sendPanasonic(bits, data); break;
default:
diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino
index 8d62536ab..3377c390d 100644
--- a/sonoff/xdrv_03_energy.ino
+++ b/sonoff/xdrv_03_energy.ino
@@ -49,7 +49,7 @@ float energy_daily = 0; // 12.123 kWh
float energy_total = 0; // 12345.12345 kWh
float energy_start = 0; // 12345.12345 kWh total from yesterday
unsigned long energy_kWhtoday; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily
-unsigned long energy_period = 0; //
+unsigned long energy_period = 0; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily
byte energy_min_power_flag = 0;
byte energy_max_power_flag = 0;
@@ -227,7 +227,7 @@ void HlwInit()
hlw_cf1_current_max_pulse_counter = 0;
hlw_load_off = 1;
- hlw_energy_period_counter = 0;
+ hlw_energy_period_counter = 1;
hlw_select_ui_flag = 0; // Voltage;
@@ -437,6 +437,7 @@ void Energy200ms()
Settings.energy_kWhtotal += (energy_kWhtoday / 1000);
RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal;
energy_kWhtoday = 0;
+ energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
#ifdef USE_PZEM004T
if (ENERGY_PZEM004T == energy_flg) {
@@ -451,6 +452,7 @@ void Energy200ms()
}
if (energy_startup && (RtcTime.day_of_year == Settings.energy_kWhdoy)) {
energy_kWhtoday = Settings.energy_kWhtoday;
+ energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
energy_start = (float)Settings.hlw_power_calibration / 1000; // Used by PZEM004T to store total yesterday
energy_startup = 0;
@@ -573,7 +575,7 @@ void EnergyMarginCheck()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
- ExecuteCommandPower(1, 0);
+ ExecuteCommandPower(1, POWER_OFF);
if (!energy_mplr_counter) {
energy_mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
}
@@ -595,7 +597,7 @@ void EnergyMarginCheck()
if (energy_mplr_counter) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR));
- ExecuteCommandPower(1, 1);
+ ExecuteCommandPower(1, POWER_ON);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0));
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
@@ -613,7 +615,7 @@ void EnergyMarginCheck()
energy_max_energy_state = 1;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
- ExecuteCommandPower(1, 1);
+ ExecuteCommandPower(1, POWER_ON);
}
else if ((1 == energy_max_energy_state) && (energy_daily_u >= Settings.energy_max_energy)) {
energy_max_energy_state = 2;
@@ -621,7 +623,7 @@ void EnergyMarginCheck()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
- ExecuteCommandPower(1, 0);
+ ExecuteCommandPower(1, POWER_OFF);
}
}
#endif // FEATURE_POWER_LIMIT
@@ -699,6 +701,7 @@ boolean EnergyCommand()
switch (XdrvMailbox.index) {
case 1:
energy_kWhtoday = lnum *100000;
+ energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
Settings.energy_kWhtoday = energy_kWhtoday;
break;
@@ -856,7 +859,7 @@ void EnergyInit()
if (energy_flg) {
energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : 0;
-
+ energy_period = energy_kWhtoday;
energy_startup = 1;
ticker_energy.attach_ms(200, Energy200ms);
}
diff --git a/sonoff/xdrv_05_domoticz.ino b/sonoff/xdrv_05_domoticz.ino
index 4aa228d75..0272d4947 100644
--- a/sonoff/xdrv_05_domoticz.ino
+++ b/sonoff/xdrv_05_domoticz.ino
@@ -25,20 +25,18 @@ const char HTTP_FORM_DOMOTICZ[] PROGMEM =
""
"
" D_DOMOTICZ_IDX " {1 | |
" D_DOMOTICZ_KEY_IDX " {1 | |
" D_DOMOTICZ_IDX " {1 | |
" D_DOMOTICZ_KEY_IDX " {1 | |
" D_DOMOTICZ_SWITCH_IDX " {1 | |
" D_DOMOTICZ_SWITCH_IDX " {1 | |
" D_DOMOTICZ_SENSOR_IDX " {1 {2 | |
" D_DOMOTICZ_SENSOR_IDX " {1 {2 | |
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ") | |
" D_DOMOTICZ_UPDATE_TIMER " (" STR(DOMOTICZ_UPDATE_TIMER) ") |