Merge pull request #1 from arendst/development

Update from original
This commit is contained in:
Mike 2018-09-15 09:06:11 +02:00 committed by GitHub
commit bb5b5187be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 480 additions and 187 deletions

View File

@ -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) - [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) - [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/) - [Luani HVIO board](https://luani.de/projekte/esp8266-hvio/)
- Xiaomi-Phillips Bulbs
- Wemos D1 mini, NodeMcu and Ledunia - Wemos D1 mini, NodeMcu and Ledunia
### Contribute ### Contribute

View File

@ -61,6 +61,7 @@ build_unflags = -Wall
build_flags = build_flags =
-Wl,-Tesp8266.flash.1m0.ld -Wl,-Tesp8266.flash.1m0.ld
-mtarget-align
; -DUSE_CONFIG_OVERRIDE ; -DUSE_CONFIG_OVERRIDE
; lwIP 1.4 (Default) ; lwIP 1.4 (Default)
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH

View File

@ -1,7 +1,17 @@
/* 6.2.1.2 20180906 /* 6.2.1.3 20180907
* Fix KNX PA exception. Regression from 6.2.1 buffer overflow (#3700, #3710) * 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 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 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 * 6.2.1.1 20180905
* Rewrite energy monitoring using energy sensor driver modules * Rewrite energy monitoring using energy sensor driver modules

View File

@ -181,6 +181,7 @@
#define D_CMND_PRESSURE_RESOLUTION "PressRes" #define D_CMND_PRESSURE_RESOLUTION "PressRes"
#define D_CMND_POWER_RESOLUTION "WattRes" #define D_CMND_POWER_RESOLUTION "WattRes"
#define D_CMND_VOLTAGE_RESOLUTION "VoltRes" #define D_CMND_VOLTAGE_RESOLUTION "VoltRes"
#define D_CMND_FREQUENCY_RESOLUTION "FreqRes"
#define D_CMND_CURRENT_RESOLUTION "AmpRes" #define D_CMND_CURRENT_RESOLUTION "AmpRes"
#define D_CMND_ENERGY_RESOLUTION "EnergyRes" #define D_CMND_ENERGY_RESOLUTION "EnergyRes"
#define D_CMND_MODULE "Module" #define D_CMND_MODULE "Module"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Подсветка" #define D_SENSOR_BACKLIGHT "Подсветка"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "RétroÉcl" #define D_SENSOR_BACKLIGHT "RétroÉcl"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Háttérvil" #define D_SENSOR_BACKLIGHT "Háttérvil"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Luz de fundo" #define D_SENSOR_BACKLIGHT "Luz de fundo"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "Luz negra" #define D_SENSOR_BACKLIGHT "Luz negra"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -476,6 +476,8 @@
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1 "SDS0X1" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -476,6 +476,8 @@
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1 "SDS0X1" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -475,7 +475,8 @@
#define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight" #define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003" #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_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx" #define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri" #define D_SENSOR_SR04_TRIG "SR04 Tri"

View File

@ -112,8 +112,7 @@ typedef union {
uint32_t spare08 : 1; uint32_t spare08 : 1;
uint32_t spare09 : 1; uint32_t spare09 : 1;
uint32_t spare10 : 1; uint32_t spare10 : 1;
uint32_t spare11 : 1; uint32_t frequency_resolution : 2;
uint32_t spare12 : 1;
uint32_t axis_resolution : 2; uint32_t axis_resolution : 2;
uint32_t current_resolution : 2; uint32_t current_resolution : 2;
uint32_t voltage_resolution : 2; uint32_t voltage_resolution : 2;

View File

@ -77,8 +77,8 @@
enum TasmotaCommands { enum TasmotaCommands {
CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_FANSPEED, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME, 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_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_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_FREQUENCY_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION,
CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE, 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_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_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME,
CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE,
@ -87,8 +87,8 @@ enum TasmotaCommands {
const char kTasmotaCommands[] PROGMEM = 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_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_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_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|"
D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|" 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_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_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_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 ota_result = 0; // OTA result
int restart_flag = 0; // Sonoff restart flag int restart_flag = 0; // Sonoff restart flag
int wifi_state_flag = WIFI_RESTART; // Wifi state 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 int blinks = 201; // Number of LED blinks
uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year uint32_t uptime = 0; // Counting every second until 4294967295 = 130 year
uint32_t global_update = 0; // Timestamp of last global temperature and humidity update 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); 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) { else if (CMND_CURRENT_RESOLUTION == command_code) {
if ((payload >= 0) && (payload <= 3)) { if ((payload >= 0) && (payload <= 3)) {
Settings.flag2.current_resolution = payload; 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)) { else if ((CMND_GPIO == command_code) && (index < MAX_GPIO_PIN)) {
mytmplt cmodule; mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(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)) { if ((GPIO_USER == ValidGPIO(index, cmodule.gp.io[index])) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
for (byte i = 0; i < MAX_GPIO_PIN; i++) { 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)) { if ((GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) && (Settings.my_gp.io[i] == payload)) {
Settings.my_gp.io[i] = 0; 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("{")); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
for (byte i = 0; i < MAX_GPIO_PIN; i++) { 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 (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
jsflg = 1; jsflg = 1;
@ -1001,7 +1004,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
else if (CMND_SYSLOG == command_code) { else if (CMND_SYSLOG == command_code) {
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
Settings.syslog_level = payload; Settings.syslog_level = payload;
syslog_level = (Settings.flag2.emulation) ? 0 : payload; syslog_level = payload;
syslog_timer = 0; syslog_timer = 0;
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); 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 if (syslog_timer) { // Restore syslog level
syslog_timer--; syslog_timer--;
if (!syslog_timer) { if (!syslog_timer) {
syslog_level = (Settings.flag2.emulation) ? 0 : Settings.syslog_level; syslog_level = Settings.syslog_level;
if (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) 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 #ifndef USE_EMULATION
Settings.flag2.emulation = 0; Settings.flag2.emulation = 0;
#endif // USE_EMULATION #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; stop_flash_rotate = Settings.flag.stop_flash_rotate;
save_data_counter = Settings.save_data; save_data_counter = Settings.save_data;
sleep = Settings.sleep; sleep = Settings.sleep;

View File

@ -62,7 +62,10 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#ifdef USE_SENSORS #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 // 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_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) #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram)

View File

@ -21,6 +21,8 @@
#define _SONOFF_TEMPLATE_H_ #define _SONOFF_TEMPLATE_H_
// User selectable GPIO functionality // 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 { enum UserSelectablePins {
GPIO_NONE, // Not used GPIO_NONE, // Not used
GPIO_DHT11, // DHT11 GPIO_DHT11, // DHT11
@ -92,7 +94,7 @@ enum UserSelectablePins {
GPIO_SPI_DC, // SPI Data Direction GPIO_SPI_DC, // SPI Data Direction
GPIO_BACKLIGHT, // Display backlight control GPIO_BACKLIGHT, // Display backlight control
GPIO_PMS5003, // Plantower PMS5003 Serial interface 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_TX, // Serial Bridge Serial interface
GPIO_SBR_RX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface
GPIO_SR04_TRIG, // SR04 Trigger pin GPIO_SR04_TRIG, // SR04 Trigger pin
@ -123,6 +125,7 @@ enum UserSelectablePins {
GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM2_RX, // 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_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_SENSOR_END }; GPIO_SENSOR_END };
// Programmer selectable GPIO functionality offset by user selectable GPIOs // 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_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|" D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|" 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_SBR_TX "|" D_SENSOR_SBR_RX "|"
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|" D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|" 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_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_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|"
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" 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, BLITZWOLF_BWSHP2,
SHELLY1, SHELLY1,
SHELLY2, SHELLY2,
PHILIPS,
MAXMODULE }; MAXMODULE };
/********************************************************************************************/ /********************************************************************************************/
@ -244,7 +248,112 @@ typedef struct MYTMPLT {
myio gp; myio gp;
} mytmplt; } 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_BASIC,
SONOFF_RF, SONOFF_RF,
SONOFF_TH, SONOFF_TH,
@ -291,7 +400,8 @@ const uint8_t kNiceList[MAXMODULE] PROGMEM = {
KMC_70011, KMC_70011,
AILIGHT, AILIGHT,
WEMOS, WEMOS,
WITTY WITTY,
PHILIPS
}; };
// Default module settings // Default module settings
@ -936,6 +1046,14 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_SWT2_NP, // GPIO14 GPIO_SWT2_NP, // GPIO14
0, // GPIO15 MCP39F501 Reset 0, // GPIO15 MCP39F501 Reset
0, 0 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
} }
}; };

View File

@ -20,7 +20,7 @@
#ifndef _SONOFF_VERSION_H_ #ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_
#define VERSION 0x06020102 #define VERSION 0x06020103
#define D_PROGRAMNAME "Sonoff-Tasmota" #define D_PROGRAMNAME "Sonoff-Tasmota"
#define D_AUTHOR "Theo Arends" #define D_AUTHOR "Theo Arends"

View File

@ -628,7 +628,8 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
if (GPIO_PMS5003 == val) { return true; } if (GPIO_PMS5003 == val) { return true; }
#endif #endif
#ifndef USE_NOVA_SDS #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 #endif
#ifndef USE_SERIAL_BRIDGE #ifndef USE_SERIAL_BRIDGE
if (GPIO_SBR_TX == val) { return true; } if (GPIO_SBR_TX == val) { return true; }
@ -935,8 +936,20 @@ void GetFeatures()
#ifdef USE_DISPLAY_SH1106 #ifdef USE_DISPLAY_SH1106
feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino feature_drv2 |= 0x00001000; // xdsp_06_sh1106.ino
#endif #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 #ifdef VTABLES_IN_FLASH
feature_drv2 |= 0x04000000; // platformio.ini feature_drv2 |= 0x04000000; // platformio.ini
#endif #endif

View File

@ -268,9 +268,6 @@
// -- Internal Analog input ----------------------- // -- Internal Analog input -----------------------
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices #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 ---------------------------- // -- One wire sensors ----------------------------
// WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple 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) #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 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_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 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_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
//#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 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 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 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 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 ----------------------- // Power monitoring sensors -----------------------
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)

View File

@ -380,9 +380,7 @@ void MqttConnected()
MqttPublishPowerState(i); MqttPublishPowerState(i);
if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay
} }
if (Settings.tele_period) { if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds
tele_period = Settings.tele_period -9;
}
rules_flag.system_boot = 1; rules_flag.system_boot = 1;
XdrvCall(FUNC_MQTT_INIT); XdrvCall(FUNC_MQTT_INIT);
} }
@ -718,7 +716,6 @@ bool MqttCommand()
} }
else if (CMND_BUTTONRETAIN == command_code) { else if (CMND_BUTTONRETAIN == command_code) {
if ((payload >= 0) && (payload <= 1)) { if ((payload >= 0) && (payload <= 1)) {
strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic));
if (!payload) { if (!payload) {
for(i = 1; i <= MAX_KEYS; i++) { for(i = 1; i <= MAX_KEYS; i++) {
SendKey(0, i, 9); // Clear MQTT retain in broker SendKey(0, i, 9); // Clear MQTT retain in broker
@ -730,7 +727,6 @@ bool MqttCommand()
} }
else if (CMND_SWITCHRETAIN == command_code) { else if (CMND_SWITCHRETAIN == command_code) {
if ((payload >= 0) && (payload <= 1)) { if ((payload >= 0) && (payload <= 1)) {
strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic));
if (!payload) { if (!payload) {
for(i = 1; i <= MAX_SWITCHES; i++) { for(i = 1; i <= MAX_SWITCHES; i++) {
SendKey(1, i, 9); // Clear MQTT retain in broker SendKey(1, i, 9); // Clear MQTT retain in broker

View File

@ -768,7 +768,7 @@ void HandleModuleConfiguration()
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE)); page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE));
page += FPSTR(HTTP_SCRIPT_MODULE1); page += FPSTR(HTTP_SCRIPT_MODULE1);
for (byte i = 0; i < MAXMODULE; i++) { 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(stemp, sizeof(stemp), kModules[midx].name);
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp); snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
page += mqtt_data; page += mqtt_data;
@ -779,10 +779,10 @@ void HandleModuleConfiguration()
mytmplt cmodule; mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule)); memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
for (byte j = 0; j < GPIO_SENSOR_END; j++) { for (byte j = 0; j < GPIO_SENSOR_END; j++) {
if (!GetUsedInModule(j, cmodule.gp.io)) { midx = pgm_read_byte(kGpioNiceList + j);
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SCRIPT_MODULE2, j, j, GetTextIndexed(stemp, sizeof(stemp), j, kSensorNames)); 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; page += mqtt_data;
} }
} }
@ -805,7 +805,7 @@ void HandleModuleConfiguration()
for (byte i = 0; i < MAX_GPIO_PIN; i++) { for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) {
snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(stemp, 3, PINS_WEMOS +i*2);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:146px'><select id='g%d' name='g%d'></select></td></tr>"), snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:160px'><select id='g%d' name='g%d'></select></td></tr>"),
(WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "<font color='red'>ESP8285</font>" :(10==i)? "<font color='red'>ESP8285</font>" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "<font color='red'>ESP8285</font>" :(10==i)? "<font color='red'>ESP8285</font>" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
page += mqtt_data; page += mqtt_data;
} }
@ -1193,7 +1193,7 @@ void HandleSaveSettings()
if (Settings.last_module != new_module) { if (Settings.last_module != new_module) {
Settings.my_gp.io[i] = 0; Settings.my_gp.io[i] = 0;
} else { } 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); snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i);
WebGetArg(stemp, tmp, sizeof(tmp)); WebGetArg(stemp, tmp, sizeof(tmp));
Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp);

View File

@ -44,11 +44,13 @@ const char kEnergyCommands[] PROGMEM =
float energy_voltage = 0; // 123.1 V float energy_voltage = 0; // 123.1 V
float energy_current = 0; // 123.123 A float energy_current = 0; // 123.123 A
float energy_power = 0; // 123.1 W float energy_power = 0; // 123.1 W
float energy_frequency = 0; // 123.1 Hz float energy_power_factor = NAN; // 0.12
float energy_power_factor = 0; // 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_daily = 0; // 123.123 kWh
float energy_total = 0; // 12345.12345 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_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_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 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); XnrgCall(FUNC_EVERY_200_MSECOND);
float power_factor = 0; if (energy_calc_power_factor) {
if (energy_voltage && energy_current && energy_power) { float power_factor = 0;
power_factor = energy_power / (energy_voltage * energy_current); if (energy_voltage && energy_current && energy_power) {
if (power_factor > 1) power_factor = 1; 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() 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}} // {"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()); 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); EnergyShow(1);
tele_period = tele_period_save;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
energy_power_delta = 0; energy_power_delta = 0;
@ -537,11 +544,18 @@ void EnergySnsInit()
} }
#ifdef USE_WEBSERVER #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_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"
"{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" "{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"
"{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}" "{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}";
"{s}" D_POWER_FACTOR "{m}%s{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_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
"{s}" D_ENERGY_YESTERDAY "{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} = <tr><th>, {m} = </th><td>, {e} = </td></tr> "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
@ -555,31 +569,43 @@ void EnergyShow(boolean json)
char energy_power_chr[10]; char energy_power_chr[10];
char energy_voltage_chr[10]; char energy_voltage_chr[10];
char energy_current_chr[10]; char energy_current_chr[10];
char energy_frequency_chr[10];
char energy_power_factor_chr[10]; char energy_power_factor_chr[10];
char energy_yesterday_chr[10]; char energy_yesterday_chr[10];
char speriod[20]; char speriod[20];
char spfactor[20];
char sfrequency[20];
bool show_energy_period = (0 == tele_period); 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; float energy = 0;
if (show_energy_period) { if (show_energy_period) {
if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100; if (energy_period) energy = (float)(energy_kWhtoday - energy_period) / 100;
energy_period = energy_kWhtoday; 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) { 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,\""
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}"), 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, energy_power_factor_chr, energy_voltage_chr, energy_current_chr); 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 #ifdef USE_DOMOTICZ
if (show_energy_period) { // Only send if telemetry if (show_energy_period) { // Only send if telemetry
dtostrfd(energy_total * 1000, 1, energy_total_chr); 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_VOLTAGE, energy_voltage);
KnxSensor(KNX_ENERGY_CURRENT, energy_current); KnxSensor(KNX_ENERGY_CURRENT, energy_current);
KnxSensor(KNX_ENERGY_POWER, energy_power); 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_DAILY, energy_daily);
KnxSensor(KNX_ENERGY_TOTAL, energy_total); KnxSensor(KNX_ENERGY_TOTAL, energy_total);
KnxSensor(KNX_ENERGY_START, energy_start); KnxSensor(KNX_ENERGY_START, energy_start);
@ -601,7 +627,10 @@ void EnergyShow(boolean json)
#endif // USE_KNX #endif // USE_KNX
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } 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 #endif // USE_WEBSERVER
} }
} }

View File

@ -427,6 +427,11 @@ void LightSetColorTemp(uint16_t ct)
} }
uint16_t icold = (100 * (347 - my_ct)) / 136; uint16_t icold = (100 * (347 - my_ct)) / 136;
uint16_t iwarm = (100 * 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) { if (LST_RGBWC == light_subtype) {
Settings.light_color[0] = 0; Settings.light_color[0] = 0;
Settings.light_color[1] = 0; Settings.light_color[1] = 0;
@ -458,6 +463,15 @@ void LightSetDimmer(uint8_t myDimmer)
{ {
float temp; 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) { if (LT_PWM1 == light_type) {
Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color 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) { if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
// Add status for HSB // Add status for HSB
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false);
// Scale these percentages up to the numbers expected byt he client // Scale these percentages up to the numbers expected by the client
h = round(hsb[0] * 360); h = round(hsb[0] * 360);
s = round(hsb[1] * 100); s = round(hsb[1] * 100);
b = round(hsb[2] * 100); b = round(hsb[2] * 100);
@ -911,13 +925,15 @@ void LightHsbToRgb()
light_current_color[0] = (uint8_t)(r * 255.0f); light_current_color[0] = (uint8_t)(r * 255.0f);
light_current_color[1] = (uint8_t)(g * 255.0f); light_current_color[1] = (uint8_t)(g * 255.0f);
light_current_color[2] = (uint8_t)(b * 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(); LightRgbToHsb();
*hue = light_hue; *hue = light_hue;
*sat = light_saturation; *sat = light_saturation;
@ -925,16 +941,19 @@ void LightGetHsb(float *hue, float *sat, float *bri)
} else { } else {
*hue = 0; *hue = 0;
*sat = 0; *sat = 0;
// *bri = (2.54f * (float)Settings.light_dimmer);
*bri = (0.01f * (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 (light_subtype > LST_COLDWARM) {
if ((LST_RGBWC == light_subtype) && (ct > 0)) { if ((LST_RGBWC == light_subtype) && (gotct)) {
LightSetColorTemp(ct); uint8_t tmp = (uint8_t)(bri * 100);
Settings.light_dimmer = tmp;
if (ct > 0) {
LightSetColorTemp(ct);
}
} else { } else {
light_hue = hue; light_hue = hue;
light_saturation = sat; light_saturation = sat;
@ -1114,7 +1133,7 @@ boolean LightCommand()
} else { // Command with only 1 parameter, Hue (0<H<360), Saturation (0<S<100) OR Brightness (0<B<100) } else { // Command with only 1 parameter, Hue (0<H<360), Saturation (0<S<100) OR Brightness (0<B<100)
float hsb[3]; float hsb[3];
LightGetHsb(&hsb[0],&hsb[1],&hsb[2]); LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false);
HSB[0] = round(hsb[0] * 360); HSB[0] = round(hsb[0] * 360);
HSB[1] = round(hsb[1] * 100); HSB[1] = round(hsb[1] * 100);
HSB[2] = round(hsb[2] * 100); HSB[2] = round(hsb[2] * 100);
@ -1130,7 +1149,8 @@ boolean LightCommand()
LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0, LightSetHsb(( (HSB[0]>360) ? (HSB[0] % 360) : HSB[0] ) /360.0,
( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0, ( (HSB[1]>100) ? (HSB[1] % 100) : HSB[1] ) /100.0,
( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0, ( (HSB[2]>100) ? (HSB[2] % 100) : HSB[2] ) /100.0,
0); 0,
false);
} }
} else { } else {
LightState(0); LightState(0);

View File

@ -426,7 +426,7 @@ void RulesEvery100ms()
{ {
if (Settings.rule_enabled) { // Any rule enabled if (Settings.rule_enabled) { // Any rule enabled
mqtt_data[0] = '\0'; 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 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} XsnsNextCall(FUNC_JSON_APPEND); // ,"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}
tele_period = tele_period_save; tele_period = tele_period_save;

View File

@ -1,32 +1,39 @@
/* /*
xdrv_91_mp3.ino - MP3 Player support for Sonoff-Tasmota xdrv_14_mp3.ino - MP3 support for Sonoff-Tasmota
Player type: RB-DFR-562, DFPlayer Mini MP3 Player
Copyright (C) 2018 Theo Arends Copyright (C) 2018 gemu2015, mike2nl and Theo Arends
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef USE_MP3_PLAYER #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.h> #include <TasmotaSerial.h>
TasmotaSerial *MP3Player; TasmotaSerial *MP3Player;
#define D_CMND_MP3 "MP3" #define D_CMND_MP3 "MP3"
const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}";
const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}";
enum MP3_Commands { CMND_MP3_PLAY, CMND_MP3_STOP, CMND_MP3_VOLUME}; 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_PLAY 3
#define MP3_CMD_VOLUME 6 #define MP3_CMD_VOLUME 6
@ -43,11 +50,10 @@ uint16_t MP3_Checksum(uint8_t *array)
} }
// init player define serial tx port // init player define serial tx port
void InitMP3Player() { void MP3PlayerInit() {
MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3PLAYER]); MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]);
if (MP3Player->begin(9600)) { if (MP3Player->begin(9600)) {
//serial_bridge_active = 1;
MP3Player->flush(); MP3Player->flush();
} }
} }
@ -67,7 +73,7 @@ boolean MP3PlayerCmd() {
char command[CMDSZ]; char command[CMDSZ];
boolean serviced = true; boolean serviced = true;
uint8_t disp_len = strlen(D_CMND_MP3); uint8_t disp_len = strlen(D_CMND_MP3);
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { // Prefix 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); 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); MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100);
} }
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload);
} }
else if (CMND_MP3_STOP == command_code) { // stop else if (CMND_MP3_STOP == command_code) { // stop
MP3_CMD(MP3_CMD_STOP, 0); MP3_CMD(MP3_CMD_STOP, 0);
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload);
@ -97,15 +103,15 @@ boolean MP3PlayerCmd() {
* Interface * Interface
\*********************************************************************************************/ \*********************************************************************************************/
#define XDRV_91 #define XDRV_14
boolean Xdrv91(byte function) boolean Xdrv14(byte function)
{ {
boolean result = false; boolean result = false;
switch (function) { switch (function) {
case FUNC_PRE_INIT: case FUNC_PRE_INIT:
InitMP3Player(); MP3PlayerInit();
break; break;
case FUNC_COMMAND: case FUNC_COMMAND:
result = MP3PlayerCmd(); result = MP3PlayerCmd();
@ -114,4 +120,4 @@ boolean Xdrv91(byte function)
return result; return result;
} }
#endif // USE_MP3_PLAYER #endif // USE_MP3_PLAYER

View File

@ -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) #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 // All version before core 2.4.2
// https://github.com/esp8266/Arduino/issues/2557
extern "C" { extern "C" {
#include <cont.h> #include <cont.h>
@ -190,7 +191,6 @@ extern "C" {
void DebugFreeMem() void DebugFreeMem()
{ {
// https://github.com/esp8266/Arduino/issues/2557
register uint32_t *sp asm("a1"); register uint32_t *sp asm("a1");
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d, UnmodifiedStack %d (%s)"), // 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() void DebugFreeMem()
{ {
// https://github.com/esp8266/Arduino/issues/2557
register uint32_t *sp asm("a1"); register uint32_t *sp asm("a1");
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"),

View File

@ -188,7 +188,7 @@ boolean Xdsp05(byte function)
if (FUNC_DISPLAY_INIT_DRIVER == function) { if (FUNC_DISPLAY_INIT_DRIVER == function) {
EpdInitDriver(); EpdInitDriver();
} }
else if (XDSP_04 == Settings.display_model) { else if (XDSP_05 == Settings.display_model) {
if (!dsp_color) { dsp_color = COLORED; } if (!dsp_color) { dsp_color = COLORED; }

View File

@ -41,26 +41,26 @@
#define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used #define HLW_POWER_PROBE_TIME 10 // Number of seconds to probe for power before deciding none used
static byte hlw_select_ui_flag; byte hlw_select_ui_flag;
static byte hlw_ui_flag = 1; byte hlw_ui_flag = 1;
static byte hlw_load_off; byte hlw_load_off;
static byte hlw_cf1_timer; byte hlw_cf1_timer;
static unsigned long hlw_cf_pulse_length; unsigned long hlw_cf_pulse_length;
static unsigned long hlw_cf_pulse_last_time; unsigned long hlw_cf_pulse_last_time;
static unsigned long hlw_cf1_pulse_length; unsigned long hlw_cf1_pulse_length;
static unsigned long hlw_cf1_pulse_last_time; unsigned long hlw_cf1_pulse_last_time;
static unsigned long hlw_cf1_summed_pulse_length; unsigned long hlw_cf1_summed_pulse_length;
static unsigned long hlw_cf1_pulse_counter; unsigned long hlw_cf1_pulse_counter;
static unsigned long hlw_cf1_voltage_pulse_length; unsigned long hlw_cf1_voltage_pulse_length;
static unsigned long hlw_cf1_current_pulse_length; unsigned long hlw_cf1_current_pulse_length;
static unsigned long hlw_energy_period_counter; unsigned long hlw_energy_period_counter;
static unsigned long hlw_power_ratio = 0; unsigned long hlw_power_ratio = 0;
static unsigned long hlw_voltage_ratio = 0; unsigned long hlw_voltage_ratio = 0;
static unsigned long hlw_current_ratio = 0; unsigned long hlw_current_ratio = 0;
static unsigned long hlw_cf1_voltage_max_pulse_counter; unsigned long hlw_cf1_voltage_max_pulse_counter;
static unsigned long hlw_cf1_current_max_pulse_counter; unsigned long hlw_cf1_current_max_pulse_counter;
#ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception #ifndef USE_WS2812_DMA // Collides with Neopixelbus but solves exception
void HlwCfInterrupt() ICACHE_RAM_ATTR; void HlwCfInterrupt() ICACHE_RAM_ATTR;
@ -217,6 +217,7 @@ void HlwDrvInit()
{ {
if (!energy_flg) { 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 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; energy_flg = XNRG_01;
} }
} }

View File

@ -185,6 +185,7 @@ void CseDrvInit()
if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2 if ((SONOFF_S31 == Settings.module) || (SONOFF_POW_R2 == Settings.module)) { // Sonoff S31 or Sonoff Pow R2
baudrate = 4800; baudrate = 4800;
serial_config = SERIAL_8E1; serial_config = SERIAL_8E1;
energy_calc_power_factor = 1; // Calculate power factor from data
energy_flg = XNRG_02; energy_flg = XNRG_02;
} }
} }

View File

@ -215,6 +215,7 @@ void PzemDrvInit()
{ {
if (!energy_flg) { if (!energy_flg) {
if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T 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; energy_flg = XNRG_03;
} }
} }

View File

@ -89,61 +89,29 @@ bool Pzem2ModbusReceiveReady()
return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame 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
// FE 04 02 08 98 HH LL
// 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 // Id Cc Sz Regis Crc--
// 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--
uint8_t len = 0; uint8_t len = 0;
while (Pzem2Serial->available() > 0) { while ((Pzem2Serial->available() > 0) && (len < (register_count *2) + 5)) {
buffer[len++] = (uint8_t)Pzem2Serial->read(); buffer[len++] = (uint8_t)Pzem2Serial->read();
if (3 == len) { if (3 == len) {
if (buffer[1] & 0x80) { // fe 84 02 f2 f1 if (buffer[1] & 0x80) { // fe 84 02 f2 f1
return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error 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); AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len);
if (len < 5) { return 8; } // 8 = Not enough data if (len < 7) { return 7; } // 7 = Not enough data
if (len != buffer[2] + 5) { return 9; } // 9 = Unexpected result if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result
uint16_t crc = (buffer[len -2] << 8) | buffer[len -1]; uint16_t crc = (buffer[len -2] << 8) | buffer[len -1];
if (Pzem2ModbusCalculateCRC(buffer, len -3) == crc) { if (Pzem2ModbusCalculateCRC(buffer, len -3) != crc) { return 9; } // 9 = crc error
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"));
}
return 0; // 0 = No error return 0; // 0 = No error
} }
@ -152,11 +120,56 @@ uint8_t Pzem2ModbusReceive()
uint8_t pzem2_sendRetry = 0; uint8_t pzem2_sendRetry = 0;
void Pzem2EverySecond() void Pzem2Every200ms()
{ {
bool data_ready = Pzem2ModbusReceiveReady(); 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) { if (0 == pzem2_sendRetry || data_ready) {
pzem2_sendRetry = 5; pzem2_sendRetry = 5;
@ -198,13 +211,13 @@ int Xnrg05(byte function)
if (FUNC_PRE_INIT == function) { if (FUNC_PRE_INIT == function) {
Pzem2DrvInit(); Pzem2DrvInit();
} }
else if (XNRG_03 == energy_flg) { else if (XNRG_05 == energy_flg) {
switch (function) { switch (function) {
case FUNC_INIT: case FUNC_INIT:
Pzem2SnsInit(); Pzem2SnsInit();
break; break;
case FUNC_EVERY_SECOND: case FUNC_EVERY_200_MSECOND:
Pzem2EverySecond(); Pzem2Every200ms();
break; break;
} }
} }

View File

@ -17,6 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#if defined(USE_WEBSERVER) && defined(USE_EMULATION) #if defined(USE_WEBSERVER) && defined(USE_EMULATION)
/*********************************************************************************************\ /*********************************************************************************************\
* Belkin WeMo and Philips Hue bridge emulation * Belkin WeMo and Philips Hue bridge emulation
@ -462,10 +465,10 @@ const char HUE_LIGHTS_STATUS_JSON[] PROGMEM =
"\"hue\":{h}," "\"hue\":{h},"
"\"sat\":{s}," "\"sat\":{s},"
"\"xy\":[0.5, 0.5]," "\"xy\":[0.5, 0.5],"
"\"ct\":500," "\"ct\":{t},"
"\"alert\":\"none\"," "\"alert\":\"none\","
"\"effect\":\"none\"," "\"effect\":\"none\","
"\"colormode\":\"hs\"," "\"colormode\":\"{m}\","
"\"reachable\":true}"; "\"reachable\":true}";
const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
",\"type\":\"Extended color light\"," ",\"type\":\"Extended color light\","
@ -559,20 +562,26 @@ void HueConfig(String *path)
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response); WebServer->send(200, FPSTR(HDR_CTYPE_JSON), response);
} }
bool g_gotct = false;
void HueLightStatus1(byte device, String *response) void HueLightStatus1(byte device, String *response)
{ {
float hue = 0; float hue = 0;
float sat = 0; float sat = 0;
float bri = 0; float bri = 0;
uint16_t ct = 500;
if (light_type) { if (light_type) {
LightGetHsb(&hue, &sat, &bri); LightGetHsb(&hue, &sat, &bri, g_gotct);
ct = LightGetColorTemp();
} }
*response += FPSTR(HUE_LIGHTS_STATUS_JSON); *response += FPSTR(HUE_LIGHTS_STATUS_JSON);
response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false");
response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{h}", String((uint16_t)(65535.0f * hue)));
response->replace("{s}", String((uint8_t)(254.0f * sat))); response->replace("{s}", String((uint8_t)(254.0f * sat)));
response->replace("{b}", String((uint8_t)(254.0f * bri))); 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) void HueLightStatus2(byte device, String *response)
@ -678,11 +687,13 @@ void HueLights(String *path)
} }
if (light_type) { 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 = hue_json["bri"];
tmp = max(tmp, 1);
tmp = min(tmp, 254);
bri = (float)tmp / 254.0f; bri = (float)tmp / 254.0f;
if (resp) { if (resp) {
response += ","; response += ",";
@ -694,7 +705,7 @@ void HueLights(String *path)
resp = true; resp = true;
change = 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"]; tmp = hue_json["hue"];
hue = (float)tmp / 65535.0f; hue = (float)tmp / 65535.0f;
if (resp) { if (resp) {
@ -704,11 +715,14 @@ void HueLights(String *path)
response.replace("{id", String(device)); response.replace("{id", String(device));
response.replace("{cm", "hue"); response.replace("{cm", "hue");
response.replace("{re", String(tmp)); response.replace("{re", String(tmp));
g_gotct = false;
resp = true; resp = true;
change = 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 = hue_json["sat"];
tmp = max(tmp, 0);
tmp = min(tmp, 254);
sat = (float)tmp / 254.0f; sat = (float)tmp / 254.0f;
if (resp) { if (resp) {
response += ","; response += ",";
@ -717,6 +731,8 @@ void HueLights(String *path)
response.replace("{id", String(device)); response.replace("{id", String(device));
response.replace("{cm", "sat"); response.replace("{cm", "sat");
response.replace("{re", String(tmp)); response.replace("{re", String(tmp));
g_gotct = false;
resp = true;
change = true; change = true;
} }
if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) 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("{id", String(device));
response.replace("{cm", "ct"); response.replace("{cm", "ct");
response.replace("{re", String(ct)); response.replace("{re", String(ct));
g_gotct = true;
change = true; change = true;
} }
if (change) { if (change) {
if (light_type) { if (light_type) {
LightSetHsb(hue, sat, bri, ct); LightSetHsb(hue, sat, bri, ct, g_gotct);
} }
change = false; change = false;
} }

View File

@ -27,20 +27,59 @@
#include <TasmotaSerial.h> #include <TasmotaSerial.h>
#ifndef WORKING_PERIOD
#define WORKING_PERIOD 5
#endif
TasmotaSerial *NovaSdsSerial; TasmotaSerial *NovaSdsSerial;
uint8_t novasds_type = 1; uint8_t novasds_type = 1;
uint8_t novasds_valid = 0; 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 { struct sds011data {
uint16_t pm100; uint16_t pm100;
uint16_t pm25; uint16_t pm25;
} novasds_data; } 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() bool NovaSdsReadData()
{ {
if (! NovaSdsSerial->available()) return false; if (! NovaSdsSerial->available()) return false;
NovaSdsSerial->write(novasds_querydata, sizeof(novasds_querydata));
NovaSdsSerial->flush();
while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) { while ((NovaSdsSerial->peek() != 0xAA) && NovaSdsSerial->available()) {
NovaSdsSerial->read(); NovaSdsSerial->read();
} }
@ -83,11 +122,14 @@ void NovaSdsSecond() // Every second
void NovaSdsInit() void NovaSdsInit()
{ {
novasds_type = 0; novasds_type = 0;
if (pin[GPIO_SDS0X1] < 99) { if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) {
NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1], -1, 1); NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1);
if (NovaSdsSerial->begin(9600)) { if (NovaSdsSerial->begin(9600)) {
if (NovaSdsSerial->hardwareSerial()) { ClaimSerial(); } if (NovaSdsSerial->hardwareSerial()) {
ClaimSerial();
}
novasds_type = 1; novasds_type = 1;
NovaSdsSetWorkPeriod();
} }
} }
} }
@ -154,4 +196,4 @@ boolean Xsns20(byte function)
return result; return result;
} }
#endif // USE_NOVA_SDS #endif // USE_NOVA_SDS

View File

@ -246,7 +246,7 @@ void SDM120Show(boolean json)
dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power); dtostrfd(sdm120_apparent_power, Settings.flag2.wattage_resolution, apparent_power);
dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power); dtostrfd(sdm120_reactive_power, Settings.flag2.wattage_resolution, reactive_power);
dtostrfd(sdm120_power_factor, 2, power_factor); 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); dtostrfd(sdm120_energy_total, Settings.flag2.energy_resolution, energy_total);
if (json) { if (json) {

View File

@ -300,7 +300,7 @@ void MCP230xx_CheckForInterrupt(void) {
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
} }
if (int_event) { 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)); sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01));
ExecuteCommand(command, SRC_RULE); ExecuteCommand(command, SRC_RULE);
} }

View File

@ -108,10 +108,10 @@ a_features = [[
"USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC", "USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC",
"USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD", "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_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER",
"USE_DISPLAY_SH1106","","","", "USE_DISPLAY_SH1106","USE_MP3_PLAYER","","",
"","","","", "","","","",
"","","","", "","","","NO_EXTRA_4K_HEAP",
"","","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH", "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" "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", "","USE_ADC_VCC","USE_ENERGY_SENSOR","USE_PZEM004T",