diff --git a/README.md b/README.md
index 581b38e83..3f695f666 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,7 @@ The following devices are supported:
- [Supla device - Espablo-inCan mod. for electrical Installation box](https://forum.supla.org/viewtopic.php?f=33&t=2188)
- [BlitzWolf BW-SHP2 Smart Socket with Energy Monitoring](https://www.banggood.com/BlitzWolf-BW-SHP2-Smart-WIFI-Socket-EU-Plug-220V-16A-Work-with-Amazon-Alexa-Google-Assistant-p-1292899.html)
- [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/)
+- Xiaomi-Phillips Bulbs
- Wemos D1 mini, NodeMcu and Ledunia
### Contribute
diff --git a/platformio.ini b/platformio.ini
index 4cda52b6f..d333fd187 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -61,6 +61,7 @@ build_unflags = -Wall
build_flags =
-Wl,-Tesp8266.flash.1m0.ld
+ -mtarget-align
; -DUSE_CONFIG_OVERRIDE
; lwIP 1.4 (Default)
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
index 49193dfbd..eed6ffcc7 100644
--- a/sonoff/_changelog.ino
+++ b/sonoff/_changelog.ino
@@ -1,7 +1,17 @@
-/* 6.2.1.2 20180906
- * Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710)
+/* 6.2.1.3 20180907
+ * Change web Configure Module GPIO drop down list order for better readability
+ * Fix showing Period Power in energy threshold messages
+ * Fix ButtonRetain to not use default topic for clearing retain messages (#3737)
+ * Add sleep to Nova Fitness SDS01X sensor (#2841, #3724, #3749)
+ * Add Analog input AD0 enabled to sonoff-sensors.bin (#3756, #3757)
+ * Add Support to Xiaomi-Phillips Bulbs
+ *
+ * 6.2.1.2 20180906
+ * Fix KNX PA exception. Regression from 6.2.1 buffer overflow caused by subStr() (#3700, #3710)
* Add command SetOption52 to control display of optional time offset from UTC in JSON messages (#3629, #3711)
* Add experimental support for PZEM-003,014,016,017 Energy monitoring (#3694)
+ * Add basic support for MP3 player using DFRobot RB-DFR-562 (#3723)
+ * Fix setting and getting color temperature for Philips Hue emulation (#3733)
*
* 6.2.1.1 20180905
* Rewrite energy monitoring using energy sensor driver modules
diff --git a/sonoff/i18n.h b/sonoff/i18n.h
index 5559ac6d1..da47371d8 100644
--- a/sonoff/i18n.h
+++ b/sonoff/i18n.h
@@ -181,6 +181,7 @@
#define D_CMND_PRESSURE_RESOLUTION "PressRes"
#define D_CMND_POWER_RESOLUTION "WattRes"
#define D_CMND_VOLTAGE_RESOLUTION "VoltRes"
+#define D_CMND_FREQUENCY_RESOLUTION "FreqRes"
#define D_CMND_CURRENT_RESOLUTION "AmpRes"
#define D_CMND_ENERGY_RESOLUTION "EnergyRes"
#define D_CMND_MODULE "Module"
diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h
index bd76cf0be..266714fe4 100644
--- a/sonoff/language/bg-BG.h
+++ b/sonoff/language/bg-BG.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Подсветка"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h
index 0a3430e01..9a0b11062 100644
--- a/sonoff/language/cs-CZ.h
+++ b/sonoff/language/cs-CZ.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h
index 32d6a8f2b..a6e62c557 100644
--- a/sonoff/language/de-DE.h
+++ b/sonoff/language/de-DE.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h
index b2fa8feb6..715b2a7cf 100644
--- a/sonoff/language/el-GR.h
+++ b/sonoff/language/el-GR.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h
index a622419fa..9ac6c1fad 100644
--- a/sonoff/language/en-GB.h
+++ b/sonoff/language/en-GB.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h
index 398d0442f..7d0408080 100644
--- a/sonoff/language/es-AR.h
+++ b/sonoff/language/es-AR.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h
index a4b7d2011..7e6ea07b9 100644
--- a/sonoff/language/fr-FR.h
+++ b/sonoff/language/fr-FR.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "RétroÉcl"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h
index 79fd88d8e..ef2c28f80 100644
--- a/sonoff/language/hu-HU.h
+++ b/sonoff/language/hu-HU.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Háttérvil"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h
index 509105eb5..ac818a9f2 100644
--- a/sonoff/language/it-IT.h
+++ b/sonoff/language/it-IT.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h
index 2761e45d3..273699477 100644
--- a/sonoff/language/nl-NL.h
+++ b/sonoff/language/nl-NL.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h
index 9fa16ac9f..199f7cce9 100644
--- a/sonoff/language/pl-PL.h
+++ b/sonoff/language/pl-PL.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h
index 46a21b998..8770b9a4a 100644
--- a/sonoff/language/pt-BR.h
+++ b/sonoff/language/pt-BR.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Luz de fundo"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h
index d4cea0a48..0b7715583 100644
--- a/sonoff/language/pt-PT.h
+++ b/sonoff/language/pt-PT.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Luz negra"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h
index e782e9409..e61cbb9c1 100644
--- a/sonoff/language/ru-RU.h
+++ b/sonoff/language/ru-RU.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h
index 1f11d4a01..086c236aa 100755
--- a/sonoff/language/tr-TR.h
+++ b/sonoff/language/tr-TR.h
@@ -476,6 +476,8 @@
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h
index 90cfb9f4a..19094d574 100644
--- a/sonoff/language/uk-UK.h
+++ b/sonoff/language/uk-UK.h
@@ -476,6 +476,8 @@
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h
index 24eb38f6f..ea15b6ccb 100644
--- a/sonoff/language/zh-CN.h
+++ b/sonoff/language/zh-CN.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h
index c07023268..f4f439c8b 100644
--- a/sonoff/language/zh-TW.h
+++ b/sonoff/language/zh-TW.h
@@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
-#define D_SENSOR_SDS0X1 "SDS0X1"
+#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
+#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
diff --git a/sonoff/settings.h b/sonoff/settings.h
index 32bc80ad0..a1fd218ac 100644
--- a/sonoff/settings.h
+++ b/sonoff/settings.h
@@ -112,8 +112,7 @@ typedef union {
uint32_t spare08 : 1;
uint32_t spare09 : 1;
uint32_t spare10 : 1;
- uint32_t spare11 : 1;
- uint32_t spare12 : 1;
+ uint32_t frequency_resolution : 2;
uint32_t axis_resolution : 2;
uint32_t current_resolution : 2;
uint32_t voltage_resolution : 2;
diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino
index 6163acfa4..a55e896c4 100755
--- a/sonoff/sonoff.ino
+++ b/sonoff/sonoff.ino
@@ -77,8 +77,8 @@
enum TasmotaCommands {
CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_FANSPEED, 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_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_FREQUENCY_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_BUTTONDEBOUNCE, CMND_SWITCHDEBOUNCE, 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,
@@ -87,8 +87,8 @@ enum TasmotaCommands {
const char kTasmotaCommands[] PROGMEM =
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_FANSPEED "|" 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_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_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_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" 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 "|"
@@ -134,7 +134,7 @@ int ota_state_flag = 0; // OTA state flag
int ota_result = 0; // OTA result
int restart_flag = 0; // Sonoff restart flag
int wifi_state_flag = WIFI_RESTART; // Wifi state flag
-int tele_period = 0; // Tele period timer
+int tele_period = 1; // Tele period timer
int blinks = 201; // Number of LED blinks
uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year
uint32_t global_update = 0; // Timestamp of last global temperature and humidity update
@@ -794,6 +794,12 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution);
}
+ else if (CMND_FREQUENCY_RESOLUTION == command_code) {
+ if ((payload >= 0) && (payload <= 3)) {
+ Settings.flag2.frequency_resolution = payload;
+ }
+ snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution);
+ }
else if (CMND_CURRENT_RESOLUTION == command_code) {
if ((payload >= 0) && (payload <= 3)) {
Settings.flag2.current_resolution = payload;
@@ -843,10 +849,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) {
mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
-// if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
if ((GPIO_USER == ValidGPIO(index, cmodule.gp.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
-// if ((GPIO_USER == cmodule.gp.io[i]) && (Settings.my_gp.io[i] == payload)) {
if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) {
Settings.my_gp.io[i] = 0;
}
@@ -856,7 +860,6 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
-// if (GPIO_USER == cmodule.gp.io[i]) {
if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
jsflg = 1;
@@ -1001,7 +1004,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
else if (CMND_SYSLOG == command_code) {
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
Settings.syslog_level = payload;
- syslog_level = (Settings.flag2.emulation) ? 0 : payload;
+ syslog_level = payload;
syslog_timer = 0;
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level);
@@ -1593,7 +1596,7 @@ void PerformEverySecond()
if (syslog_timer) { // Restore syslog level
syslog_timer--;
if (!syslog_timer) {
- syslog_level = (Settings.flag2.emulation) ? 0 : Settings.syslog_level;
+ syslog_level = Settings.syslog_level;
if (Settings.syslog_level) {
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose)
}
@@ -2510,7 +2513,7 @@ void setup()
#ifndef USE_EMULATION
Settings.flag2.emulation = 0;
#endif // USE_EMULATION
- syslog_level = (Settings.flag2.emulation) ? 0 : Settings.syslog_level;
+ syslog_level = Settings.syslog_level;
stop_flash_rotate = Settings.flag.stop_flash_rotate;
save_data_counter = Settings.save_data;
sleep = Settings.sleep;
diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h
index 7504af3b4..8622d0818 100755
--- a/sonoff/sonoff_post.h
+++ b/sonoff/sonoff_post.h
@@ -62,7 +62,10 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#ifdef USE_SENSORS
-#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
+#ifdef USE_ADC_VCC
+#undef USE_ADC_VCC
+#endif
+//#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
#define USE_DS18x20 // For more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code)
//#define USE_DS18x20_LEGACY // For more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code)
#define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)
diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h
index 2ab43286d..781b1004d 100644
--- a/sonoff/sonoff_template.h
+++ b/sonoff/sonoff_template.h
@@ -21,6 +21,8 @@
#define _SONOFF_TEMPLATE_H_
// User selectable GPIO functionality
+// ATTENTION: Only add at the end of this list just before GPIO_SENSOR_END
+// Then add the same name(s) in a nice location in array kGpioNiceList
enum UserSelectablePins {
GPIO_NONE, // Not used
GPIO_DHT11, // DHT11
@@ -92,7 +94,7 @@ enum UserSelectablePins {
GPIO_SPI_DC, // SPI Data Direction
GPIO_BACKLIGHT, // Display backlight control
GPIO_PMS5003, // Plantower PMS5003 Serial interface
- GPIO_SDS0X1, // Nova Fitness SDS011 Serial interface
+ GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
GPIO_SBR_TX, // Serial Bridge Serial interface
GPIO_SBR_RX, // Serial Bridge Serial interface
GPIO_SR04_TRIG, // SR04 Trigger pin
@@ -123,6 +125,7 @@ enum UserSelectablePins {
GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
+ GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality offset by user selectable GPIOs
@@ -164,7 +167,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|"
- D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1 "|"
+ D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1_RX "|"
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|"
@@ -174,7 +177,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|"
D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|"
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
- D_SENSOR_DFR562;
+ D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX;
/********************************************************************************************/
@@ -227,6 +230,7 @@ enum SupportedModules {
BLITZWOLF_BWSHP2,
SHELLY1,
SHELLY2,
+ PHILIPS,
MAXMODULE };
/********************************************************************************************/
@@ -244,7 +248,112 @@ typedef struct MYTMPLT {
myio gp;
} mytmplt;
-const uint8_t kNiceList[MAXMODULE] PROGMEM = {
+const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = {
+ GPIO_NONE, // Not used
+ GPIO_KEY1, // Buttons
+ GPIO_KEY1_NP,
+ GPIO_KEY2,
+ GPIO_KEY2_NP,
+ GPIO_KEY3,
+ GPIO_KEY3_NP,
+ GPIO_KEY4,
+ GPIO_KEY4_NP,
+ GPIO_SWT1, // User connected external switches
+ GPIO_SWT1_NP,
+ GPIO_SWT2,
+ GPIO_SWT2_NP,
+ GPIO_SWT3,
+ GPIO_SWT3_NP,
+ GPIO_SWT4,
+ GPIO_SWT4_NP,
+ GPIO_SWT5,
+ GPIO_SWT5_NP,
+ GPIO_SWT6,
+ GPIO_SWT6_NP,
+ GPIO_SWT7,
+ GPIO_SWT7_NP,
+ GPIO_SWT8,
+ GPIO_SWT8_NP,
+ GPIO_REL1, // Relays
+ GPIO_REL1_INV,
+ GPIO_REL2,
+ GPIO_REL2_INV,
+ GPIO_REL3,
+ GPIO_REL3_INV,
+ GPIO_REL4,
+ GPIO_REL4_INV,
+ GPIO_REL5,
+ GPIO_REL5_INV,
+ GPIO_REL6,
+ GPIO_REL6_INV,
+ GPIO_REL7,
+ GPIO_REL7_INV,
+ GPIO_REL8,
+ GPIO_REL8_INV,
+ GPIO_LED1, // Leds
+ GPIO_LED1_INV,
+ GPIO_LED2,
+ GPIO_LED2_INV,
+ GPIO_LED3,
+ GPIO_LED3_INV,
+ GPIO_LED4,
+ GPIO_LED4_INV,
+ GPIO_PWM1, // RGB Red or C Cold White
+ GPIO_PWM1_INV,
+ GPIO_PWM2, // RGB Green or CW Warm White
+ GPIO_PWM2_INV,
+ GPIO_PWM3, // RGB Blue
+ GPIO_PWM3_INV,
+ GPIO_PWM4, // RGBW (Cold) White
+ GPIO_PWM4_INV,
+ GPIO_PWM5, // RGBCW Warm White
+ GPIO_PWM5_INV,
+ GPIO_CNTR1, // Counters
+ GPIO_CNTR1_NP,
+ GPIO_CNTR2,
+ GPIO_CNTR2_NP,
+ GPIO_CNTR3,
+ GPIO_CNTR3_NP,
+ GPIO_CNTR4,
+ GPIO_CNTR4_NP,
+ GPIO_I2C_SCL, // I2C SCL
+ GPIO_I2C_SDA, // I2C SDA
+ GPIO_SPI_CS, // SPI Chip Select
+ GPIO_SPI_DC, // SPI Data Direction
+ GPIO_BACKLIGHT, // Display backlight control
+ GPIO_DHT11, // DHT11
+ GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321
+ GPIO_SI7021, // iTead SI7021
+ GPIO_DSB, // Single wire DS18B20 or DS18S20
+ GPIO_WS2812, // WS2812 Led string
+ GPIO_IRSEND, // IR remote
+ GPIO_IRRECV, // IR receiver
+ GPIO_SR04_TRIG, // SR04 Trigger pin
+ GPIO_SR04_ECHO, // SR04 Echo pin
+ GPIO_TM16CLK, // TM1638 Clock
+ GPIO_TM16DIO, // TM1638 Data I/O
+ GPIO_TM16STB, // TM1638 Strobe
+ GPIO_SBR_TX, // Serial Bridge Serial interface
+ GPIO_SBR_RX, // Serial Bridge Serial interface
+ GPIO_MHZ_TXD, // MH-Z19 Serial interface
+ GPIO_MHZ_RXD, // MH-Z19 Serial interface
+ GPIO_SAIR_TX, // SenseAir Serial interface
+ GPIO_SAIR_RX, // SenseAir Serial interface
+ GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
+ GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
+ GPIO_PZEM_TX, // PZEM004T Serial interface
+ GPIO_PZEM_RX, // PZEM004T Serial interface
+ GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface
+ GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface
+ GPIO_SDM120_TX, // SDM120 Serial interface
+ GPIO_SDM120_RX, // SDM120 Serial interface
+ GPIO_SDM630_TX, // SDM630 Serial interface
+ GPIO_SDM630_RX, // SDM630 Serial interface
+ GPIO_PMS5003, // Plantower PMS5003 Serial interface
+ GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
+};
+
+const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
SONOFF_BASIC,
SONOFF_RF,
SONOFF_TH,
@@ -291,7 +400,8 @@ const uint8_t kNiceList[MAXMODULE] PROGMEM = {
KMC_70011,
AILIGHT,
WEMOS,
- WITTY
+ WITTY,
+ PHILIPS
};
// Default module settings
@@ -936,6 +1046,14 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_SWT2_NP, // GPIO14
0, // GPIO15 MCP39F501 Reset
0, 0
+ },
+ { "Xiaomi Philips", // Xiaomi Philips bulb (ESP8266)
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ GPIO_PWM2, // GPIO12 cold/warm light
+ 0, 0,
+ GPIO_PWM1, // GPIO15 light intensity
+ 0, 0
}
};
diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h
index 178e0af68..f068473ab 100644
--- a/sonoff/sonoff_version.h
+++ b/sonoff/sonoff_version.h
@@ -20,7 +20,7 @@
#ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_
-#define VERSION 0x06020102
+#define VERSION 0x06020103
#define D_PROGRAMNAME "Sonoff-Tasmota"
#define D_AUTHOR "Theo Arends"
diff --git a/sonoff/support.ino b/sonoff/support.ino
index d00ee009b..af93fa148 100644
--- a/sonoff/support.ino
+++ b/sonoff/support.ino
@@ -628,7 +628,8 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
if (GPIO_PMS5003 == val) { return true; }
#endif
#ifndef USE_NOVA_SDS
- if (GPIO_SDS0X1 == val) { return true; }
+ if (GPIO_SDS0X1_TX == val) { return true; }
+ if (GPIO_SDS0X1_RX == val) { return true; }
#endif
#ifndef USE_SERIAL_BRIDGE
if (GPIO_SBR_TX == val) { return true; }
@@ -935,8 +936,20 @@ void GetFeatures()
#ifdef USE_DISPLAY_SH1106
feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino
#endif
+#ifdef USE_MP3_PLAYER
+ feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino
+#endif
+#ifdef NO_EXTRA_4K_HEAP
+ feature_drv2 |= 0x00800000; // sonoff_post.h
+#endif
+#ifdef VTABLES_IN_IRAM
+ feature_drv2 |= 0x01000000; // platformio.ini
+#endif
+#ifdef VTABLES_IN_DRAM
+ feature_drv2 |= 0x02000000; // platformio.ini
+#endif
#ifdef VTABLES_IN_FLASH
feature_drv2 |= 0x04000000; // platformio.ini
#endif
diff --git a/sonoff/user_config.h b/sonoff/user_config.h
index b7a54408d..357fe5fab 100644
--- a/sonoff/user_config.h
+++ b/sonoff/user_config.h
@@ -268,9 +268,6 @@
// -- Internal Analog input -----------------------
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
-// -- MP3 player ----------------------------------
-//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
-
// -- One wire sensors ----------------------------
// WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors
#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code)
@@ -338,11 +335,13 @@
#define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1)
#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code)
#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code)
+ #define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
#define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
#define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud)
+//#define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
// Power monitoring sensors -----------------------
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
diff --git a/sonoff/xdrv_01_mqtt.ino b/sonoff/xdrv_01_mqtt.ino
index c47728df0..f3f33d693 100644
--- a/sonoff/xdrv_01_mqtt.ino
+++ b/sonoff/xdrv_01_mqtt.ino
@@ -380,9 +380,7 @@ void MqttConnected()
MqttPublishPowerState(i);
if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay
}
- if (Settings.tele_period) {
- tele_period = Settings.tele_period -9;
- }
+ if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds
rules_flag.system_boot = 1;
XdrvCall(FUNC_MQTT_INIT);
}
@@ -718,7 +716,6 @@ bool MqttCommand()
}
else if (CMND_BUTTONRETAIN == command_code) {
if ((payload >= 0) && (payload <= 1)) {
- strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic));
if (!payload) {
for(i = 1; i <= MAX_KEYS; i++) {
SendKey(0, i, 9); // Clear MQTT retain in broker
@@ -730,7 +727,6 @@ bool MqttCommand()
}
else if (CMND_SWITCHRETAIN == command_code) {
if ((payload >= 0) && (payload <= 1)) {
- strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic));
if (!payload) {
for(i = 1; i <= MAX_SWITCHES; i++) {
SendKey(1, i, 9); // Clear MQTT retain in broker
diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino
index 4059459c5..6cadb952f 100644
--- a/sonoff/xdrv_02_webserver.ino
+++ b/sonoff/xdrv_02_webserver.ino
@@ -768,7 +768,7 @@ void HandleModuleConfiguration()
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE));
page += FPSTR(HTTP_SCRIPT_MODULE1);
for (byte i = 0; i < MAXMODULE; i++) {
- midx = pgm_read_byte(kNiceList + i);
+ midx = pgm_read_byte(kModuleNiceList + i);
snprintf_P(stemp, sizeof(stemp), kModules[midx].name);
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
page += mqtt_data;
@@ -779,10 +779,10 @@ void HandleModuleConfiguration()
mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
-
for (byte j = 0; j < GPIO_SENSOR_END; j++) {
- if (!GetUsedInModule(j, cmodule.gp.io)) {
- snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, j, j, GetTextIndexed(stemp, sizeof(stemp), j, kSensorNames));
+ midx = pgm_read_byte(kGpioNiceList + j);
+ if (!GetUsedInModule(midx, cmodule.gp.io)) {
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames));
page += mqtt_data;
}
}
@@ -805,7 +805,7 @@ void HandleModuleConfiguration()
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
snprintf_P(stemp, 3, PINS_WEMOS +i*2);
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("
%s " D_GPIO "%d %s | |
"),
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s " D_GPIO "%d %s | |
"),
(WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
page += mqtt_data;
}
@@ -1193,7 +1193,7 @@ void HandleSaveSettings()
if (Settings.last_module != new_module) {
Settings.my_gp.io[i] = 0;
} else {
- if (GPIO_USER == cmodule.gp.io[i]) {
+ if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp));
Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino
index d9cfee8cb..ac26a18da 100644
--- a/sonoff/xdrv_03_energy.ino
+++ b/sonoff/xdrv_03_energy.ino
@@ -44,11 +44,13 @@ const char kEnergyCommands[] PROGMEM =
float energy_voltage = 0; // 123.1 V
float energy_current = 0; // 123.123 A
float energy_power = 0; // 123.1 W
-float energy_frequency = 0; // 123.1 Hz
-float energy_power_factor = 0; // 0.12
+float energy_power_factor = NAN; // 0.12
+int energy_calc_power_factor = 0; // Do not calculate power factor from data
+float energy_frequency = NAN; // 123.1 Hz
+float energy_start = 0; // 12345.12345 kWh total previous
+
float energy_daily = 0; // 123.123 kWh
float energy_total = 0; // 12345.12345 kWh
-float energy_start = 0; // 12345.12345 kWh total previous
unsigned long energy_kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to energy_kWhtoday (HLW and CSE only)
unsigned long energy_kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily
unsigned long energy_period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = energy_daily
@@ -123,12 +125,14 @@ void Energy200ms()
XnrgCall(FUNC_EVERY_200_MSECOND);
- float power_factor = 0;
- if (energy_voltage && energy_current && energy_power) {
- power_factor = energy_power / (energy_voltage * energy_current);
- if (power_factor > 1) power_factor = 1;
+ if (energy_calc_power_factor) {
+ float power_factor = 0;
+ if (energy_voltage && energy_current && energy_power) {
+ power_factor = energy_power / (energy_voltage * energy_current);
+ if (power_factor > 1) power_factor = 1;
+ }
+ energy_power_factor = power_factor;
}
- energy_power_factor = power_factor;
}
void EnergySaveState()
@@ -300,7 +304,10 @@ void EnergyMqttShow()
{
// {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
+ int tele_period_save = tele_period;
+ tele_period = 2;
EnergyShow(1);
+ tele_period = tele_period_save;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
energy_power_delta = 0;
@@ -537,11 +544,18 @@ void EnergySnsInit()
}
#ifdef USE_WEBSERVER
-const char HTTP_ENERGY_SNS[] PROGMEM = "%s"
+const char HTTP_ENERGY_SNS1[] PROGMEM = "%s"
"{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"
"{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"
- "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"
- "{s}" D_POWER_FACTOR "{m}%s{e}"
+ "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}";
+
+const char HTTP_ENERGY_SNS2[] PROGMEM = "%s"
+ "{s}" D_POWER_FACTOR "{m}%s{e}";
+
+const char HTTP_ENERGY_SNS3[] PROGMEM = "%s"
+ "{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}";
+
+const char HTTP_ENERGY_SNS4[] PROGMEM = "%s"
"{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
"{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
"{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = , {m} = | , {e} = |
@@ -555,31 +569,43 @@ void EnergyShow(boolean json)
char energy_power_chr[10];
char energy_voltage_chr[10];
char energy_current_chr[10];
+ char energy_frequency_chr[10];
char energy_power_factor_chr[10];
char energy_yesterday_chr[10];
char speriod[20];
+ char spfactor[20];
+ char sfrequency[20];
bool show_energy_period = (0 == tele_period);
+ dtostrfd(energy_power, Settings.flag2.wattage_resolution, energy_power_chr);
+ dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, energy_voltage_chr);
+ dtostrfd(energy_current, Settings.flag2.current_resolution, energy_current_chr);
+ dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr);
+ dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr);
+ dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
+
float energy = 0;
if (show_energy_period) {
if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100;
energy_period = energy_kWhtoday;
+ dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
+ snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
+ }
+ if (!isnan(energy_frequency)) {
+ dtostrfd(energy_frequency, Settings.flag2.frequency_resolution, energy_frequency_chr);
+ snprintf_P(sfrequency, sizeof(sfrequency), PSTR(",\"" D_JSON_FREQUENCY "\":%s"), energy_frequency_chr);
+ }
+ if (!isnan(energy_power_factor)) {
+ dtostrfd(energy_power_factor, 2, energy_power_factor_chr);
+ snprintf_P(spfactor, sizeof(spfactor), PSTR(",\"" D_JSON_POWERFACTOR "\":%s"), energy_power_factor_chr);
}
- dtostrfd(energy_total, Settings.flag2.energy_resolution, energy_total_chr);
- dtostrfd(energy_daily, Settings.flag2.energy_resolution, energy_daily_chr);
- dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
- dtostrfd(energy_power, Settings.flag2.wattage_resolution, energy_power_chr);
- dtostrfd(energy_voltage, Settings.flag2.voltage_resolution, energy_voltage_chr);
- dtostrfd(energy_current, Settings.flag2.current_resolution, energy_current_chr);
- dtostrfd(energy_power_factor, 2, energy_power_factor_chr);
- dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
-
if (json) {
- snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
- snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"),
- mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", energy_power_chr, energy_power_factor_chr, energy_voltage_chr, energy_current_chr);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\""
+ D_JSON_POWERUSAGE "\":%s%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s%s}"),
+ mqtt_data, energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "",
+ energy_power_chr, (!isnan(energy_power_factor)) ? spfactor : "", energy_voltage_chr, energy_current_chr, (!isnan(energy_frequency)) ? sfrequency : "");
#ifdef USE_DOMOTICZ
if (show_energy_period) { // Only send if telemetry
dtostrfd(energy_total * 1000, 1, energy_total_chr);
@@ -593,7 +619,7 @@ void EnergyShow(boolean json)
KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage);
KnxSensor(KNX_ENERGY_CURRENT, energy_current);
KnxSensor(KNX_ENERGY_POWER, energy_power);
- KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor);
+ if (!isnan(energy_power_factor)) { KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor); }
KnxSensor(KNX_ENERGY_DAILY, energy_daily);
KnxSensor(KNX_ENERGY_TOTAL, energy_total);
KnxSensor(KNX_ENERGY_START, energy_start);
@@ -601,7 +627,10 @@ void EnergyShow(boolean json)
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
- snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr, energy_power_factor_chr, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS1, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr);
+ if (!isnan(energy_power_factor)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS2, mqtt_data, energy_power_factor_chr); }
+ if (!isnan(energy_frequency)) { snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS3, mqtt_data, energy_frequency_chr); }
+ snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS4, mqtt_data, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
#endif // USE_WEBSERVER
}
}
diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino
index 209fe467a..2a5a15b0c 100644
--- a/sonoff/xdrv_04_light.ino
+++ b/sonoff/xdrv_04_light.ino
@@ -427,6 +427,11 @@ void LightSetColorTemp(uint16_t ct)
}
uint16_t icold = (100 * (347 - my_ct)) / 136;
uint16_t iwarm = (100 * my_ct) / 136;
+ if (PHILIPS == Settings.module) {
+ // Xiaomi Philips bulbs follow a different scheme:
+ // channel 0=intensity, channel2=temperature
+ Settings.light_color[1] = (uint8_t)icold;
+ } else
if (LST_RGBWC == light_subtype) {
Settings.light_color[0] = 0;
Settings.light_color[1] = 0;
@@ -458,6 +463,15 @@ void LightSetDimmer(uint8_t myDimmer)
{
float temp;
+ if (PHILIPS == Settings.module) {
+ // Xiaomi Philips bulbs use two PWM channels with a different scheme:
+ float dimmer = 100 / (float)myDimmer;
+ temp = (float)Settings.light_color[0] / dimmer; // channel 1 is intensity
+ light_current_color[0] = (uint8_t)temp;
+ temp = (float)Settings.light_color[1]; // channel 2 is temperature
+ light_current_color[1] = (uint8_t)temp;
+ return;
+ }
if (LT_PWM1 == light_type) {
Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color
}
@@ -557,8 +571,8 @@ void LightState(uint8_t append)
if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
// Add status for HSB
- LightGetHsb(&hsb[0],&hsb[1],&hsb[2]);
- // Scale these percentages up to the numbers expected byt he client
+ LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false);
+ // Scale these percentages up to the numbers expected by the client
h = round(hsb[0] * 360);
s = round(hsb[1] * 100);
b = round(hsb[2] * 100);
@@ -911,13 +925,15 @@ void LightHsbToRgb()
light_current_color[0] = (uint8_t)(r * 255.0f);
light_current_color[1] = (uint8_t)(g * 255.0f);
light_current_color[2] = (uint8_t)(b * 255.0f);
+ light_current_color[3] = 0;
+ light_current_color[4] = 0;
}
/********************************************************************************************/
-void LightGetHsb(float *hue, float *sat, float *bri)
+void LightGetHsb(float *hue, float *sat, float *bri, bool gotct)
{
- if (light_subtype > LST_COLDWARM) {
+ if (light_subtype > LST_COLDWARM && !gotct) {
LightRgbToHsb();
*hue = light_hue;
*sat = light_saturation;
@@ -925,16 +941,19 @@ void LightGetHsb(float *hue, float *sat, float *bri)
} else {
*hue = 0;
*sat = 0;
-// *bri = (2.54f * (float)Settings.light_dimmer);
*bri = (0.01f * (float)Settings.light_dimmer);
}
}
-void LightSetHsb(float hue, float sat, float bri, uint16_t ct)
+void LightSetHsb(float hue, float sat, float bri, uint16_t ct, bool gotct)
{
if (light_subtype > LST_COLDWARM) {
- if ((LST_RGBWC == light_subtype) && (ct > 0)) {
- LightSetColorTemp(ct);
+ if ((LST_RGBWC == light_subtype) && (gotct)) {
+ uint8_t tmp = (uint8_t)(bri * 100);
+ Settings.light_dimmer = tmp;
+ if (ct > 0) {
+ LightSetColorTemp(ct);
+ }
} else {
light_hue = hue;
light_saturation = sat;
@@ -1114,7 +1133,7 @@ boolean LightCommand()
} else { // Command with only 1 parameter, Hue (0360) ? (HSB[0] % 360) : HSB[0] ) /360.0,
( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0,
( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0,
- 0);
+ 0,
+ false);
}
} else {
LightState(0);
diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino
index df27cb4cd..930bde7d5 100644
--- a/sonoff/xdrv_10_rules.ino
+++ b/sonoff/xdrv_10_rules.ino
@@ -426,7 +426,7 @@ void RulesEvery100ms()
{
if (Settings.rule_enabled) { // Any rule enabled
mqtt_data[0] = '\0';
- uint16_t tele_period_save = tele_period;
+ int tele_period_save = tele_period;
tele_period = 2; // Do not allow HA updates during next function call
XsnsNextCall(FUNC_JSON_APPEND); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
tele_period = tele_period_save;
diff --git a/sonoff/xdrv_91_mp3.ino b/sonoff/xdrv_14_mp3.ino
similarity index 83%
rename from sonoff/xdrv_91_mp3.ino
rename to sonoff/xdrv_14_mp3.ino
index 82c778127..e4c72cb16 100644
--- a/sonoff/xdrv_91_mp3.ino
+++ b/sonoff/xdrv_14_mp3.ino
@@ -1,32 +1,39 @@
/*
- xdrv_91_mp3.ino - MP3 Player support for Sonoff-Tasmota
- Player type: RB-DFR-562, DFPlayer Mini MP3 Player
- Copyright (C) 2018 Theo Arends
+ xdrv_14_mp3.ino - MP3 support for Sonoff-Tasmota
+
+ Copyright (C) 2018 gemu2015, mike2nl and Theo Arends
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
+
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-
*/
#ifdef USE_MP3_PLAYER
+/*********************************************************************************************\
+ * MP3 control for RB-DFR-562 DFRobot mini MP3 player
+ * https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299
+\*********************************************************************************************/
#include
TasmotaSerial *MP3Player;
#define D_CMND_MP3 "MP3"
+
const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}";
const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}";
enum MP3_Commands { CMND_MP3_PLAY, CMND_MP3_STOP, CMND_MP3_VOLUME};
-const char kMP3_Commands[] PROGMEM = "Play" "|" "Stop" "|" "Volume";
+const char kMP3_Commands[] PROGMEM = "Play|Stop|Volume";
#define MP3_CMD_PLAY 3
#define MP3_CMD_VOLUME 6
@@ -43,11 +50,10 @@ uint16_t MP3_Checksum(uint8_t *array)
}
// init player define serial tx port
-void InitMP3Player() {
- MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3PLAYER]);
-
+void MP3PlayerInit() {
+ MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]);
+
if (MP3Player->begin(9600)) {
- //serial_bridge_active = 1;
MP3Player->flush();
}
}
@@ -67,7 +73,7 @@ boolean MP3PlayerCmd() {
char command[CMDSZ];
boolean serviced = true;
uint8_t disp_len = strlen(D_CMND_MP3);
-
+
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // Prefix
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands);
@@ -82,7 +88,7 @@ boolean MP3PlayerCmd() {
MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload);
- }
+ }
else if (CMND_MP3_STOP == command_code) { // stop
MP3_CMD(MP3_CMD_STOP, 0);
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload);
@@ -97,15 +103,15 @@ boolean MP3PlayerCmd() {
* Interface
\*********************************************************************************************/
-#define XDRV_91
+#define XDRV_14
-boolean Xdrv91(byte function)
+boolean Xdrv14(byte function)
{
boolean result = false;
switch (function) {
case FUNC_PRE_INIT:
- InitMP3Player();
+ MP3PlayerInit();
break;
case FUNC_COMMAND:
result = MP3PlayerCmd();
@@ -114,4 +120,4 @@ boolean Xdrv91(byte function)
return result;
}
-#endif // USE_MP3_PLAYER
+#endif // USE_MP3_PLAYER
diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino
index 8a167511c..3cd2e69c5 100644
--- a/sonoff/xdrv_99_debug.ino
+++ b/sonoff/xdrv_99_debug.ino
@@ -182,6 +182,7 @@ void CpuLoadLoop()
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1)
// All version before core 2.4.2
+// https://github.com/esp8266/Arduino/issues/2557
extern "C" {
#include
@@ -190,7 +191,6 @@ extern "C" {
void DebugFreeMem()
{
-// https://github.com/esp8266/Arduino/issues/2557
register uint32_t *sp asm("a1");
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"),
@@ -213,7 +213,6 @@ extern "C" {
void DebugFreeMem()
{
-// https://github.com/esp8266/Arduino/issues/2557
register uint32_t *sp asm("a1");
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"),
diff --git a/sonoff/xdsp_05_epaper.ino b/sonoff/xdsp_05_epaper.ino
index 59a08584b..91eb747f2 100644
--- a/sonoff/xdsp_05_epaper.ino
+++ b/sonoff/xdsp_05_epaper.ino
@@ -188,7 +188,7 @@ boolean Xdsp05(byte function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
EpdInitDriver();
}
- else if (XDSP_04 == Settings.display_model) {
+ else if (XDSP_05 == Settings.display_model) {
if (!dsp_color) { dsp_color = COLORED; }
diff --git a/sonoff/xnrg_01_hlw8012.ino b/sonoff/xnrg_01_hlw8012.ino
index 440112c15..6ef196fb1 100644
--- a/sonoff/xnrg_01_hlw8012.ino
+++ b/sonoff/xnrg_01_hlw8012.ino
@@ -41,26 +41,26 @@
#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used
-static byte hlw_select_ui_flag;
-static byte hlw_ui_flag = 1;
-static byte hlw_load_off;
-static byte hlw_cf1_timer;
-static unsigned long hlw_cf_pulse_length;
-static unsigned long hlw_cf_pulse_last_time;
-static unsigned long hlw_cf1_pulse_length;
-static unsigned long hlw_cf1_pulse_last_time;
-static unsigned long hlw_cf1_summed_pulse_length;
-static unsigned long hlw_cf1_pulse_counter;
-static unsigned long hlw_cf1_voltage_pulse_length;
-static unsigned long hlw_cf1_current_pulse_length;
-static unsigned long hlw_energy_period_counter;
+byte hlw_select_ui_flag;
+byte hlw_ui_flag = 1;
+byte hlw_load_off;
+byte hlw_cf1_timer;
+unsigned long hlw_cf_pulse_length;
+unsigned long hlw_cf_pulse_last_time;
+unsigned long hlw_cf1_pulse_length;
+unsigned long hlw_cf1_pulse_last_time;
+unsigned long hlw_cf1_summed_pulse_length;
+unsigned long hlw_cf1_pulse_counter;
+unsigned long hlw_cf1_voltage_pulse_length;
+unsigned long hlw_cf1_current_pulse_length;
+unsigned long hlw_energy_period_counter;
-static unsigned long hlw_power_ratio = 0;
-static unsigned long hlw_voltage_ratio = 0;
-static unsigned long hlw_current_ratio = 0;
+unsigned long hlw_power_ratio = 0;
+unsigned long hlw_voltage_ratio = 0;
+unsigned long hlw_current_ratio = 0;
-static unsigned long hlw_cf1_voltage_max_pulse_counter;
-static unsigned long hlw_cf1_current_max_pulse_counter;
+unsigned long hlw_cf1_voltage_max_pulse_counter;
+unsigned long hlw_cf1_current_max_pulse_counter;
#ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception
void HlwCfInterrupt() ICACHE_RAM_ATTR;
@@ -217,6 +217,7 @@ void HlwDrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99)) { // Sonoff Pow or any HLW8012 based device
+ energy_calc_power_factor = 1; // Calculate power factor from data
energy_flg = XNRG_01;
}
}
diff --git a/sonoff/xnrg_02_cse7766.ino b/sonoff/xnrg_02_cse7766.ino
index 640da704e..84535cf96 100644
--- a/sonoff/xnrg_02_cse7766.ino
+++ b/sonoff/xnrg_02_cse7766.ino
@@ -185,6 +185,7 @@ void CseDrvInit()
if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2
baudrate = 4800;
serial_config = SERIAL_8E1;
+ energy_calc_power_factor = 1; // Calculate power factor from data
energy_flg = XNRG_02;
}
}
diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino
index d009feea4..03581862c 100644
--- a/sonoff/xnrg_03_pzem004t.ino
+++ b/sonoff/xnrg_03_pzem004t.ino
@@ -215,6 +215,7 @@ void PzemDrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T
+ energy_calc_power_factor = 1; // Calculate power factor from data
energy_flg = XNRG_03;
}
}
diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino
index 2b326f216..b7e1eab42 100644
--- a/sonoff/xnrg_05_pzem2.ino
+++ b/sonoff/xnrg_05_pzem2.ino
@@ -89,61 +89,29 @@ bool Pzem2ModbusReceiveReady()
return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame
}
-uint8_t Pzem2ModbusReceive()
+uint8_t Pzem2ModbusReceive(uint8_t *buffer, uint8_t register_count)
{
- uint8_t buffer[26];
-
-// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
-// FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014
-// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
-// FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017
-// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
+ // 0 1 2 3 4 5 6
+ // FE 04 02 08 98 HH LL
+ // Id Cc Sz Regis Crc--
uint8_t len = 0;
- while (Pzem2Serial->available() > 0) {
+ while ((Pzem2Serial->available() > 0) && (len < (register_count *2) + 5)) {
buffer[len++] = (uint8_t)Pzem2Serial->read();
if (3 == len) {
if (buffer[1] & 0x80) { // fe 84 02 f2 f1
return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error
}
}
- if (sizeof(buffer) == len) { break; }
}
AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len);
- if (len < 5) { return 8; } // 8 = Not enough data
- if (len != buffer[2] + 5) { return 9; } // 9 = Unexpected result
+ if (len < 7) { return 7; } // 7 = Not enough data
+ if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result
uint16_t crc = (buffer[len -2] << 8) | buffer[len -1];
- if (Pzem2ModbusCalculateCRC(buffer, len -3) == crc) {
- float energy = 0;
- if (0x10 == buffer[2]) { // PZEM-003,017
- pzem2_type = PZEM2_TYPES_003_017;
- energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V
- energy_current = (float)((buffer[5] << 8) + buffer[6]); // 65535.xx A
- energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]); // 65535 W
- energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 65535 Wh
- if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
- energy_kWhtoday += (energy - energy_start) * 100;
- energy_start = energy;
- EnergyUpdateToday();
- }
- else if (0x14 == buffer[2]) { // PZEM-014,016
- pzem2_type = PZEM2_TYPES_014_016;
- energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 65535.x V
- energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]); // 65535.xx A
- energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]); // 65535 W
- energy_frequency = (float)((buffer[13] << 8) + buffer[14]) / 10.0; // 50.0 Hz
- energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 65535 Wh
- if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
- energy_kWhtoday += (energy - energy_start) * 100;
- energy_start = energy;
- EnergyUpdateToday();
- }
- } else {
- AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Pzem2 crc error"));
- }
+ if (Pzem2ModbusCalculateCRC(buffer, len -3) != crc) { return 9; } // 9 = crc error
return 0; // 0 = No error
}
@@ -152,11 +120,56 @@ uint8_t Pzem2ModbusReceive()
uint8_t pzem2_sendRetry = 0;
-void Pzem2EverySecond()
+void Pzem2Every200ms()
{
bool data_ready = Pzem2ModbusReceiveReady();
- if (data_ready) { Pzem2ModbusReceive(); }
+ if (data_ready) {
+ uint8_t buffer[26];
+ uint8_t error = Pzem2ModbusReceive(buffer, pzem2_type);
+ if (error) {
+ snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error);
+ AddLog(LOG_LEVEL_DEBUG);
+// if (9 == error) {
+ if (PZEM2_TYPES_014_016 == pzem2_type) {
+ pzem2_type = PZEM2_TYPES_003_017;
+ } else {
+ pzem2_type = PZEM2_TYPES_014_016;
+ }
+// }
+ } else {
+ float energy = 0;
+
+ if (PZEM2_TYPES_003_017 == pzem2_type) {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ // FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017
+ // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
+ energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
+ energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
+ energy_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W
+ energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 4294967295 Wh
+ if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
+ energy_kWhtoday += (energy - energy_start) * 100;
+ energy_start = energy;
+ EnergyUpdateToday();
+ }
+ else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ // FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014
+ // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
+ energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
+ energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]) / 1000.0; // 4294967.000 A
+ energy_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W
+ energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
+ energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
+ energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 4294967295 Wh
+ if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
+ energy_kWhtoday += (energy - energy_start) * 100;
+ energy_start = energy;
+ EnergyUpdateToday();
+ }
+ }
+ }
if (0 == pzem2_sendRetry || data_ready) {
pzem2_sendRetry = 5;
@@ -198,13 +211,13 @@ int Xnrg05(byte function)
if (FUNC_PRE_INIT == function) {
Pzem2DrvInit();
}
- else if (XNRG_03 == energy_flg) {
+ else if (XNRG_05 == energy_flg) {
switch (function) {
case FUNC_INIT:
Pzem2SnsInit();
break;
- case FUNC_EVERY_SECOND:
- Pzem2EverySecond();
+ case FUNC_EVERY_200_MSECOND:
+ Pzem2Every200ms();
break;
}
}
diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino
index 93912bc76..f0b20ef59 100644
--- a/sonoff/xplg_wemohue.ino
+++ b/sonoff/xplg_wemohue.ino
@@ -17,6 +17,9 @@
along with this program. If not, see .
*/
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
/*********************************************************************************************\
* Belkin WeMo and Philips Hue bridge emulation
@@ -462,10 +465,10 @@ const char HUE_LIGHTS_STATUS_JSON[] PROGMEM =
"\"hue\":{h},"
"\"sat\":{s},"
"\"xy\":[0.5, 0.5],"
- "\"ct\":500,"
+ "\"ct\":{t},"
"\"alert\":\"none\","
"\"effect\":\"none\","
- "\"colormode\":\"hs\","
+ "\"colormode\":\"{m}\","
"\"reachable\":true}";
const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
",\"type\":\"Extended color light\","
@@ -559,20 +562,26 @@ void HueConfig(String *path)
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
}
+bool g_gotct = false;
+
void HueLightStatus1(byte device, String *response)
{
float hue = 0;
float sat = 0;
float bri = 0;
+ uint16_t ct = 500;
if (light_type) {
- LightGetHsb(&hue, &sat, &bri);
+ LightGetHsb(&hue, &sat, &bri, g_gotct);
+ ct = LightGetColorTemp();
}
*response += FPSTR(HUE_LIGHTS_STATUS_JSON);
response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false");
response->replace("{h}", String((uint16_t)(65535.0f * hue)));
response->replace("{s}", String((uint8_t)(254.0f * sat)));
response->replace("{b}", String((uint8_t)(254.0f * bri)));
+ response->replace("{t}", String(ct));
+ response->replace("{m}", g_gotct?"ct":"hs");
}
void HueLightStatus2(byte device, String *response)
@@ -678,11 +687,13 @@ void HueLights(String *path)
}
if (light_type) {
- LightGetHsb(&hue, &sat, &bri);
+ LightGetHsb(&hue, &sat, &bri, g_gotct);
}
- if (hue_json.containsKey("bri")) {
+ if (hue_json.containsKey("bri")) { // Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum). Note: a brightness of 1 is not off.
tmp = hue_json["bri"];
+ tmp = max(tmp, 1);
+ tmp = min(tmp, 254);
bri = (float)tmp / 254.0f;
if (resp) {
response += ",";
@@ -694,7 +705,7 @@ void HueLights(String *path)
resp = true;
change = true;
}
- if (hue_json.containsKey("hue")) {
+ if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue.
tmp = hue_json["hue"];
hue = (float)tmp / 65535.0f;
if (resp) {
@@ -704,11 +715,14 @@ void HueLights(String *path)
response.replace("{id", String(device));
response.replace("{cm", "hue");
response.replace("{re", String(tmp));
+ g_gotct = false;
resp = true;
change = true;
}
- if (hue_json.containsKey("sat")) {
+ if (hue_json.containsKey("sat")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
tmp = hue_json["sat"];
+ tmp = max(tmp, 0);
+ tmp = min(tmp, 254);
sat = (float)tmp / 254.0f;
if (resp) {
response += ",";
@@ -717,6 +731,8 @@ void HueLights(String *path)
response.replace("{id", String(device));
response.replace("{cm", "sat");
response.replace("{re", String(tmp));
+ g_gotct = false;
+ resp = true;
change = true;
}
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm)
@@ -728,11 +744,12 @@ void HueLights(String *path)
response.replace("{id", String(device));
response.replace("{cm", "ct");
response.replace("{re", String(ct));
+ g_gotct = true;
change = true;
}
if (change) {
if (light_type) {
- LightSetHsb(hue, sat, bri, ct);
+ LightSetHsb(hue, sat, bri, ct, g_gotct);
}
change = false;
}
diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino
index dc5f0ab66..815041cab 100644
--- a/sonoff/xsns_20_novasds.ino
+++ b/sonoff/xsns_20_novasds.ino
@@ -27,20 +27,59 @@
#include
+#ifndef WORKING_PERIOD
+ #define WORKING_PERIOD 5
+#endif
+
TasmotaSerial *NovaSdsSerial;
uint8_t novasds_type = 1;
uint8_t novasds_valid = 0;
+uint8_t novasds_workperiod[19] = {0xAA, 0xB4, 0x08, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x0C, 0xAB}; //5 minutes
+uint8_t novasds_setquerymode[19] = {0xAA, 0xB4, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query mode
+uint8_t novasds_querydata[19] = {0xAA, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0xAB}; //query DATA
+
+
struct sds011data {
uint16_t pm100;
uint16_t pm25;
} novasds_data;
+void NovaSdsSetWorkPeriod()
+{
+
+ while (NovaSdsSerial->available() > 0) {
+ NovaSdsSerial->read();
+ }
+
+ novasds_workperiod[4] = WORKING_PERIOD;
+ novasds_workperiod[17] = ((novasds_workperiod[2] + novasds_workperiod[3] + novasds_workperiod[4] + novasds_workperiod[15] + novasds_workperiod[16]) & 0xFF); //checksum
+
+ NovaSdsSerial->write(novasds_workperiod, sizeof(novasds_workperiod));
+ NovaSdsSerial->flush();
+
+ while (NovaSdsSerial->available() > 0) {
+ NovaSdsSerial->read();
+ }
+
+ NovaSdsSerial->write(novasds_setquerymode, sizeof(novasds_setquerymode));
+ NovaSdsSerial->flush();
+
+ while (NovaSdsSerial->available() > 0) {
+ NovaSdsSerial->read();
+ }
+}
+
+
+
bool NovaSdsReadData()
{
if (! NovaSdsSerial->available()) return false;
+ NovaSdsSerial->write(novasds_querydata, sizeof(novasds_querydata));
+ NovaSdsSerial->flush();
+
while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) {
NovaSdsSerial->read();
}
@@ -83,11 +122,14 @@ void NovaSdsSecond() // Every second
void NovaSdsInit()
{
novasds_type = 0;
- if (pin[GPIO_SDS0X1] < 99) {
- NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1], -1, 1);
+ if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) {
+ NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1);
if (NovaSdsSerial->begin(9600)) {
- if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); }
+ if (NovaSdsSerial->hardwareSerial()) {
+ ClaimSerial();
+ }
novasds_type = 1;
+ NovaSdsSetWorkPeriod();
}
}
}
@@ -154,4 +196,4 @@ boolean Xsns20(byte function)
return result;
}
-#endif // USE_NOVA_SDS
\ No newline at end of file
+#endif // USE_NOVA_SDS
diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino
index c22bc28cb..e5cc64418 100644
--- a/sonoff/xsns_23_sdm120.ino
+++ b/sonoff/xsns_23_sdm120.ino
@@ -246,7 +246,7 @@ void SDM120Show(boolean json)
dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power);
dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power);
dtostrfd(sdm120_power_factor, 2, power_factor);
- dtostrfd(sdm120_frequency, 2, frequency);
+ dtostrfd(sdm120_frequency, Settings.flag2.frequency_resolution, frequency);
dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total);
if (json) {
diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino
index d6683da44..058d6c25c 100644
--- a/sonoff/xsns_29_mcp230xx.ino
+++ b/sonoff/xsns_29_mcp230xx.ino
@@ -300,7 +300,7 @@ void MCP230xx_CheckForInterrupt(void) {
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
}
if (int_event) {
- char command[18];
+ char command[19]; // Theoretical max = 'event MCPINT_D16=1' so 18 + 1 (for the \n)
sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01));
ExecuteCommand(command, SRC_RULE);
}
diff --git a/tools/decode-status.py b/tools/decode-status.py
index b26be9df0..154b6e719 100644
--- a/tools/decode-status.py
+++ b/tools/decode-status.py
@@ -108,10 +108,10 @@ a_features = [[
"USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC",
"USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD",
"USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER",
- "USE_DISPLAY_SH1106","","","",
+ "USE_DISPLAY_SH1106","USE_MP3_PLAYER","","",
"","","","",
- "","","","",
- "","","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH",
+ "","","","NO_EXTRA_4K_HEAP",
+ "VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH",
"PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER"
],[
"","USE_ADC_VCC","USE_ENERGY_SENSOR","USE_PZEM004T",