Merge remote-tracking branch 'upstream/development' into development

This commit is contained in:
Gennaro Tortone 2018-01-25 10:50:15 +01:00
commit dd5ad2e6df
29 changed files with 539 additions and 432 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **5.11.1c** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
Current version is **5.11.1e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
### ATTENTION All versions

View File

@ -18,12 +18,13 @@ compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
build.lwip_lib=-llwip_gcc
build.lwip_include=lwip/include
build.lwip_flags=-DLWIP_OPEN_SRC
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/lwip/include" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections
@ -31,7 +32,8 @@ compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implici
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
# compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -u _printf_float -u _scanf_float -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -laxtls -lespnow -lsmartconfig -lairkiss -lmesh -lwpa2 -lstdc++ -lm -lc -lgcc

View File

@ -1,4 +1,22 @@
/* 5.11.1c
/* 5.11.1e
* Replaced command Ina219Mode with command Sensor13
* Add chunked webserver pages for large pages saving memory
* Fix Non-English JSON temperature unit attachement
* Add command Sensor15 2 to start MHZ19(B) Zero Point Calibration (#1643)
* Fix Sonoff Pow Energy Today and Energy Total reading after restart (#1648)
* Rewrite function pointers to save code space and memory (#1683)
* Add option define HOME_ASSISTANT_DISCOVERY_ENABLE in user_config.h (#1685)
* Fix SOnoff Pow Energy Period roll-over (#1688)
*
* 5.11.1d
* Add locale Decimal Separator to Web sensor page
* Add command State to retrieve device state information (same data as teleperiod state and status 11 in slightly different JSON format)
* Extent state information with Light parameters
* Fix IRSend parameter translation (#1636)
* Add optional login to Webserver AP mode (#1587, #1635)
* Fix BME680 teleperiod resistance measuring (#1647)
*
* 5.11.1c
* Make command color parameter input less strict to ease Hass support
* Add ColorTemperature to light status message
* Change PubSubClient.h define MQTT_MAX_PACKET_SIZE from 512 to 1000 for Hass support

View File

@ -118,6 +118,7 @@
#define D_JSON_WIFI "Wifi"
#define D_JSON_WRONG "Wrong"
#define D_JSON_YESTERDAY "Yesterday"
#define D_JSON_ZERO_POINT_CALIBRATION "Zero Point Calibration"
#define D_RSLT_ENERGY "ENERGY"
#define D_RSLT_INFO "INFO"
@ -166,11 +167,13 @@
#define D_STATUS9_MARGIN "PTH"
#define D_STATUS10_SENSOR "SNS"
#define D_STATUS11_STATUS "STS"
#define D_CMND_STATE "State"
#define D_CMND_POWER "Power"
#define D_CMND_POWERONSTATE "PowerOnState"
#define D_CMND_PULSETIME "PulseTime"
#define D_CMND_BLINKTIME "BlinkTime"
#define D_CMND_BLINKCOUNT "BlinkCount"
#define D_CMND_SENSOR "Sensor"
#define D_CMND_SAVEDATA "SaveData"
#define D_CMND_SETOPTION "SetOption"
#define D_CMND_TEMPERATURE_RESOLUTION "TempRes"
@ -236,7 +239,6 @@
#define D_CMND_LEDSTATE "LedState"
#define D_CMND_CFGDUMP "CfgDump"
#define D_CMND_I2CSCAN "I2CScan"
#define D_CMND_INA219MODE "Ina219Mode"
#define D_CMND_EXCEPTION "Exception"
// Commands xdrv_01_light.ino
@ -255,7 +257,18 @@
// Commands xdrv_02_irremote.ino
#define D_CMND_IRSEND "IRSend"
#define D_JSON_INVALID_JSON "Invalid JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol not supported"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_CMND_IRHVAC "IRHVAC"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// Commands xdrv_03_energy.ino
#define D_CMND_POWERLOW "PowerLow"
@ -384,6 +397,9 @@ const char S_JSON_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"%s%d\":%d}";
const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}";
const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}";
const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}";
const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}";
const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}";
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "."
#define D_MONTH_DAY_SEPARATOR "."
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "ungültiger JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protokoll nicht unterstützt"
#define D_JSON_IR_PROTOCOL "PROTOKOLL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATEN"
#define D_JSON_IRHVAC_VENDOR "HERSTELLER"
#define D_JSON_IRHVAC_POWER "STROM"
#define D_JSON_IRHVAC_MODE "MODUS"
#define D_JSON_IRHVAC_FANSPEED "LÜFTERGESCHWINDIGKEIT"
#define D_JSON_IRHVAC_TEMP "TEMPERATUR"
#define D_JSON_IRRECEIVED "IR empfangen"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "Invalid JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol not supported"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "JSON no válido"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocolo no soportado"
#define D_JSON_IR_PROTOCOL "PROTOCOLO"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 paquets response envoyés"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "JSON Invalide"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocole non supporté"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST argomenti"
#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "JSON non valido"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocollo non supportato"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST argumenten"
#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "Ongeldig JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protocol wordt niet ondersteund"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysylane"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "Invalid JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "Protokol nie jest obslugiwany"
#define D_JSON_IR_PROTOCOL "PROTOCOL"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "DATA"
#define D_JSON_IRHVAC_VENDOR "VENDOR"
#define D_JSON_IRHVAC_POWER "POWER"
#define D_JSON_IRHVAC_MODE "MODE"
#define D_JSON_IRHVAC_FANSPEED "FANSPEED"
#define D_JSON_IRHVAC_TEMP "TEMP"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -30,6 +30,8 @@
*
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
@ -335,19 +337,6 @@
#define D_HUE_POST_ARGS "Hue POST 参数"
#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送"
// xdrv_02_irremote.ino
#define D_JSON_INVALID_JSON "无效的JSON"
#define D_JSON_PROTOCOL_NOT_SUPPORTED "协议不支持"
#define D_JSON_IR_PROTOCOL "协议"
#define D_JSON_IR_BITS "BITS"
#define D_JSON_IR_DATA "数据"
#define D_JSON_IRHVAC_VENDOR "供应商"
#define D_JSON_IRHVAC_POWER "电源"
#define D_JSON_IRHVAC_MODE "模式"
#define D_JSON_IRHVAC_FANSPEED "风扇转速"
#define D_JSON_IRHVAC_TEMP "温度"
#define D_JSON_IRRECEIVED "IrReceived"
// xdrv_05_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz 设置"
#define D_DOMOTICZ_IDX "Idx"

View File

@ -430,6 +430,7 @@ void SettingsDefaultSet2()
Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN;
Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN;
Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN;
Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE;
Settings.flag2.emulation = EMULATION;

View File

@ -86,7 +86,7 @@ typedef unsigned long power_t; // Power (Relay) type
#define CMDSZ 24 // Max number of characters in command
#define TOPSZ 100 // Max number of characters in topic string
#define LOGSZ 400 // Max number of characters in log
#define MIN_MESSZ 893 // Min number of characters in MQTT message
#define MIN_MESSZ 893 // Min number of characters in MQTT message
#ifdef USE_MQTT_TLS
#define MAX_LOG_LINES 10 // Max number of lines in weblog
#else
@ -128,6 +128,10 @@ enum EmulationOptions {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESULT_OR_TELE };
enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, power_nu1, POWER_OFF_NO_STATE, POWER_ON_NO_STATE, power_nu2, POWER_SHOW_STATE };
enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON };
enum ButtonStates {PRESSED, NOT_PRESSED};
enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8};
@ -145,4 +149,10 @@ enum XsnsFunctions {FUNC_INIT, FUNC_EVERY_50_MSECOND, FUNC_EVERY_SECOND, FUNC_PR
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
/*********************************************************************************************\
* Extern global variables
\*********************************************************************************************/
extern uint8_t light_device; // Light device number
#endif // _SONOFF_H_

View File

@ -25,10 +25,10 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
#define VERSION 0x050B0103 // 5.11.1c
#define VERSION 0x050B0105 // 5.11.1e
// Location specific includes
#include "sonoff.h" // Enumaration used in user_config.h
#include "sonoff.h" // Enumeration used in user_config.h
#include "user_config.h" // Fixed user configurable options
#include "user_config_override.h" // Configuration overrides for user_config.h
#include "i18n.h" // Language support configured by user_config.h
@ -67,25 +67,25 @@
#include "settings.h"
enum TasmotaCommands {
CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_POWERONSTATE, CMND_PULSETIME,
CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION,
CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME,
CMND_BLINKTIME, CMND_BLINKCOUNT, CMND_SENSOR, CMND_SAVEDATA, CMND_SETOPTION, CMND_TEMPERATURE_RESOLUTION, CMND_HUMIDITY_RESOLUTION,
CMND_PRESSURE_RESOLUTION, CMND_POWER_RESOLUTION, CMND_VOLTAGE_RESOLUTION, CMND_CURRENT_RESOLUTION, CMND_ENERGY_RESOLUTION, CMND_MODULE, CMND_MODULES,
CMND_GPIO, CMND_GPIOS, CMND_PWM, CMND_PWMFREQUENCY, CMND_PWMRANGE, CMND_COUNTER, CMND_COUNTERTYPE,
CMND_COUNTERDEBOUNCE, CMND_SLEEP, CMND_UPGRADE, CMND_UPLOAD, CMND_OTAURL, CMND_SERIALLOG, CMND_SYSLOG,
CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME,
CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION,
CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE,
CMND_CFGDUMP, CMND_I2CSCAN, CMND_INA219MODE, CMND_EXCEPTION };
CMND_CFGDUMP, CMND_I2CSCAN, CMND_EXCEPTION };
const char kTasmotaCommands[] PROGMEM =
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|"
D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SENSOR "|" D_CMND_SAVEDATA "|" D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|"
D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|"
D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" D_CMND_COUNTER "|" D_CMND_COUNTERTYPE "|"
D_CMND_COUNTERDEBOUNCE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_SYSLOG "|"
D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|"
D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|"
D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|"
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN "|" D_CMND_INA219MODE
D_CMND_CFGDUMP "|" D_CMND_I2CSCAN
#ifdef DEBUG_THEO
"|" D_CMND_EXCEPTION
#endif
@ -186,21 +186,12 @@ uint8_t light_type = 0; // Light types
boolean mdns_begun = false;
uint8_t xdrv_present = 0; // Number of drivers found
boolean (*xdrv_func_ptr[XDRV_MAX])(byte); // Driver Function Pointers
uint8_t xsns_present = 0; // Number of External Sensors found
boolean (*xsns_func_ptr[XSNS_MAX])(byte); // External Sensor Function Pointers for simple implementation of sensors
char my_version[33]; // Composed version string
char my_hostname[33]; // Composed Wifi hostname
char mqtt_client[33]; // Composed MQTT Clientname
char serial_in_buffer[INPUT_BUFFER_SIZE + 2]; // Receive buffer
//char mqtt_data[MESSZ + TOPSZ]; // MQTT publish buffer (MESSZ) and web page ajax buffer (MESSZ + TOPSZ)
char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer
//char log_data[TOPSZ + MESSZ]; // Logging
char log_data[LOGSZ]; // Logging
String web_log[MAX_LOG_LINES]; // Web log buffer
String backlog[MAX_BACKLOG]; // Command backlog
@ -298,7 +289,7 @@ void SetDevicePower(power_t rpower)
{
uint8_t state;
if (4 == Settings.poweronstate) { // All on and stay on
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on
power = (1 << devices_present) -1;
rpower = power;
}
@ -317,7 +308,7 @@ void SetDevicePower(power_t rpower)
}
}
XdrvSetPower(bitRead(rpower, devices_present -1));
XdrvSetPower(rpower);
if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) {
Serial.write(0xA0);
@ -938,6 +929,10 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
fallback_topic_flag = 0;
return;
}
else if (CMND_STATE == command_code) {
mqtt_data[0] = '\0';
MqttShowState();
}
else if ((CMND_POWERONSTATE == command_code) && (Settings.module != MOTOR)) {
/* 0 = Keep relays off after power on
* 1 = Turn relays on after power on, if PulseTime set wait for PulseTime seconds, and turn relays off
@ -946,11 +941,11 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
* 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power)
* 5 = Keep relays off after power on, if PulseTime set wait for PulseTime seconds, and turn relays on
*/
if ((payload >= 0) && (payload <= 5)) {
if ((payload >= POWER_ALL_OFF) && (payload <= POWER_ALL_OFF_PULSETIME_ON)) {
Settings.poweronstate = payload;
if (4 == Settings.poweronstate) {
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
for (byte i = 1; i <= devices_present; i++) {
ExecuteCommandPower(i, 1);
ExecuteCommandPower(i, POWER_ON);
}
}
}
@ -992,6 +987,17 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data));
}
else if (CMND_SENSOR == command_code) {
XdrvMailbox.topic = command;
XdrvMailbox.index = index;
XdrvMailbox.payload = payload;
XdrvMailbox.data_len = data_len;
XdrvMailbox.data = dataBuf;
XsnsCall(FUNC_COMMAND);
// if (!XsnsCall(FUNC_COMMAND)) {
// type = NULL;
// }
}
else if ((CMND_SETOPTION == command_code) && ((index >= 0) && (index <= 19)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
if (index <= 31) {
ptype = 0; // SetOption0 .. 31
@ -1494,15 +1500,6 @@ void MqttDataCallback(char* topic, byte* data, unsigned int data_len)
I2cScan(mqtt_data, sizeof(mqtt_data));
}
#endif // USE_I2C
#ifdef USE_INA219
else if (CMND_INA219MODE == command_code) {
if ((payload >= 0) && (payload <= 2)) {
Settings.ina219_mode = payload;
restart_flag = 2;
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ina219_mode);
}
#endif // USE_INA219
else if (Settings.flag.mqtt_enabled && MqttCommand(grpflg, type, index, dataBuf, data_len, payload, payload16)) {
// Serviced
}
@ -1589,7 +1586,7 @@ void ExecuteCommandPower(byte device, byte state)
// state 9 = Show power state
uint8_t publish_power = 1;
if ((6 == state) || (7 == state)) {
if ((POWER_OFF_NO_STATE == state) || (POWER_ON_NO_STATE == state)) {
state &= 1;
publish_power = 0;
}
@ -1600,7 +1597,7 @@ void ExecuteCommandPower(byte device, byte state)
pulse_timer[(device -1)] = 0;
}
power_t mask = 1 << (device -1);
if (state <= 2) {
if (state <= POWER_TOGGLE) {
if ((blink_mask & mask)) {
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
MqttPublishPowerBlinkState(device);
@ -1610,19 +1607,19 @@ void ExecuteCommandPower(byte device, byte state)
for (byte i = 0; i < devices_present; i++) {
power_t imask = 1 << i;
if ((power & imask) && (mask != imask)) {
ExecuteCommandPower(i +1, 0);
ExecuteCommandPower(i +1, POWER_OFF);
}
}
interlock_mutex = 0;
}
switch (state) {
case 0: { // Off
case POWER_OFF: {
power &= (POWER_MASK ^ mask);
break; }
case 1: // On
case POWER_ON:
power |= mask;
break;
case 2: // Toggle
case POWER_TOGGLE:
power ^= mask;
}
SetDevicePower(power);
@ -1631,10 +1628,10 @@ void ExecuteCommandPower(byte device, byte state)
#endif // USE_DOMOTICZ
if (device <= MAX_PULSETIMERS) {
// pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0;
pulse_timer[(device -1)] = (((5 == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1)] : 0;
pulse_timer[(device -1)] = (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[(device -1)] : 0;
}
}
else if (3 == state) { // Blink
else if (POWER_BLINK == state) {
if (!(blink_mask & mask)) {
blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state
blink_power = (power >> (device -1))&1; // Prep to Toggle
@ -1645,7 +1642,7 @@ void ExecuteCommandPower(byte device, byte state)
MqttPublishPowerBlinkState(device);
return;
}
else if (4 == state) { // No Blink
else if (POWER_BLINK_STOP == state) {
byte flag = (blink_mask & mask);
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
MqttPublishPowerBlinkState(device);
@ -1796,9 +1793,15 @@ void MqttShowState()
dtostrfd((double)ESP.getVcc()/1000, 3, stemp1);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1);
#endif
for (byte i = 0; i < devices_present; i++) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1)), GetStateText(bitRead(power, i)));
if (i == light_device -1) {
LightState(1);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1)), GetStateText(bitRead(power, i)));
}
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_APMAC_ADDRESS "\":\"%s\"}}"),
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
}
@ -1815,7 +1818,7 @@ boolean MqttShowSensor()
}
XsnsCall(FUNC_JSON_APPEND);
boolean json_data_available = (strlen(mqtt_data) - json_data_start);
if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) {
if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit());
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
@ -1957,7 +1960,7 @@ void ButtonHandler()
}
if (button_pressed) {
if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(i +1, 2); // Execute Toggle command internally
ExecuteCommandPower(i +1, POWER_TOGGLE); // Execute Toggle command internally
}
}
} else {
@ -1966,7 +1969,7 @@ void ButtonHandler()
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON " %d " D_IMMEDIATE), i +1);
AddLog(LOG_LEVEL_DEBUG);
if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(i +1, 2); // Execute Toggle command internally
ExecuteCommandPower(i +1, POWER_TOGGLE); // Execute Toggle command internally
}
} else {
multipress[i] = (multiwindow[i]) ? multipress[i] +1 : 1;
@ -2021,7 +2024,7 @@ void ButtonHandler()
if (WifiState()) { // WPSconfig, Smartconfig or Wifimanager active
restart_flag = 1;
} else {
ExecuteCommandPower(i + multipress[i], 2); // Execute Toggle command internally
ExecuteCommandPower(i + multipress[i], POWER_TOGGLE); // Execute Toggle command internally
}
} else { // 3 - 7 press
if (!Settings.flag.button_restrict) {
@ -2109,7 +2112,7 @@ void SwitchHandler()
if (switchflag < 3) {
if (!send_button_power(1, i +1, switchflag)) { // Execute command via MQTT
ExecuteCommandPower(i +1, switchflag); // Execute command internally (if i < devices_present)
ExecuteCommandPower(i +1, switchflag); // Execute command internally (if i < devices_present)
}
}
@ -2160,8 +2163,8 @@ void StateLoop()
if ((pulse_timer[i] > 0) && (pulse_timer[i] < 112)) {
pulse_timer[i]--;
if (!pulse_timer[i]) {
// ExecuteCommandPower(i +1, 0);
ExecuteCommandPower(i +1, (5 == Settings.poweronstate) ? 1: 0);
// ExecuteCommandPower(i +1, POWER_OFF);
ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF);
}
}
}
@ -2640,7 +2643,7 @@ void GpioInit()
}
SetLedPower(Settings.ledstate &8);
XDrvInit();
XdrvCall(FUNC_INIT);
}
extern "C" {
@ -2700,29 +2703,29 @@ void setup()
GetMqttClient(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client));
if (MOTOR == Settings.module) {
Settings.poweronstate = 1; // Needs always on else in limbo!
Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo!
}
if (4 == Settings.poweronstate) { // Allways on
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
SetDevicePower(1);
} else {
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
switch (Settings.poweronstate) {
case 0: // All off
case 5: // All off but on after PulseTime
case POWER_ALL_OFF:
case POWER_ALL_OFF_PULSETIME_ON:
power = 0;
SetDevicePower(power);
break;
case 1: // All on
case POWER_ALL_ON: // All on
power = (1 << devices_present) -1;
SetDevicePower(power);
break;
case 2: // All saved state toggle
case POWER_ALL_SAVED_TOGGLE:
power = Settings.power & ((1 << devices_present) -1) ^ POWER_MASK;
if (Settings.flag.save_state) {
SetDevicePower(power);
}
break;
case 3: // All saved state
case POWER_ALL_SAVED:
power = Settings.power & ((1 << devices_present) -1);
if (Settings.flag.save_state) {
SetDevicePower(power);
@ -2742,8 +2745,7 @@ void setup()
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i));
}
// if ((i < MAX_PULSETIMERS) && bitRead(power, i)) {
if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (5 == Settings.poweronstate))) {
if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) {
pulse_timer[i] = Settings.pulse_timer[i];
}
}
@ -2759,7 +2761,7 @@ void setup()
#endif // BE_MINIMAL
RtcInit();
XSnsInit();
XsnsCall(FUNC_INIT);
}
void loop()

View File

@ -885,6 +885,20 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
0, 0, 0
}
{ "MagicHome v2.3", // Magic Home (aka Flux-light) (ESP8266) (#1353)
0, 0,
GPIO_LED1_INV, // GPIO02 Blue onboard LED
0,
GPIO_USER, // GPIO04 IR receiver (optional)
GPIO_PWM2, // GPIO05 RGB LED Green
0, 0, 0, 0, 0, 0, // Flash connection
GPIO_PWM1, // GPIO12 RGB LED Red
GPIO_PWM3, // GPIO13 RGB LED Blue
0,
GPIO_PWM4, // GPIO15 RGBW LED White
0, 0
},
*/
#endif // _SONOFF_TEMPLATE_H_

View File

@ -148,83 +148,9 @@ Decoding 14 results
* General
\*********************************************************************************************/
char* _dtostrf(double number, unsigned char prec, char *s, bool i18n)
char* dtostrfd(double number, unsigned char prec, char *s)
{
bool negative = false;
if (isnan(number)) {
strcpy_P(s, PSTR("nan"));
return s;
}
if (isinf(number)) {
strcpy_P(s, PSTR("inf"));
return s;
}
char decimal = '.';
if (i18n) {
decimal = D_DECIMAL_SEPARATOR[0];
}
char* out = s;
// Handle negative numbers
if (number < 0.0) {
negative = true;
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
// I optimized out most of the divisions
double rounding = 2.0;
for (uint8_t i = 0; i < prec; ++i) {
rounding *= 10.0;
}
rounding = 1.0 / rounding;
number += rounding;
// Figure out how big our number really is
double tenpow = 1.0;
int digitcount = 1;
while (number >= 10.0 * tenpow) {
tenpow *= 10.0;
digitcount++;
}
number /= tenpow;
// Handle negative sign
if (negative) {
*out++ = '-';
}
// Print the digits, and if necessary, the decimal point
digitcount += prec;
int8_t digit = 0;
while (digitcount-- > 0) {
digit = (int8_t)number;
if (digit > 9) {
digit = 9; // insurance
}
*out++ = (char)('0' | digit);
if ((digitcount == prec) && (prec > 0)) {
*out++ = decimal;
}
number -= digit;
number *= 10.0;
}
// make sure the string is terminated
*out = 0;
return s;
}
char* dtostrfd(double number, unsigned char prec, char *s) // Always decimal dot
{
return _dtostrf(number, prec, s, 0);
}
char* dtostrfi(double number, unsigned char prec, char *s) // Use localized decimal dot
{
return _dtostrf(number, prec, s, 1);
return dtostrf(number, 1, prec, s);
}
boolean ParseIp(uint32_t* addr, const char* str)

View File

@ -120,8 +120,9 @@
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional)
// -- MQTT - Home Assistant Discovery -------------
#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery (+1k4 code)
#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+1k4 code)
#define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix
#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 // [SetOption19] Home Assistant Discovery (0 = Disable, 1 = Enable)
// -- HTTP ----------------------------------------
#define USE_WEBSERVER // Enable web server and wifi manager (+66k code, +8k mem) - Disable by //

View File

@ -73,7 +73,9 @@ const char HTTP_HEAD[] PROGMEM =
"}"
"function lc(p){"
"la('?t='+p);"
"}"
"}";
const char HTTP_HEAD_STYLE[] PROGMEM =
"</script>"
"<style>"
@ -96,7 +98,11 @@ const char HTTP_HEAD[] PROGMEM =
#ifdef BE_MINIMAL
"<div style='text-align:center;color:red;'><h3>" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "</h3></div>"
#endif
#ifdef LANGUAGE_MODULE_NAME
"<div style='text-align:center;'><h3>" D_MODULE " {ha</h3><h2>{h}</h2></div>";
#else
"<div style='text-align:center;'><h3>{ha " D_MODULE "</h3><h2>{h}</h2></div>";
#endif
const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"var sn=0;" // Scroll position
"var id=99;" // Get most of weblog initially
@ -190,6 +196,12 @@ const char HTTP_BTN_MENU4[] PROGMEM =
"<br/><form action='rs' method='get'><button>" D_RESTORE_CONFIGURATION "</button></form>";
const char HTTP_BTN_MAIN[] PROGMEM =
"<br/><br/><form action='.' method='get'><button>" D_MAIN_MENU "</button></form>";
const char HTTP_FORM_LOGIN[] PROGMEM =
"<form method='post' action='/'>"
"<br/><b>" D_USER "</b><br/><input name='USER1' placeholder='" D_USER "'><br/>"
"<br/><b>" D_PASSWORD "</b><br/><input name='PASS1' type='password' placeholder='" D_PASSWORD "'><br/>"
"<br/>"
"<br/><button>" D_OK "</button></form>";
const char HTTP_BTN_CONF[] PROGMEM =
"<br/><br/><form action='cn' method='get'><button>" D_CONFIGURATION "</button></form>";
const char HTTP_FORM_MODULE[] PROGMEM =
@ -204,9 +216,9 @@ const char HTTP_FORM_WIFI[] PROGMEM =
"<fieldset><legend><b>&nbsp;" D_WIFI_PARAMETERS "&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='1' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>" D_AP1_SSID "</b> (" STA_SSID1 ")<br/><input id='s1' name='s1' placeholder='" STA_SSID1 "' value='{s1'><br/>"
"<br/><b>" D_AP1_PASSWORD "</b><br/><input id='p1' name='p1' type='password' placeholder='" STA_PASS1 "' value='{p1'><br/>"
"<br/><b>" D_AP1_PASSWORD "</b><br/><input id='p1' name='p1' type='password' placeholder='" D_AP1_PASSWORD "' value='********'><br/>"
"<br/><b>" D_AP2_SSID "</b> (" STA_SSID2 ")<br/><input id='s2' name='s2' placeholder='" STA_SSID2 "' value='{s2'><br/>"
"<br/><b>" D_AP2_PASSWORD "</b><br/><input id='p2' name='p2' type='password' placeholder='" STA_PASS2 "' value='{p2'><br/>"
"<br/><b>" D_AP2_PASSWORD "</b><br/><input id='p2' name='p2' type='password' placeholder='" D_AP2_PASSWORD "' value='********'><br/>"
"<br/><b>" D_HOSTNAME "</b> (" WIFI_HOSTNAME ")<br/><input id='h' name='h' placeholder='" WIFI_HOSTNAME" ' value='{h1'><br/>";
const char HTTP_FORM_MQTT[] PROGMEM =
"<fieldset><legend><b>&nbsp;" D_MQTT_PARAMETERS "&nbsp;</b></legend><form method='get' action='sv'>"
@ -236,7 +248,7 @@ const char HTTP_FORM_LOG3[] PROGMEM =
const char HTTP_FORM_OTHER[] PROGMEM =
"<fieldset><legend><b>&nbsp;" D_OTHER_PARAMETERS "&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='5' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>" D_WEB_ADMIN_PASSWORD "</b><br/><input id='p1' name='p1' type='password' placeholder='" WEB_PASSWORD "' value='{p1'><br/>"
"<br/><b>" D_WEB_ADMIN_PASSWORD "</b><br/><input id='p1' name='p1' type='password' placeholder='" D_WEB_ADMIN_PASSWORD "' value='********'><br/>"
"<br/><input style='width:10%;' id='b1' name='b1' type='checkbox'{r1><b>" D_MQTT_ENABLE "</b><br/>";
const char HTTP_FORM_OTHER2[] PROGMEM =
"<br/><b>" D_FRIENDLY_NAME " {1</b> ({2)<br/><input id='a{1' name='a{1' placeholder='{2' value='{3'><br/>";
@ -244,8 +256,8 @@ const char HTTP_FORM_OTHER[] PROGMEM =
const char HTTP_FORM_OTHER3a[] PROGMEM =
"<br/><fieldset><legend><b>&nbsp;" D_EMULATION "&nbsp;</b></legend>";
const char HTTP_FORM_OTHER3b[] PROGMEM =
"<br/><input style='width:10%;' id='b2' name='b2' type='radio' value='{1'{2><b>{3</b>{4";
#endif // USE_EMULATION
"<br/><input style='width:10%;' id='r{1' name='b2' type='radio' value='{1'{2><b>{3</b>{4"; // Different id only used for labels
#endif // USE_EMULATION
const char HTTP_FORM_END[] PROGMEM =
"<br/><button type='submit'>" D_SAVE "</button></form></fieldset>";
const char HTTP_FORM_RST[] PROGMEM =
@ -412,11 +424,14 @@ void SetHeader()
#endif
}
void ShowPage(String &page)
/*********************************************************************************************/
void ShowPage(String &page, bool auth)
{
if((HTTP_ADMIN == webserver_state) && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
return WebServer->requestAuthentication();
}
page.replace(F("{ha"), my_module.name);
page.replace(F("{h}"), Settings.friendlyname[0]);
if (HTTP_MANAGER == webserver_state) {
@ -431,9 +446,75 @@ void ShowPage(String &page)
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
}
void ShowPage(String &page)
{
ShowPage(page, true);
}
/*********************************************************************************************/
void ShowPageStartChunk()
{
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), "");
}
void ShowPageChunk(String &page)
{
page.replace(F("{ha"), my_module.name);
page.replace(F("{h}"), Settings.friendlyname[0]);
if (HTTP_MANAGER == webserver_state) {
if (WifiConfigCounter()) {
page.replace(F("<body>"), F("<body onload='u()'>"));
page += FPSTR(HTTP_COUNTER);
}
}
WebServer->sendContent(page);
}
void ShowPageStart(String &page, bool auth)
{
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
return WebServer->requestAuthentication();
}
SetHeader();
ShowPageStartChunk();
ShowPageChunk(page);
}
void ShowPageStart(String &page)
{
ShowPageStart(page, true);
}
void ShowPageStopChunk()
{
WebServer->sendContent("");
WebServer->client().stop(); // Stop is needed because we sent no content length
}
void ShowPageEnd(String &page)
{
ShowPageChunk(page);
String endpart = FPSTR(HTTP_END);
endpart.replace(F("{mv"), my_version);
WebServer->sendContent(endpart);
ShowPageStopChunk();
}
/*********************************************************************************************/
void HandleWifiLogin()
{
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR( D_CONFIGURE_WIFI ));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_LOGIN);
ShowPage(page, false); // false means show page no matter if the client has or has not credentials
}
void HandleRoot()
{
// AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_MAIN_MENU));
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU);
if (CaptivePortal()) { // If captive portal redirect instead of displaying the page.
@ -441,12 +522,22 @@ void HandleRoot()
}
if (HTTP_MANAGER == webserver_state) {
HandleWifiConfiguration();
if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) {
HandleWifiLogin();
} else {
if (!(Settings.web_password[0] != 0) || ((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password ))) {
HandleWifiConfiguration();
} else {
// wrong user and pass
HandleWifiLogin();
}
}
} else {
char stemp[10];
char line[160];
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_MAIN_MENU));
page += FPSTR(HTTP_HEAD_STYLE);
page.replace(F("<body>"), F("<body onload='la()'>"));
page += F("<div id='l1' name='l1'></div>");
@ -499,7 +590,7 @@ void HandleAjaxStatusRefresh()
char svalue[80];
if (strlen(WebServer->arg("o").c_str())) {
ExecuteCommandPower(atoi(WebServer->arg("o").c_str()), 2);
ExecuteCommandPower(atoi(WebServer->arg("o").c_str()), POWER_TOGGLE);
}
if (strlen(WebServer->arg("d").c_str())) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), WebServer->arg("d").c_str());
@ -514,37 +605,23 @@ void HandleAjaxStatusRefresh()
ExecuteCommand(svalue);
}
String page = "";
mqtt_data[0] = '\0';
ShowPageStartChunk();
WebServer->sendContent(HTTP_TABLE100);
XsnsCall(FUNC_WEB_APPEND);
if (strlen(mqtt_data)) {
page += FPSTR(HTTP_TABLE100);
page += mqtt_data;
page += F("</table>");
}
char line[80];
WebServer->sendContent(PSTR("</table>"));
if (devices_present) {
page += FPSTR(HTTP_TABLE100);
page += F("<tr>");
WebServer->sendContent(HTTP_TABLE100);
WebServer->sendContent(PSTR("<tr>"));
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
for (byte idx = 1; idx <= devices_present; idx++) {
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
// snprintf_P(line, sizeof(line), PSTR("<td style='width:%d%'><div style='text-align:center;font-weight:%s;font-size:%dpx'>%s</div></td>"),
snprintf_P(line, sizeof(line), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight:
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight:
100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
page += line;
WebServer->sendContent(mqtt_data);
}
page += F("</tr></table>");
WebServer->sendContent(PSTR("</tr></table>"));
}
/*
* Will interrupt user action when selected
if (light_type) {
snprintf_P(line, sizeof(line), PSTR("<input type='range' min='1' max='100' value='%d' onchange='lb(value)'>"),
Settings.light_dimmer);
page += line;
}
*/
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
ShowPageStopChunk();
}
boolean HttpUser()
@ -565,6 +642,7 @@ void HandleConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_BTN_MENU2);
if (Settings.flag.mqtt_enabled) {
page += FPSTR(HTTP_BTN_MENU3);
@ -643,52 +721,60 @@ void HandleModuleConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MODULE));
page += FPSTR(HTTP_FORM_MODULE);
snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name);
page.replace(F("{mt"), stemp);
ShowPageStart(page);
mytmplt cmodule;
memcpy_P(&cmodule, &kModules[Settings.module], sizeof(cmodule));
String func = FPSTR(HTTP_SCRIPT_MODULE1);
page = FPSTR(HTTP_SCRIPT_MODULE1);
for (byte i = 0; i < MAXMODULE; i++) {
midx = pgm_read_byte(kNiceList + i);
snprintf_P(stemp, sizeof(stemp), kModules[midx].name);
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, midx, midx +1, stemp);
func += line;
page += line;
}
func += FPSTR(HTTP_SCRIPT_MODULE3);
page += FPSTR(HTTP_SCRIPT_MODULE3);
ShowPageChunk(page);
snprintf_P(line, sizeof(line), PSTR("sk(%d,99);o0=\""), Settings.module); // g99
func += line;
page = line;
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(stemp, sizeof(stemp), kSensors[j]);
snprintf_P(line, sizeof(line), HTTP_SCRIPT_MODULE2, j, j, stemp);
func += line;
page += line;
}
}
func += FPSTR(HTTP_SCRIPT_MODULE3);
page += FPSTR(HTTP_SCRIPT_MODULE3);
ShowPageChunk(page);
page = FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_MODULE);
snprintf_P(stemp, sizeof(stemp), kModules[MODULE].name);
page.replace(F("{mt"), stemp);
page += F("<br/><table>");
String func = "";
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if (GPIO_USER == cmodule.gp.io[i]) {
snprintf_P(stemp, 3, PINS_WEMOS +i*2);
snprintf_P(line, sizeof(line), PSTR("<tr><td style='width:190'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126'><select id='g%d' name='g%d'></select></td></tr>"),
snprintf_P(line, sizeof(line), PSTR("<tr><td style='width:190px'>%s <b>" D_GPIO "%d</b> %s</td><td style='width:126px'><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 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i);
page += line;
snprintf_P(line, sizeof(line), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16
func += line;
}
}
page += F("</table>");
func += F("}");
ShowPageChunk(func);
func += F("}</script>");
page.replace(F("</script>"), func);
page.replace(F("<body>"), F("<body onload='sl()'>"));
page += F("</table>");
ShowPageChunk(page);
page += FPSTR(HTTP_FORM_END);
page = FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
ShowPage(page);
ShowPageEnd(page);
}
void HandleWifiConfigurationWithScan()
@ -711,6 +797,7 @@ void HandleWifi(boolean scan)
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_WIFI));
page += FPSTR(HTTP_HEAD_STYLE);
if (scan) {
#ifdef USE_EMULATION
@ -790,16 +877,15 @@ void HandleWifi(boolean scan)
page += FPSTR(HTTP_FORM_WIFI);
page.replace(F("{h1"), Settings.hostname);
page.replace(F("{s1"), Settings.sta_ssid[0]);
page.replace(F("{p1"), Settings.sta_pwd[0]);
page.replace(F("{s2"), Settings.sta_ssid[1]);
page.replace(F("{p2"), Settings.sta_pwd[1]);
page += FPSTR(HTTP_FORM_END);
if (HTTP_MANAGER == webserver_state) {
page += FPSTR(HTTP_BTN_RSTRT);
} else {
page += FPSTR(HTTP_BTN_CONF);
}
ShowPage(page);
// ShowPage(page);
ShowPage(page, !(HTTP_MANAGER == webserver_state));
}
void HandleMqttConfiguration()
@ -811,6 +897,7 @@ void HandleMqttConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_MQTT);
char str[sizeof(Settings.mqtt_client)];
GetMqttClient(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client));
@ -836,6 +923,7 @@ void HandleLoggingConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_LOGGING));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_LOG1);
for (byte idx = 0; idx < 3; idx++) {
page += FPSTR(HTTP_FORM_LOG2);
@ -885,8 +973,8 @@ void HandleOtherConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_OTHER));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_OTHER);
page.replace(F("{p1"), Settings.web_password);
page.replace(F("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F(""));
uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
for (byte i = 0; i < maxfn; i++) {
@ -905,7 +993,7 @@ void HandleOtherConfiguration()
page.replace(F("{3"), (i == EMUL_NONE) ? F(D_NONE) : (i == EMUL_WEMO) ? F(D_BELKIN_WEMO) : F(D_HUE_BRIDGE));
page.replace(F("{4"), (i == EMUL_NONE) ? F("") : (i == EMUL_WEMO) ? F(" " D_SINGLE_DEVICE) : F(" " D_MULTI_DEVICE));
}
// page += F("<br/>");
page += F("<br/>");
page += F("<br/></fieldset>");
#endif // USE_EMULATION
page += FPSTR(HTTP_FORM_END);
@ -964,9 +1052,11 @@ void HandleSaveSettings()
strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname));
}
strlcpy(Settings.sta_ssid[0], (!strlen(WebServer->arg("s1").c_str())) ? STA_SSID1 : WebServer->arg("s1").c_str(), sizeof(Settings.sta_ssid[0]));
strlcpy(Settings.sta_pwd[0], (!strlen(WebServer->arg("p1").c_str())) ? STA_PASS1 : WebServer->arg("p1").c_str(), sizeof(Settings.sta_pwd[0]));
strlcpy(Settings.sta_ssid[1], (!strlen(WebServer->arg("s2").c_str())) ? STA_SSID2 : WebServer->arg("s2").c_str(), sizeof(Settings.sta_ssid[1]));
strlcpy(Settings.sta_pwd[1], (!strlen(WebServer->arg("p2").c_str())) ? STA_PASS2 : WebServer->arg("p2").c_str(), sizeof(Settings.sta_pwd[1]));
// strlcpy(Settings.sta_ssid[0], (!strlen(WebServer->arg("s1").c_str())) ? "" : WebServer->arg("s1").c_str(), sizeof(Settings.sta_ssid[0]));
// strlcpy(Settings.sta_ssid[1], (!strlen(WebServer->arg("s2").c_str())) ? "" : WebServer->arg("s2").c_str(), sizeof(Settings.sta_ssid[1]));
strlcpy(Settings.sta_pwd[0], (!strlen(WebServer->arg("p1").c_str())) ? "" : (strchr(WebServer->arg("p1").c_str(),'*')) ? Settings.sta_pwd[0] : WebServer->arg("p1").c_str(), sizeof(Settings.sta_pwd[0]));
strlcpy(Settings.sta_pwd[1], (!strlen(WebServer->arg("p2").c_str())) ? "" : (strchr(WebServer->arg("p2").c_str(),'*')) ? Settings.sta_pwd[1] : WebServer->arg("p2").c_str(), sizeof(Settings.sta_pwd[1]));
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_PASSWORD "1 %s, " D_CMND_SSID "2 %s, " D_CMND_PASSWORD "2 %s"),
Settings.hostname, Settings.sta_ssid[0], Settings.sta_pwd[0], Settings.sta_ssid[1], Settings.sta_pwd[1]);
AddLog(LOG_LEVEL_INFO);
@ -1014,7 +1104,7 @@ snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D
break;
#endif // USE_DOMOTICZ
case 5:
strlcpy(Settings.web_password, (!strlen(WebServer->arg("p1").c_str())) ? WEB_PASSWORD : (!strcmp(WebServer->arg("p1").c_str(),"0")) ? "" : WebServer->arg("p1").c_str(), sizeof(Settings.web_password));
strlcpy(Settings.web_password, (!strlen(WebServer->arg("p1").c_str())) ? "" : (strchr(WebServer->arg("p1").c_str(),'*')) ? Settings.web_password : WebServer->arg("p1").c_str(), sizeof(Settings.web_password));
Settings.flag.mqtt_enabled = WebServer->hasArg("b1");
#ifdef USE_EMULATION
Settings.flag2.emulation = (!strlen(WebServer->arg("b2").c_str())) ? 0 : atoi(WebServer->arg("b2").c_str());
@ -1055,6 +1145,7 @@ snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D
if (restart) {
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_SAVE_CONFIGURATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += F("<div style='text-align:center;'><b>" D_CONFIGURATION_SAVED "</b><br/>");
page += result;
page += F("</div>");
@ -1084,6 +1175,7 @@ void HandleResetConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_RESET_CONFIGURATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += F("<div style='text-align:center;'>" D_CONFIGURATION_RESET "</div>");
page += FPSTR(HTTP_MSG_RSTRT);
page += FPSTR(HTTP_BTN_MAIN);
@ -1102,6 +1194,7 @@ void HandleRestoreConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_RESTORE_CONFIGURATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_RST);
page += FPSTR(HTTP_FORM_RST_UPG);
page.replace(F("{r1"), F(D_RESTORE));
@ -1121,6 +1214,7 @@ void HandleUpgradeFirmware()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_FIRMWARE_UPGRADE));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_UPG);
page.replace(F("{o1"), Settings.ota_url);
page += FPSTR(HTTP_FORM_RST_UPG);
@ -1149,6 +1243,7 @@ void HandleUpgradeFirmwareStart()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_INFORMATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += F("<div style='text-align:center;'><b>" D_UPGRADE_STARTED " ...</b></div>");
page += FPSTR(HTTP_MSG_RSTRT);
page += FPSTR(HTTP_BTN_MAIN);
@ -1173,6 +1268,7 @@ void HandleUploadDone()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_INFORMATION));
page += FPSTR(HTTP_HEAD_STYLE);
page += F("<div style='text-align:center;'><b>" D_UPLOAD " <font color='");
if (upload_error) {
page += F("red'>" D_FAILED "</font></b><br/><br/>");
@ -1376,6 +1472,7 @@ void HandleHttpCommand()
}
SetHeader();
WebServer->send(200, FPSTR(HDR_CTYPE_JSON), message);
// WebServer->sendContent("");
}
void HandleConsole()
@ -1388,6 +1485,7 @@ void HandleConsole()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONSOLE));
page += FPSTR(HTTP_HEAD_STYLE);
page.replace(F("</script>"), FPSTR(HTTP_SCRIPT_CONSOL));
page.replace(F("<body>"), F("<body onload='l()'>"));
page += FPSTR(HTTP_FORM_CMND);
@ -1419,15 +1517,14 @@ void HandleAjaxConsoleRefresh()
counter = atoi(WebServer->arg("c2").c_str());
}
String message = F("<r><i>");
message += String(web_log_index);
message += F("</i><j>");
message += String(reset_web_log_flag);
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->send(200, FPSTR(HDR_CTYPE_XML), "");
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<r><i>%d</i><j>%d</j><l>"), web_log_index, reset_web_log_flag);
WebServer->sendContent(mqtt_data);
if (!reset_web_log_flag) {
counter = 99;
reset_web_log_flag = 1;
}
message += F("</j><l>");
if (counter != web_log_index) {
if (99 == counter) {
counter = web_log_index;
@ -1436,15 +1533,14 @@ void HandleAjaxConsoleRefresh()
do {
if (web_log[counter].length()) {
if (cflg) {
message += F("\n");
WebServer->sendContent(PSTR("\n"));
} else {
cflg = 1;
}
String nextline = web_log[counter];
nextline.replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent
nextline.replace(F(">"), F("%3E"));
nextline.replace(F("&"), F("%26"));
message += nextline;
web_log[counter].replace(F("<"), F("%3C")); // XML encoding to fix blank console log in concert with javascript decodeURIComponent
web_log[counter].replace(F(">"), F("%3E"));
web_log[counter].replace(F("&"), F("%26"));
WebServer->sendContent(web_log[counter]);
}
counter++;
if (counter > MAX_LOG_LINES -1) {
@ -1452,8 +1548,8 @@ void HandleAjaxConsoleRefresh()
}
} while (counter != web_log_index);
}
message += F("</l></r>");
WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
WebServer->sendContent(PSTR("</l></r>"));
ShowPageStopChunk();
}
void HandleInformation()
@ -1469,6 +1565,7 @@ void HandleInformation()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_INFORMATION));
page += FPSTR(HTTP_HEAD_STYLE);
// page += F("<fieldset><legend><b>&nbsp;Information&nbsp;</b></legend>");
page += F("<style>td{padding:0px 5px;}</style>");
@ -1580,6 +1677,7 @@ void HandleRestart()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_RESTART));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_MSG_RSTRT);
if (HTTP_MANAGER == webserver_state) {
webserver_state = HTTP_ADMIN;
@ -1609,18 +1707,13 @@ void HandleNotFound()
} else
#endif // USE_EMULATION
{
String message = F(D_FILE_NOT_FOUND "\n\nURI: ");
message += WebServer->uri();
message += F("\nMethod: ");
message += (WebServer->method() == HTTP_GET) ? F("GET") : F("POST");
message += F("\nArguments: ");
message += WebServer->args();
message += F("\n");
for ( uint8_t i = 0; i < WebServer->args(); i++ ) {
message += " " + WebServer->argName(i) + ": " + WebServer->arg(i) + "\n";
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"),
WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args());
for (uint8_t i = 0; i < WebServer->args(); i++) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str());
}
SetHeader();
WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), message);
WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data);
}
}

View File

@ -99,6 +99,7 @@ uint8_t light_signal_color[5];
uint8_t light_wheel = 0;
uint8_t light_subtype = 0;
uint8_t light_device = 0;
uint8_t light_power = 0;
uint8_t light_update = 1;
uint8_t light_wakeup_active = 0;
@ -337,6 +338,7 @@ void LightInit()
{
uint8_t max_scheme = LS_MAX -1;
light_device = devices_present;
light_subtype = light_type &7;
if (light_type < LT_PWM6) { // PWM
@ -526,35 +528,56 @@ char* LightGetColor(uint8_t type, char* scolor)
void LightPowerOn()
{
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(devices_present, 1);
ExecuteCommandPower(light_device, POWER_ON);
}
}
void LightPreparePower()
void LightState(uint8_t append)
{
char scolor[25];
char scommand[33];
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(devices_present, 7); // No publishPowerState
if (append) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{"));
}
else if (!Settings.light_dimmer && light_power) {
ExecuteCommandPower(devices_present, 6); // No publishPowerState
}
#ifdef USE_DOMOTICZ
DomoticzUpdatePowerState(devices_present);
#endif // USE_DOMOTICZ
GetPowerDevice(scommand, devices_present, sizeof(scommand));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"),
scommand, GetStateText(light_power), Settings.light_dimmer);
GetPowerDevice(scommand, light_device, sizeof(scommand));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"),
mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer);
if (light_subtype > LST_SINGLE) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor));
}
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp());
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
if (append) {
if (light_subtype >= LST_RGB) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_SCHEME "\":%d"), mqtt_data, Settings.light_scheme);
}
if (LT_WS2812 == light_type) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_WIDTH "\":%d"), mqtt_data, Settings.light_width);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""),
mqtt_data, GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction));
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
}
}
void LightPreparePower()
{
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(light_device, POWER_ON_NO_STATE);
}
else if (!Settings.light_dimmer && light_power) {
ExecuteCommandPower(light_device, POWER_OFF_NO_STATE);
}
#ifdef USE_DOMOTICZ
DomoticzUpdatePowerState(light_device);
#endif // USE_DOMOTICZ
LightState(0);
}
void LightFade()
@ -638,7 +661,8 @@ void LightRandomColor()
void LightSetPower()
{
light_power = XdrvMailbox.index;
// light_power = XdrvMailbox.index;
light_power = bitRead(XdrvMailbox.index, light_device -1);
if (light_wakeup_active) {
light_wakeup_active--;
}

View File

@ -309,21 +309,26 @@ boolean IrSendCommand()
data = ir_json[D_JSON_IR_DATA];
if (protocol && bits && data) {
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %d, protocol_code %d"),
protocol_text, protocol, bits, data, protocol_code);
AddLog(LOG_LEVEL_DEBUG);
switch (protocol_code) {
case NEC:
irsend->sendNEC(data, bits); break;
irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break;
case SONY:
irsend->sendSony(data, bits); break;
irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break;
case RC5:
irsend->sendRC5(data, bits); break;
case RC6:
irsend->sendRC6(data, bits); break;
case DISH:
irsend->sendDISH(data, bits); break;
irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break;
case JVC:
irsend->sendJVC(data, bits, 1); break;
irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break;
case SAMSUNG:
irsend->sendSAMSUNG(data, bits); break;
irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break;
case PANASONIC:
irsend->sendPanasonic(bits, data); break;
default:

View File

@ -49,7 +49,7 @@ float energy_daily = 0; // 12.123 kWh
float energy_total = 0; // 12345.12345 kWh
float energy_start = 0; // 12345.12345 kWh total from yesterday
unsigned long energy_kWhtoday; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily
unsigned long energy_period = 0; //
unsigned long energy_period = 0; // 1212312345 Wh * 10^-5 (deca micro Watt hours) - 5763924 = 0.05763924 kWh = 0.058 kWh = energy_daily
byte energy_min_power_flag = 0;
byte energy_max_power_flag = 0;
@ -227,7 +227,7 @@ void HlwInit()
hlw_cf1_current_max_pulse_counter = 0;
hlw_load_off = 1;
hlw_energy_period_counter = 0;
hlw_energy_period_counter = 1;
hlw_select_ui_flag = 0; // Voltage;
@ -437,6 +437,7 @@ void Energy200ms()
Settings.energy_kWhtotal += (energy_kWhtoday / 1000);
RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal;
energy_kWhtoday = 0;
energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
#ifdef USE_PZEM004T
if (ENERGY_PZEM004T == energy_flg) {
@ -451,6 +452,7 @@ void Energy200ms()
}
if (energy_startup && (RtcTime.day_of_year == Settings.energy_kWhdoy)) {
energy_kWhtoday = Settings.energy_kWhtoday;
energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
energy_start = (float)Settings.hlw_power_calibration / 1000; // Used by PZEM004T to store total yesterday
energy_startup = 0;
@ -573,7 +575,7 @@ void EnergyMarginCheck()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
ExecuteCommandPower(1, 0);
ExecuteCommandPower(1, POWER_OFF);
if (!energy_mplr_counter) {
energy_mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
}
@ -595,7 +597,7 @@ void EnergyMarginCheck()
if (energy_mplr_counter) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR));
ExecuteCommandPower(1, 1);
ExecuteCommandPower(1, POWER_ON);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0));
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
@ -613,7 +615,7 @@ void EnergyMarginCheck()
energy_max_energy_state = 1;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
ExecuteCommandPower(1, 1);
ExecuteCommandPower(1, POWER_ON);
}
else if ((1 == energy_max_energy_state) && (energy_daily_u >= Settings.energy_max_energy)) {
energy_max_energy_state = 2;
@ -621,7 +623,7 @@ void EnergyMarginCheck()
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : "");
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
EnergyMqttShow();
ExecuteCommandPower(1, 0);
ExecuteCommandPower(1, POWER_OFF);
}
}
#endif // FEATURE_POWER_LIMIT
@ -699,6 +701,7 @@ boolean EnergyCommand()
switch (XdrvMailbox.index) {
case 1:
energy_kWhtoday = lnum *100000;
energy_period = energy_kWhtoday;
RtcSettings.energy_kWhtoday = energy_kWhtoday;
Settings.energy_kWhtoday = energy_kWhtoday;
break;
@ -856,7 +859,7 @@ void EnergyInit()
if (energy_flg) {
energy_kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : 0;
energy_period = energy_kWhtoday;
energy_startup = 1;
ticker_energy.attach_ms(200, Energy200ms);
}

View File

@ -25,20 +25,18 @@ const char HTTP_FORM_DOMOTICZ[] PROGMEM =
"<input id='w' name='w' value='4' hidden><input id='r' name='r' value='1' hidden>"
"<br/><table>";
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
"<tr><td width='260'><b>" D_DOMOTICZ_IDX " {1</b></td><td width='70'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
"<tr><td width='260'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td width='70'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " {1</b></td><td style='width:70px'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td style='width:70px'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
"<tr><td width='260'><b>" D_DOMOTICZ_SWITCH_IDX " {1</b></td><td width='70'><input id='s{1' name='s{1' placeholder='0' value='{4'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " {1</b></td><td style='width:70px'><input id='s{1' name='s{1' placeholder='0' value='{4'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
"<tr><td width='260'><b>" D_DOMOTICZ_SENSOR_IDX " {1</b> {2</td><td width='70'><input id='l{1' name='l{1' placeholder='0' value='{5'></td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " {1</b> {2</td><td style='width:70px'><input id='l{1' name='l{1' placeholder='0' value='{5'></td></tr>";
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
"<tr><td width='260'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td width='70'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
#endif // USE_WEBSERVER
enum DomoticzCommands {
CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER };
const char kDomoticzCommands[] PROGMEM =
D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ;
enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER };
const char kDomoticzCommands[] PROGMEM = D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ;
//enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS};
@ -338,6 +336,7 @@ void HandleDomoticzConfiguration()
String page = FPSTR(HTTP_HEAD);
page.replace(F("{v}"), FPSTR(S_CONFIGURE_DOMOTICZ));
page += FPSTR(HTTP_HEAD_STYLE);
page += FPSTR(HTTP_FORM_DOMOTICZ);
for (int i = 0; i < MAX_DOMOTICZ_IDX; i++) {
if (i < devices_present) {

View File

@ -17,58 +17,49 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
void XDrvInit()
{
for (byte i = 0; i < XDRV_MAX; i++) {
xdrv_func_ptr[i] = NULL;
}
xdrv_present = 0;
boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointers
#ifdef XDRV_01
xdrv_func_ptr[xdrv_present++] = &Xdrv01;
&Xdrv01,
#endif
#ifdef XDRV_02
xdrv_func_ptr[xdrv_present++] = &Xdrv02;
&Xdrv02,
#endif
#ifdef XDRV_03
xdrv_func_ptr[xdrv_present++] = &Xdrv03;
&Xdrv03,
#endif
#ifdef XDRV_04
xdrv_func_ptr[xdrv_present++] = &Xdrv04;
&Xdrv04,
#endif
#ifdef XDRV_05
xdrv_func_ptr[xdrv_present++] = &Xdrv05;
&Xdrv05,
#endif
#ifdef XDRV_06
xdrv_func_ptr[xdrv_present++] = &Xdrv06;
&Xdrv06,
#endif
#ifdef XDRV_07
xdrv_func_ptr[xdrv_present++] = &Xdrv07;
&Xdrv07,
#endif
#ifdef XDRV_08
xdrv_func_ptr[xdrv_present++] = &Xdrv08;
&Xdrv08,
#endif
#ifdef XDRV_09
xdrv_func_ptr[xdrv_present++] = &Xdrv09;
&Xdrv09,
#endif
#ifdef XDRV_10
xdrv_func_ptr[xdrv_present++] = &Xdrv10;
&Xdrv10,
#endif
};
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Drivers %d"), xdrv_present);
// AddLog(LOG_LEVEL_DEBUG);
XdrvCall(FUNC_INIT);
}
const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); // Number of drivers found
boolean XdrvCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload)
{
@ -82,7 +73,7 @@ boolean XdrvCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len
return XdrvCall(FUNC_COMMAND);
}
void XdrvSetPower(uint8_t mpower)
void XdrvSetPower(power_t mpower)
{
// XdrvMailbox.valid = 1;
XdrvMailbox.index = mpower;
@ -102,6 +93,16 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t
/*********************************************************************************************\
* Function call to all xdrv
*
* FUNC_INIT
* FUNC_MQTT_SUBSCRIBE
* FUNC_MQTT_INIT
* return FUNC_MQTT_DATA
* return FUNC_COMMAND
* FUNC_SET_POWER
* FUNC_SHOW_SENSOR
* FUNC_EVERY_SECOND
* FUNC_EVERY_50_MSECOND
\*********************************************************************************************/
boolean XdrvCall(byte Function)

View File

@ -388,10 +388,10 @@ void HandleUpnpEvent()
//differentiate get and set state
if (request.indexOf(F("SetBinaryState")) > 0) {
if (request.indexOf(F("State>1</Binary")) > 0) {
ExecuteCommandPower(devices_present, 1);
ExecuteCommandPower(devices_present, POWER_ON);
}
else if (request.indexOf(F("State>0</Binary")) > 0) {
ExecuteCommandPower(devices_present, 0);
ExecuteCommandPower(devices_present, POWER_OFF);
}
}
else if(request.indexOf(F("GetBinaryState")) > 0){
@ -661,10 +661,10 @@ void HueLights(String *path)
on = hue_json["on"];
switch(on)
{
case false : ExecuteCommandPower(device, 0);
case false : ExecuteCommandPower(device, POWER_OFF);
response.replace("{re", "false");
break;
case true : ExecuteCommandPower(device, 1);
case true : ExecuteCommandPower(device, POWER_ON);
response.replace("{re", "true");
break;
default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false");

View File

@ -504,8 +504,14 @@ boolean Xsns09(byte function)
switch (function) {
case FUNC_PREP_BEFORE_TELEPERIOD:
BmpDetect();
break;
case FUNC_EVERY_SECOND:
#ifdef USE_BME680
Bme680PerformReading();
if ((Settings.tele_period - tele_period) < 300) { // 5 minute stabilization time
if (tele_period &1) {
Bme680PerformReading(); // Keep BME680 busy every two seconds
}
}
#endif // USE_BME680
break;
case FUNC_JSON_APPEND:

View File

@ -19,6 +19,9 @@
#ifdef USE_I2C
#ifdef USE_INA219
#define XSNS_13 13
/*********************************************************************************************\
* INA219 - Low voltage (max 32V!) Current sensor
*
@ -152,6 +155,23 @@ float Ina219GetCurrent_mA()
return value;
}
/*********************************************************************************************\
* Command Sensor13
\*********************************************************************************************/
bool Ina219CommandSensor()
{
boolean serviced = true;
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings.ina219_mode = XdrvMailbox.payload;
restart_flag = 2;
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode);
return serviced;
}
/********************************************************************************************/
void Ina219Detect()
@ -211,14 +231,17 @@ void Ina219Show(boolean json)
* Interface
\*********************************************************************************************/
#define XSNS_13
boolean Xsns13(byte function)
{
boolean result = false;
if (i2c_flg) {
switch (function) {
case FUNC_COMMAND:
if ((XSNS_13 == XdrvMailbox.index) && (ina219_type)) {
result = Ina219CommandSensor();
}
break;
case FUNC_PREP_BEFORE_TELEPERIOD:
Ina219Detect();
break;

View File

@ -18,6 +18,9 @@
*/
#ifdef USE_MHZ19
#define XSNS_15 15
/*********************************************************************************************\
* MH-Z19 - CO2 sensor
*
@ -71,6 +74,7 @@ const char kMhzTypes[] PROGMEM = "MHZ19|MHZ19B";
const uint8_t mhz_cmnd_read_ppm[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
const uint8_t mhz_cmnd_abc_enable[9] = {0xFF, 0x01, 0x79, 0xA0, 0x00, 0x00, 0x00, 0x00, 0xE6};
const uint8_t mhz_cmnd_abc_disable[9] = {0xFF, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86};
const uint8_t mhz_cmnd_zeropoint[9] = {0xff, 0x01, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78};
uint8_t mhz_type = 1;
uint16_t mhz_last_ppm = 0;
@ -208,6 +212,34 @@ void Mhz50ms()
}
}
/*********************************************************************************************\
* Command Sensor15
\*********************************************************************************************/
/*
0 - ABC Off
1 - ABC On
2 - Manual start = ABC Off
3 - Optional filter settings
*/
bool MhzCommandSensor()
{
boolean serviced = true;
switch (XdrvMailbox.payload) {
case 2:
MhzSerial->write(mhz_cmnd_zeropoint, 9);
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION);
break;
default:
serviced = false;
}
return serviced;
}
/*********************************************************************************************/
void MhzInit()
@ -244,8 +276,6 @@ void MhzShow(boolean json)
* Interface
\*********************************************************************************************/
#define XSNS_15
boolean Xsns15(byte function)
{
boolean result = false;
@ -258,6 +288,11 @@ boolean Xsns15(byte function)
case FUNC_EVERY_50_MSECOND:
Mhz50ms();
break;
case FUNC_COMMAND:
if (XSNS_15 == XdrvMailbox.index) {
result = MhzCommandSensor();
}
break;
case FUNC_JSON_APPEND:
MhzShow(1);
break;

View File

@ -1,5 +1,5 @@
/*
xsns_interface.ino - External sensor interface support for Sonoff-Tasmota
xsns_interface.ino - Sensor interface support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends inspired by ESPEasy
@ -17,101 +17,101 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
void XSnsInit()
{
for (byte i = 0; i < XSNS_MAX; i++) {
xsns_func_ptr[i] = NULL;
}
xsns_present = 0;
boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers for simple implementation of sensors
#ifdef XSNS_01
xsns_func_ptr[xsns_present++] = &Xsns01;
&Xsns01,
#endif
#ifdef XSNS_02
xsns_func_ptr[xsns_present++] = &Xsns02;
&Xsns02,
#endif
#ifdef XSNS_03
xsns_func_ptr[xsns_present++] = &Xsns03;
&Xsns03,
#endif
#ifdef XSNS_04
xsns_func_ptr[xsns_present++] = &Xsns04;
&Xsns04,
#endif
#ifdef XSNS_05
xsns_func_ptr[xsns_present++] = &Xsns05;
&Xsns05,
#endif
#ifdef XSNS_06
xsns_func_ptr[xsns_present++] = &Xsns06;
&Xsns06,
#endif
#ifdef XSNS_07
xsns_func_ptr[xsns_present++] = &Xsns07;
&Xsns07,
#endif
#ifdef XSNS_08
xsns_func_ptr[xsns_present++] = &Xsns08;
&Xsns08,
#endif
#ifdef XSNS_09
xsns_func_ptr[xsns_present++] = &Xsns09;
&Xsns09,
#endif
#ifdef XSNS_10
xsns_func_ptr[xsns_present++] = &Xsns10;
&Xsns10,
#endif
#ifdef XSNS_11
xsns_func_ptr[xsns_present++] = &Xsns11;
&Xsns11,
#endif
#ifdef XSNS_12
xsns_func_ptr[xsns_present++] = &Xsns12;
&Xsns12,
#endif
#ifdef XSNS_13
xsns_func_ptr[xsns_present++] = &Xsns13;
&Xsns13,
#endif
#ifdef XSNS_14
xsns_func_ptr[xsns_present++] = &Xsns14;
&Xsns14,
#endif
#ifdef XSNS_15
xsns_func_ptr[xsns_present++] = &Xsns15;
&Xsns15,
#endif
#ifdef XSNS_16
xsns_func_ptr[xsns_present++] = &Xsns16;
&Xsns16,
#endif
#ifdef XSNS_17
xsns_func_ptr[xsns_present++] = &Xsns17;
&Xsns17,
#endif
#ifdef XSNS_18
xsns_func_ptr[xsns_present++] = &Xsns18;
&Xsns18,
#endif
#ifdef XSNS_19
xsns_func_ptr[xsns_present++] = &Xsns19;
&Xsns19,
#endif
#ifdef XSNS_20
xsns_func_ptr[xsns_present++] = &Xsns20;
&Xsns20,
#endif
};
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Sensors found %d"), xsns_present);
// AddLog(LOG_LEVEL_DEBUG);
XsnsCall(FUNC_INIT);
}
const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); // Number of External Sensors found
/*********************************************************************************************\
* Function call to all xsns
*
* FUNC_INIT
* FUNC_PREP_BEFORE_TELEPERIOD
* FUNC_SAVE_BEFORE_RESTART
* FUNC_JSON_APPEND
* FUNC_WEB_APPEND
* return FUNC_COMMAND
* FUNC_EVERY_SECOND
* FUNC_EVERY_50_MSECOND
\*********************************************************************************************/
boolean XsnsCall(byte Function)
@ -119,7 +119,23 @@ boolean XsnsCall(byte Function)
boolean result = false;
for (byte x = 0; x < xsns_present; x++) {
xsns_func_ptr[x](Function);
if (FUNC_WEB_APPEND == Function) {
mqtt_data[0] = '\0';
}
result = xsns_func_ptr[x](Function);
if (result) {
break;
}
if ((FUNC_WEB_APPEND == Function) && strlen(mqtt_data)) {
if (D_DECIMAL_SEPARATOR[0] != '.') {
for (int i = 0; i < strlen(mqtt_data); i++) {
if ('.' == mqtt_data[i]) {
mqtt_data[i] = D_DECIMAL_SEPARATOR[0];
}
}
}
WebServer->sendContent(mqtt_data);
}
}
return result;