Merge branch 'arendst/development' into development

This commit is contained in:
reloxx13 2018-01-24 20:07:07 +01:00
commit 86700e7d4b
27 changed files with 381 additions and 225 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.1d** - 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,14 @@
/* 5.11.1d
/* 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

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"
@ -172,6 +173,7 @@
#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"
@ -237,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
@ -396,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 "."

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 "-"

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 "-"

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 "-"

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 "-"

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 "-"

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 "-"

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 "-"

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

@ -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};

View File

@ -25,10 +25,10 @@
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
====================================================*/
#define VERSION 0x050B0104 // 5.11.1d
#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
@ -68,24 +68,24 @@
enum TasmotaCommands {
CMND_BACKLOG, CMND_DELAY, CMND_POWER, CMND_STATUS, CMND_STATE, CMND_POWERONSTATE, CMND_PULSETIME,
CMND_BLINKTIME, CMND_BLINKCOUNT, 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_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_STATE "|" 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_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,10 +186,6 @@ 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
@ -293,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;
}
@ -945,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);
}
}
}
@ -991,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
@ -1493,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
}
@ -1588,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;
}
@ -1599,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);
@ -1609,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);
@ -1630,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
@ -1644,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);
@ -1820,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);
@ -1962,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 {
@ -1971,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;
@ -2026,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) {
@ -2114,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)
}
}
@ -2165,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);
}
}
}
@ -2645,7 +2643,7 @@ void GpioInit()
}
SetLedPower(Settings.ledstate &8);
XDrvInit();
XdrvCall(FUNC_INIT);
}
extern "C" {
@ -2705,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);
@ -2747,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];
}
}
@ -2764,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

@ -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,11 +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
//#if (MY_LANGUAGE == es-AR) // This does not function
// "<div style='text-align:center;'><h3>" D_MODULE " {ha</h3><h2>{h}</h2></div>";
//#else
#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
#endif
const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"var sn=0;" // Scroll position
"var id=99;" // Get most of weblog initially
@ -422,13 +424,10 @@ void SetHeader()
#endif
}
/*********************************************************************************************/
void ShowPage(String &page, bool auth)
{
// if((HTTP_ADMIN == webserver_state) && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
// return WebServer->requestAuthentication();
// }
//Authentication
if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) {
return WebServer->requestAuthentication();
}
@ -445,7 +444,6 @@ void ShowPage(String &page, bool auth)
page.replace(F("{mv"), my_version);
SetHeader();
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), page);
// WebServer->sendContent("");
}
void ShowPage(String &page)
@ -453,11 +451,64 @@ void ShowPage(String &page)
ShowPage(page, true);
}
//Authentication
/*********************************************************************************************/
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
}
@ -471,9 +522,6 @@ void HandleRoot()
}
if (HTTP_MANAGER == webserver_state) {
// HandleWifiConfiguration();
//Authentication
if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) {
HandleWifiLogin();
} else {
@ -484,12 +532,12 @@ void HandleRoot()
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>");
@ -542,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());
@ -557,38 +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.replace(F("."), F(D_DECIMAL_SEPARATOR));
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{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);
// WebServer->sendContent("");
ShowPageStopChunk();
}
boolean HttpUser()
@ -609,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);
@ -687,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()
@ -755,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
@ -854,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));
@ -879,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);
@ -928,6 +973,7 @@ 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("{r1"), (Settings.flag.mqtt_enabled) ? F(" checked") : F(""));
uint8_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present;
@ -1099,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>");
@ -1128,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);
@ -1146,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));
@ -1165,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);
@ -1193,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);
@ -1217,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/>");
@ -1433,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);
@ -1464,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;
@ -1481,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) {
@ -1497,9 +1548,8 @@ void HandleAjaxConsoleRefresh()
}
} while (counter != web_log_index);
}
message += F("</l></r>");
WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
// WebServer->sendContent("");
WebServer->sendContent(PSTR("</l></r>"));
ShowPageStopChunk();
}
void HandleInformation()
@ -1515,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>");
@ -1626,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;
@ -1655,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

@ -528,7 +528,7 @@ char* LightGetColor(uint8_t type, char* scolor)
void LightPowerOn()
{
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(light_device, 1);
ExecuteCommandPower(light_device, POWER_ON);
}
}
@ -568,10 +568,10 @@ void LightState(uint8_t append)
void LightPreparePower()
{
if (Settings.light_dimmer && !(light_power)) {
ExecuteCommandPower(light_device, 7); // No publishPowerState
ExecuteCommandPower(light_device, POWER_ON_NO_STATE);
}
else if (!Settings.light_dimmer && light_power) {
ExecuteCommandPower(light_device, 6); // No publishPowerState
ExecuteCommandPower(light_device, POWER_OFF_NO_STATE);
}
#ifdef USE_DOMOTICZ
DomoticzUpdatePowerState(light_device);

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)
{

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

@ -507,8 +507,10 @@ boolean Xsns09(byte function)
break;
case FUNC_EVERY_SECOND:
#ifdef USE_BME680
if (tele_period == Settings.tele_period -3) {
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;

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,7 +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};
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;
@ -209,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()
@ -245,8 +276,6 @@ void MhzShow(boolean json)
* Interface
\*********************************************************************************************/
#define XSNS_15
boolean Xsns15(byte function)
{
boolean result = false;
@ -259,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,98 +17,89 @@
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
@ -118,6 +109,7 @@ void XSnsInit()
* FUNC_SAVE_BEFORE_RESTART
* FUNC_JSON_APPEND
* FUNC_WEB_APPEND
* return FUNC_COMMAND
* FUNC_EVERY_SECOND
* FUNC_EVERY_50_MSECOND
\*********************************************************************************************/
@ -127,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;