From ca431184e6340da36607cc6dd504d7a06b1e54e8 Mon Sep 17 00:00:00 2001 From: arendst Date: Tue, 10 Oct 2017 15:40:02 +0200 Subject: [PATCH] v5.8.0j - Fixes and Prep for more relays 5.8.0j * Set default altitude to 0 to be used with pressure sensors * Document flash settings area for future use * Prepare for 32-bit power control (#995) * Introduce sonoff.h master header * Fix TLS MQTT SSL fingerprint test (#808, #970) * Fix pressure calculation for some BMP versions regression introduced with version 5.8.0i (#974) * Fix Domoticz Dimmer set to same level not powering on (#945) --- README.md | 2 +- sonoff/_releasenotes.ino | 11 +- sonoff/settings.h | 318 +++++++++++++++++++------------------- sonoff/settings.ino | 60 ++++--- sonoff/sonoff.h | 102 ++++++++++++ sonoff/sonoff.ino | 226 +++++++++++---------------- sonoff/webserver.ino | 6 +- sonoff/xdrv_domoticz.ino | 13 +- sonoff/xdrv_ir_send.ino | 4 +- sonoff/xdrv_snfbridge.ino | 2 +- sonoff/xdrv_snfled.ino | 6 +- sonoff/xdrv_wemohue.ino | 4 +- sonoff/xsns_bmp.ino | 1 + sonoff/xsns_ds18b20.ino | 4 +- 14 files changed, 405 insertions(+), 354 deletions(-) create mode 100644 sonoff/sonoff.h diff --git a/README.md b/README.md index 77ed35fc1e63..264e899a0a85 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.8.0i** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.8.0j** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index e7c3576742b9..ed75ef40d4c6 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,13 @@ -/* 5.8.0i +/* 5.8.0j + * Set default altitude to 0 to be used with pressure sensors + * Document flash settings area for future use + * Prepare for 32-bit power control (#995) + * Introduce sonoff.h master header + * Fix TLS MQTT SSL fingerprint test (#808, #970) + * Fix pressure calculation for some BMP versions regression introduced with version 5.8.0i (#974) + * Fix Domoticz Dimmer set to same level not powering on (#945) + * + * 5.8.0i * Add Domoticz counter sensor to IrReceive representing Received IR Protocol and Data * Fix Southern Hemisphere TIME_STD/TIME_DST (#968) * Add Sea level pressure calculation (#974) diff --git a/sonoff/settings.h b/sonoff/settings.h index 90f2ddce441d..2bfbda85f673 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -52,172 +52,166 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu } sysBitfield; struct SYSCFG { - unsigned long cfg_holder; - unsigned long saveFlag; - unsigned long version; - unsigned long bootcount; - sysBitfield flag; // Add flag since 5.0.2 - int16_t savedata; - - int8_t timezone; - char otaUrl[101]; - - char mqtt_prefix[3][11]; // was ex_friendlyname[33] until 3.2.5 - - byte serial_enable; // Not used (ever) - byte seriallog_level; - uint8_t sta_config; - byte sta_active; - char sta_ssid[2][33]; - char sta_pwd[2][65]; - char hostname[33]; - char syslog_host[33]; - uint16_t syslog_port; - byte syslog_level; - uint8_t webserver; - byte weblog_level; - - char mqtt_fingerprint[60]; - char mqtt_host[33]; - uint16_t mqtt_port; - char mqtt_client[33]; - char mqtt_user[33]; - char mqtt_pwd[33]; - char mqtt_topic[33]; - char button_topic[33]; - char mqtt_grptopic[33]; - char ex_state_text[3][11]; // was state_text until 5.1.6, was ex_mqtt_subtopic[33] until 4.1.1 - byte ex_mqtt_button_retain; // Not used since 5.0.2 - byte ex_mqtt_power_retain; // Not used since 5.0.2 - //byte ex_value_units; // Not used since 5.0.2 - //byte ex_button_restrict; // Not used since 5.0.2 - int16_t altitude; // Add since 5.8.0i - uint16_t tele_period; - - uint8_t power; - uint8_t ledstate; - - uint8_t param[PARAM8_SIZE]; // was domoticz_in_topic until 5.1.6 - char state_text[4][11]; // was domoticz_out_topic until 5.1.6 - - uint16_t domoticz_update_timer; - unsigned long domoticz_relay_idx[4]; - unsigned long domoticz_key_idx[4]; - - unsigned long hlw_pcal; - unsigned long hlw_ucal; - unsigned long hlw_ical; - unsigned long hlw_kWhtoday; - unsigned long hlw_kWhyesterday; - uint16_t hlw_kWhdoy; - uint16_t hlw_pmin; - uint16_t hlw_pmax; - uint16_t hlw_umin; - uint16_t hlw_umax; - uint16_t hlw_imin; - uint16_t hlw_imax; - uint16_t hlw_mpl; // MaxPowerLimit - uint16_t hlw_mplh; // MaxPowerLimitHold - uint16_t hlw_mplw; // MaxPowerLimitWindow - uint16_t hlw_mspl; // MaxSafePowerLimit - uint16_t hlw_msplh; // MaxSafePowerLimitHold - uint16_t hlw_msplw; // MaxSafePowerLimitWindow - uint16_t hlw_mkwh; // MaxEnergy - uint16_t hlw_mkwhs; // MaxEnergyStart - - // 3.0.6 - uint16_t mqtt_retry; // was ex_pulsetime until 4.0.4 - - // 3.1.1 - uint8_t poweronstate; - - // 3.1.6 - uint16_t blinktime; - uint16_t blinkcount; - - // 3.2.4 - uint16_t ws_pixels; - uint8_t ws_red; - uint8_t ws_green; - uint8_t ws_blue; - uint8_t ws_ledtable; - uint8_t ws_dimmer; - uint8_t ws_fade; - uint8_t ws_speed; - uint8_t ws_scheme; - uint8_t ws_width; - uint16_t ws_wakeup; - - // 3.2.5 - char friendlyname[4][33]; - - // 3.2.8 - char switch_topic[33]; - byte ex_mqtt_switch_retain; // Not used since 5.0.2 - uint8_t ex_mqtt_enabled; // Not used since 5.0.2 - - // 3.2.12 - uint8_t sleep; - - // 3.9.3 - uint16_t domoticz_switch_idx[4]; - uint16_t domoticz_sensor_idx[12]; - uint8_t module; - mytmplt my_module; - uint16_t led_pixels; - uint8_t led_color[5]; - uint8_t led_table; - uint8_t led_dimmer; - uint8_t ex_led_dimmer1; // Never used - uint8_t ex_led_dimmer2; // Never used - uint8_t led_fade; - uint8_t led_speed; - uint8_t led_scheme; - uint8_t led_width; - uint16_t led_wakeup; - - // 3.9.7 - uint8_t ex_emulation; // Not used since 5.0.2 - - // 3.9.20 - char web_password[33]; - - // 3.9.21 - uint8_t switchmode[4]; - - // 4.0.4 - char ntp_server[3][33]; - uint16_t pulsetime[MAX_PULSETIMERS]; - - // 4.0.7 - uint16_t pwmvalue[5]; - - // 4.0.9 - uint32_t ip_address[4]; - - // 5.0.4 - unsigned long hlw_kWhtotal; - - // 5.0.4a - char mqtt_fulltopic[101]; - - // 5.1.1 - unsigned long pCounter[MAX_COUNTERS]; - uint16_t pCounterType; - uint16_t pCounterDebounce; - - // 5.4.1 - uint8_t sfb_code[17][9]; + unsigned long cfg_holder; // 000 + unsigned long saveFlag; // 004 + unsigned long version; // 008 + unsigned long bootcount; // 00C + sysBitfield flag; // 010 Add flag since 5.0.2 + int16_t savedata; // 014 + int8_t timezone; // 016 + char otaUrl[101]; // 017 + char mqtt_prefix[3][11]; // 07C + + byte free_09D[1]; // 09D + + byte seriallog_level; // 09E + uint8_t sta_config; // 09F + byte sta_active; // 0A0 + char sta_ssid[2][33]; // 0A1 + char sta_pwd[2][65]; // 0E3 + char hostname[33]; // 165 + char syslog_host[33]; // 186 + + byte free_1A7[1]; // 1A7 + + uint16_t syslog_port; // 1A8 + byte syslog_level; // 1AA + uint8_t webserver; // 1AB + byte weblog_level; // 1AC + char mqtt_fingerprint[60]; // 1AD To be freed by binary fingerprint + char mqtt_host[33]; // 1E9 + uint16_t mqtt_port; // 20A + char mqtt_client[33]; // 20C + char mqtt_user[33]; // 22D + char mqtt_pwd[33]; // 24E + char mqtt_topic[33]; // 26F + char button_topic[33]; // 290 + char mqtt_grptopic[33]; // 2B1 + uint8_t mqtt_fingerprinth[20]; // 2D2 Reserved for binary fingerprint + + byte free_2E6[2]; // 2E6 + + power_t power; // 2E8 + + byte free_2EC[10]; // 2EC + + int16_t altitude; // 2F6 Add since 5.8.0i + uint16_t tele_period; // 2F8 + uint8_t ex_power; // 2FA Not used since 5.8.0j + uint8_t ledstate; // 2FB + uint8_t param[PARAM8_SIZE]; // 2FC was domoticz_in_topic until 5.1.6 + char state_text[4][11]; // 313 + + byte free_33F[1]; // 33F + + uint16_t domoticz_update_timer; // 340 + + byte free_342[2]; // 342 + + unsigned long domoticz_relay_idx[4]; // 344 + unsigned long domoticz_key_idx[4]; // 354 + + unsigned long hlw_pcal; // 364 + unsigned long hlw_ucal; // 368 + unsigned long hlw_ical; // 36C + unsigned long hlw_kWhtoday; // 370 + unsigned long hlw_kWhyesterday; // 374 + uint16_t hlw_kWhdoy; // 378 + uint16_t hlw_pmin; // 37A + uint16_t hlw_pmax; // 37C + uint16_t hlw_umin; // 37E + uint16_t hlw_umax; // 380 + uint16_t hlw_imin; // 382 + uint16_t hlw_imax; // 384 + uint16_t hlw_mpl; // 386 MaxPowerLimit + uint16_t hlw_mplh; // 388 MaxPowerLimitHold + uint16_t hlw_mplw; // 38A MaxPowerLimitWindow + uint16_t hlw_mspl; // 38C MaxSafePowerLimit + uint16_t hlw_msplh; // 38E MaxSafePowerLimitHold + uint16_t hlw_msplw; // 390 MaxSafePowerLimitWindow + uint16_t hlw_mkwh; // 392 MaxEnergy + uint16_t hlw_mkwhs; // 394 MaxEnergyStart + uint16_t mqtt_retry; // 396 + uint8_t poweronstate; // 398 + + byte free_399[1]; // 399 + + uint16_t blinktime; // 39A + uint16_t blinkcount; // 39C + uint16_t ws_pixels; // 39E Not used since 5.8.0 + uint8_t ws_red; // 3A0 Not used since 5.8.0 + uint8_t ws_green; // 3A1 Not used since 5.8.0 + uint8_t ws_blue; // 3A2 Not used since 5.8.0 + uint8_t ws_ledtable; // 3A3 Not used since 5.8.0 + uint8_t ws_dimmer; // 3A4 Not used since 5.8.0 + uint8_t ws_fade; // 3A5 Not used since 5.8.0 + uint8_t ws_speed; // 3A6 Not used since 5.8.0 + uint8_t ws_scheme; // 3A7 Not used since 5.8.0 + uint8_t ws_width; // 3A8 Not used since 5.8.0 + + byte free_3A9[1]; // 3A9 + + uint16_t ws_wakeup; // 3AA Not used since 5.8.0 + char friendlyname[4][33]; // 3AC + char switch_topic[33]; // 430 + + byte free_451[2]; // 451 + + uint8_t sleep; // 453 + uint16_t domoticz_switch_idx[4]; // 454 + uint16_t domoticz_sensor_idx[12]; // 45C + uint8_t module; // 474 + + byte free_475[15]; // 475 + + myio my_gp; // 484 + uint16_t led_pixels; // 496 + uint8_t led_color[5]; // 498 + uint8_t led_table; // 49D + uint8_t led_dimmer; // 49E + + byte free_49F[2]; // 49F + + uint8_t led_fade; // 4A1 + uint8_t led_speed; // 4A2 + uint8_t led_scheme; // 4A3 + uint8_t led_width; // 4A4 + + byte free_4A5[1]; // 4A5 + + uint16_t led_wakeup; // 4A6 + + byte free_4A8[1]; // 4A8 + + char web_password[33]; // 4A9 + uint8_t switchmode[4]; // 4CA + char ntp_server[3][33]; // 4CE + + byte free_531[1]; // 531 + + uint16_t pulsetime[MAX_PULSETIMERS]; // 532 + uint16_t pwmvalue[5]; // 53A + uint32_t ip_address[4]; // 544 + unsigned long hlw_kWhtotal; // 554 + char mqtt_fulltopic[101]; // 558 + + byte free_5BD[3]; // 5BD + + unsigned long pCounter[MAX_COUNTERS]; // 5C0 + uint16_t pCounterType; // 5D0 + uint16_t pCounterDebounce; // 5D2 + uint8_t sfb_code[17][9]; // 5D4 } sysCfg; struct RTCMEM { - uint16_t valid; - byte osw_flag; - uint8_t power; - unsigned long hlw_kWhtoday; - unsigned long hlw_kWhtotal; - unsigned long pCounter[MAX_COUNTERS]; + uint16_t valid; // 000 + byte osw_flag; // 002 + uint8_t unused; // 003 + unsigned long hlw_kWhtoday; // 004 + unsigned long hlw_kWhtotal; // 008 + unsigned long pCounter[MAX_COUNTERS]; // 00C + power_t power; // 01C } rtcMem; // See issue https://github.com/esp8266/Arduino/issues/2913 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 775c5c69538e..eb8ab58a6df2 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -63,14 +63,14 @@ void RTC_Load() RTC_Dump(); #endif // DEBUG_THEO if (rtcMem.valid != RTC_MEM_VALID) { - memset(&rtcMem, 0x00, sizeof(RTCMEM)); + memset(&rtcMem, 0, sizeof(RTCMEM)); rtcMem.valid = RTC_MEM_VALID; - rtcMem.power = sysCfg.power; rtcMem.hlw_kWhtoday = sysCfg.hlw_kWhtoday; rtcMem.hlw_kWhtotal = sysCfg.hlw_kWhtotal; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_COUNTERS; i++) { rtcMem.pCounter[i] = sysCfg.pCounter[i]; } + rtcMem.power = sysCfg.power; RTC_Save(); } _rtcHash = getRtcHash(); @@ -384,6 +384,16 @@ void CFG_DefaultSet2() memset((char*)&sysCfg +16, 0x00, sizeof(SYSCFG) -16); sysCfg.flag.savestate = SAVE_STATE; + //sysCfg.flag.button_restrict = 0; + //sysCfg.flag.value_units = 0; + sysCfg.flag.mqtt_enabled = MQTT_USE; + //sysCfg.flag.mqtt_response = 0; + sysCfg.flag.mqtt_power_retain = MQTT_POWER_RETAIN; + sysCfg.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; + sysCfg.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + + sysCfg.flag.emulation = EMULATION; + sysCfg.savedata = SAVE_DATA; sysCfg.timezone = APP_TIMEZONE; strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl)); @@ -411,10 +421,6 @@ void CFG_DefaultSet2() strlcpy(sysCfg.mqtt_topic, MQTT_TOPIC, sizeof(sysCfg.mqtt_topic)); strlcpy(sysCfg.button_topic, "0", sizeof(sysCfg.button_topic)); strlcpy(sysCfg.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(sysCfg.mqtt_grptopic)); - sysCfg.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; - sysCfg.flag.mqtt_power_retain = MQTT_POWER_RETAIN; -// sysCfg.flag.value_units = 0; -// sysCfg.flag.button_restrict = 0; sysCfg.tele_period = TELE_PERIOD; sysCfg.power = APP_POWER; @@ -463,10 +469,6 @@ void CFG_DefaultSet2() CFG_DefaultSet_3_9_3(); strlcpy(sysCfg.switch_topic, "0", sizeof(sysCfg.switch_topic)); - sysCfg.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.flag.mqtt_enabled = MQTT_USE; - - sysCfg.flag.emulation = EMULATION; strlcpy(sysCfg.web_password, WEB_PASSWORD, sizeof(sysCfg.web_password)); @@ -536,7 +538,7 @@ void CFG_DefaultSet_3_9_3() sysCfg.module = MODULE; for (byte i = 0; i < MAX_GPIO_PIN; i++){ - sysCfg.my_module.gp.io[i] = 0; + sysCfg.my_gp.io[i] = 0; } sysCfg.led_pixels = WS2812_LEDS; @@ -621,8 +623,6 @@ void CFG_Delta() } if (sysCfg.version < 0x03020800) { // 3.2.8 - Add parameter strlcpy(sysCfg.switch_topic, sysCfg.button_topic, sizeof(sysCfg.switch_topic)); - sysCfg.ex_mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.ex_mqtt_enabled = MQTT_USE; } if (sysCfg.version < 0x03020C00) { // 3.2.12 - Add parameter sysCfg.sleep = APP_SLEEP; @@ -630,9 +630,6 @@ void CFG_Delta() if (sysCfg.version < 0x03090300) { // 3.9.2d - Add parameter CFG_DefaultSet_3_9_3(); } - if (sysCfg.version < 0x03090700) { // 3.9.7 - Add parameter - sysCfg.ex_emulation = EMULATION; - } if (sysCfg.version < 0x03091400) { strlcpy(sysCfg.web_password, WEB_PASSWORD, sizeof(sysCfg.web_password)); } @@ -643,8 +640,8 @@ void CFG_Delta() CFG_DefaultSet_4_0_4(); } if (sysCfg.version < 0x04000500) { - memmove(sysCfg.my_module.gp.io, sysCfg.my_module.gp.io +1, MAX_GPIO_PIN -1); // move myio 1 byte to front - sysCfg.my_module.gp.io[MAX_GPIO_PIN -1] = 0; // Clear ADC0 + memmove(sysCfg.my_gp.io, sysCfg.my_gp.io +1, MAX_GPIO_PIN -1); // move myio 1 byte to front + sysCfg.my_gp.io[MAX_GPIO_PIN -1] = 0; // Clear ADC0 } if (sysCfg.version < 0x04000700) { for (byte i = 0; i < 5; i++) { @@ -660,14 +657,14 @@ void CFG_Delta() if (sysCfg.version < 0x05000105) { sysCfg.flag = { 0 }; sysCfg.flag.savestate = SAVE_STATE; - sysCfg.flag.button_restrict = 0; - sysCfg.flag.value_units = 0; - sysCfg.flag.mqtt_enabled = sysCfg.ex_mqtt_enabled; +// sysCfg.flag.button_restrict = 0; +// sysCfg.flag.value_units = 0; + sysCfg.flag.mqtt_enabled = MQTT_USE; // sysCfg.flag.mqtt_response = 0; - sysCfg.flag.mqtt_power_retain = sysCfg.ex_mqtt_power_retain; - sysCfg.flag.mqtt_button_retain = sysCfg.ex_mqtt_button_retain; - sysCfg.flag.mqtt_switch_retain = sysCfg.ex_mqtt_switch_retain; - sysCfg.flag.emulation = sysCfg.ex_emulation; +// sysCfg.flag.mqtt_power_retain = 0; +// sysCfg.flag.mqtt_button_retain = 0; + sysCfg.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + sysCfg.flag.emulation = EMULATION; CFG_DefaultSet_5_0_2(); @@ -692,10 +689,7 @@ void CFG_Delta() } } if (sysCfg.version < 0x05010600) { - if (sysCfg.version > 0x04010100) { - memcpy(sysCfg.state_text, sysCfg.ex_state_text, 33); - } - strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3])); + CFG_DefaultSet_4_1_1(); } if (sysCfg.version < 0x05010700) { sysCfg.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time @@ -712,7 +706,7 @@ void CFG_Delta() if (sysCfg.version < 0x05080000) { uint8_t cfg_wsflg = 0; for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_WS2812 == sysCfg.my_module.gp.io[i]) { + if (GPIO_WS2812 == sysCfg.my_gp.io[i]) { cfg_wsflg = 1; } } @@ -733,6 +727,10 @@ void CFG_Delta() sysCfg.led_width = 1; } } + if (sysCfg.version < 0x0508000A) { + sysCfg.power = sysCfg.ex_power; + sysCfg.altitude = 0; + } sysCfg.version = VERSION; CFG_Save(1); diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h new file mode 100644 index 000000000000..05f5564956e7 --- /dev/null +++ b/sonoff/sonoff.h @@ -0,0 +1,102 @@ +/* + sonoff.h - Sonoff-Tasmota master header + + Copyright (C) 2017 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/*********************************************************************************************\ + * Power Type +\*********************************************************************************************/ + +typedef unsigned long power_t; // Power (Relay) type +#define POWER_MASK 0xFFFFFFFF // Power (Relay) full mask + +/*********************************************************************************************\ + * Defines +\*********************************************************************************************/ + +#define MAX_RELAYS 4 // Max number of relays +#define MAX_BUTTONS 4 // Max number of buttons or keys +#define MAX_SWITCHES 4 // Max number of switches +#define MAX_LEDS 4 // Max number of leds +#define MAX_PWMS 5 // Max number of PWM channels +#define MAX_COUNTERS 4 // Max number of counter sensors +#define MAX_PULSETIMERS 4 // Max number of supported pulse timers + +#define MODULE SONOFF_BASIC // [Module] Select default model + +#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] +#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic + +#define WIFI_HOSTNAME "%s-%04d" // Expands to - + +#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature +#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor) + +#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W +#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V +#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A + +#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection +#define APP_POWER 0 // Default saved power state Off +#define WS2812_MAX_LEDS 512 // Max number of LEDs + +#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256 +//#define PWM_FREQ 1000 // 100..1000 Hz led refresh +//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value) +#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value) + +#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow) +#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power (Pow) +#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power (Pow) +#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power (Pow) +#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow (Pow) + +#define STATES 20 // State loops per second +#define SYSLOG_TIMER 600 // Seconds to restore syslog_level +#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog +#define OTA_ATTEMPTS 10 // Number of times to try fetching the new firmware + +#define INPUT_BUFFER_SIZE 250 // Max number of characters in (serial) command buffer +#define CMDSZ 20 // Max number of characters in command +#define TOPSZ 100 // Max number of characters in topic string +#ifdef USE_MQTT_TLS + #define MAX_LOG_LINES 10 // Max number of lines in weblog +#else + #define MAX_LOG_LINES 20 // Max number of lines in weblog +#endif +#define MAX_BACKLOG 16 // Max number of commands in backlog (chk blogidx and blogptr code) +#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds + +#define APP_BAUDRATE 115200 // Default serial baudrate +#define MAX_STATUS 11 // Max number of status lines + +/*********************************************************************************************\ + * Enumeration +\*********************************************************************************************/ + +enum week_t {Last, First, Second, Third, Fourth}; +enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; +enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; +enum hemis_t {North, South}; +enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; // SerialLog, Syslog, Weblog +enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, MAX_WIFI_OPTION}; // WifiConfig +enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION}; // SwitchMode +enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; // LedState +enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; // Emulation + +enum butt_t {PRESSED, NOT_PRESSED}; +enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCfg.param diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 241c2d79f51d..c88d48f4b203 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,18 +25,9 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05080009 // 5.8.0i - -enum week_t {Last, First, Second, Third, Fourth}; -enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; -enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; -enum hemis_t {North, South}; -enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; // SerialLog, Syslog, Weblog -enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, WIFI_WAIT, MAX_WIFI_OPTION}; // WifiConfig -enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION}; // SwitchMode -enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION}; // LedState -enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; // Emulation +#define VERSION 0x0508000A // 5.8.0j +#include "sonoff.h" #include "user_config.h" #include "user_config_override.h" #include "i18n.h" @@ -46,8 +37,6 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; // Emulation * No user configurable items below \*********************************************************************************************/ -#define MODULE SONOFF_BASIC // [Module] Select default model - #define USE_DHT // Default DHT11 sensor needs no external library #ifndef USE_DS18x20 #define USE_DS18B20 // Default DS18B20 sensor needs no external library @@ -108,56 +97,6 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; // Emulation #define WS2812_LEDS 30 // [Pixels] Number of LEDs #endif -#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] -#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic - -#define WIFI_HOSTNAME "%s-%04d" // Expands to - -#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature -#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor) - -#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W -#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V -#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A - -#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection -#define APP_POWER 0 // Default saved power state Off -#define MAX_COUNTERS 4 // Max number of counter sensors -#define MAX_PULSETIMERS 4 // Max number of supported pulse timers -#define WS2812_MAX_LEDS 512 // Max number of LEDs - -#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256 -//#define PWM_FREQ 1000 // 100..1000 Hz led refresh -//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value) -#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value) - -#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow) -#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power (Pow) -#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power (Pow) -#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power (Pow) -#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow (Pow) - -#define STATES 20 // State loops per second -#define SYSLOG_TIMER 600 // Seconds to restore syslog_level -#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog -#define OTA_ATTEMPTS 10 // Number of times to try fetching the new firmware - -#define INPUT_BUFFER_SIZE 250 // Max number of characters in (serial) command buffer -#define CMDSZ 20 // Max number of characters in command -#define TOPSZ 100 // Max number of characters in topic string -#ifdef USE_MQTT_TLS - #define MAX_LOG_LINES 10 // Max number of lines in weblog -#else - #define MAX_LOG_LINES 20 // Max number of lines in weblog -#endif -#define MAX_BACKLOG 16 // Max number of commands in backlog (chk blogidx and blogptr code) -#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds - -#define APP_BAUDRATE 115200 // Default serial baudrate -#define MAX_STATUS 11 // Max number of status lines - -enum butt_t {PRESSED, NOT_PRESSED}; -enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCfg.param - #include "support.h" // Global support #include // MQTT @@ -244,11 +183,11 @@ int status_update_timer = 0; // Refresh initial status uint16_t pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer uint16_t blink_timer = 0; // Power cycle timer uint16_t blink_counter = 0; // Number of blink cycles -uint8_t blink_power; // Blink power state -uint8_t blink_mask = 0; // Blink relay active mask -uint8_t blink_powersave; // Blink start power save state +power_t blink_power; // Blink power state +power_t blink_mask = 0; // Blink relay active mask +power_t blink_powersave; // Blink start power save state uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command -uint8_t latching_power = 0; // Power state at latching start +power_t latching_power = 0; // Power state at latching start uint8_t latching_relay_pulse = 0; // Latching relay pulse timer uint8_t blogidx = 0; // Command backlog index uint8_t blogptr = 0; // Command backlog pointer @@ -264,7 +203,7 @@ uint8_t interlockmutex = 0; // Interlock power command pending PubSubClient mqttClient(espClient); // MQTT Client WiFiUDP portUDP; // UDP Syslog and Alexa -uint8_t power; // Current copy of sysCfg.power +power_t power = 0; // Current copy of sysCfg.power byte syslog_level; // Current copy of sysCfg.syslog_level uint16_t syslog_timer = 0; // Timer to re-enable syslog_level byte seriallog_level; // Current copy of sysCfg.seriallog_level @@ -275,19 +214,19 @@ uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation int blinks = 201; // Number of LED blinks uint8_t blinkstate = 0; // LED state -uint8_t lastbutton[4] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states -uint8_t holdbutton[4] = { 0 }; // Timer for button hold -uint8_t multiwindow[4] = { 0 }; // Max time between button presses to record press count -uint8_t multipress[4] = { 0 }; // Number of button presses within multiwindow -uint8_t lastwallswitch[4]; // Last wall switch states -uint8_t holdwallswitch[4] = { 0 }; // Timer for wallswitch push button hold uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit +uint8_t lastbutton[MAX_BUTTONS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states +uint8_t holdbutton[MAX_BUTTONS] = { 0 }; // Timer for button hold +uint8_t multiwindow[MAX_BUTTONS] = { 0 }; // Max time between button presses to record press count +uint8_t multipress[MAX_BUTTONS] = { 0 }; // Number of button presses within multiwindow +uint8_t lastwallswitch[MAX_SWITCHES]; // Last wall switch states +uint8_t holdwallswitch[MAX_SWITCHES] = { 0 }; // Timer for wallswitch push button hold mytmplt my_module; // Active copy of GPIOs uint8_t pin[GPIO_MAX]; // Possible pin configurations -uint8_t rel_inverted[4] = { 0 }; // Relay inverted flag (1 = (0 = On, 1 = Off)) -uint8_t led_inverted[4] = { 0 }; // LED inverted flag (1 = (0 = On, 1 = Off)) -uint8_t pwm_inverted[5] = { 0 }; // PWM inverted flag (1 = inverted) +power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) +uint8_t led_inverted = 0; // LED inverted flag (1 = (0 = On, 1 = Off)) +uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted) uint8_t dht_flg = 0; // DHT configured uint8_t hlw_flg = 0; // Power monitor configured uint8_t i2c_flg = 0; // I2C configured @@ -374,7 +313,7 @@ char* getStateText(byte state) /********************************************************************************************/ -void setLatchingRelay(uint8_t power, uint8_t state) +void setLatchingRelay(power_t power, uint8_t state) { power &= 1; if (2 == state) { // Reset relay @@ -387,11 +326,11 @@ void setLatchingRelay(uint8_t power, uint8_t state) latching_relay_pulse = 2; // max 200mS (initiated by stateloop()) } if (pin[GPIO_REL1 +latching_power] < 99) { - digitalWrite(pin[GPIO_REL1 +latching_power], rel_inverted[latching_power] ? !state : state); + digitalWrite(pin[GPIO_REL1 +latching_power], bitRead(rel_inverted, latching_power) ? !state : state); } } -void setRelay(uint8_t rpower) +void setRelay(power_t rpower) { uint8_t state; @@ -400,7 +339,7 @@ void setRelay(uint8_t rpower) rpower = power; } if (sysCfg.flag.interlock) { // Allow only one or no relay set - uint8_t mask = 0x01; + power_t mask = 1; uint8_t count = 0; for (byte i = 0; i < Maxdevice; i++) { if (rpower & mask) { @@ -416,7 +355,7 @@ void setRelay(uint8_t rpower) if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) { Serial.write(0xA0); Serial.write(0x04); - Serial.write(rpower); + Serial.write(rpower &0xFF); Serial.write(0xA1); Serial.write('\n'); Serial.flush(); @@ -431,7 +370,7 @@ void setRelay(uint8_t rpower) for (byte i = 0; i < Maxdevice; i++) { state = rpower &1; if (pin[GPIO_REL1 +i] < 99) { - digitalWrite(pin[GPIO_REL1 +i], rel_inverted[i] ? !state : state); + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); } rpower >>= 1; } @@ -444,7 +383,7 @@ void setLed(uint8_t state) if (state) { state = 1; } - digitalWrite(pin[GPIO_LED1], (led_inverted[0]) ? !state : state); + digitalWrite(pin[GPIO_LED1], (bitRead(led_inverted, 0)) ? !state : state); } /********************************************************************************************/ @@ -628,6 +567,8 @@ void mqtt_reconnect() } else { addLog_P(LOG_LEVEL_DEBUG, S_LOG_MQTT, PSTR(D_INSECURE)); } + espClient.stop(); + yield(); #endif // USE_MQTT_TLS mqttClient.setCallback(mqttDataCb); mqttflag = 1; @@ -820,7 +761,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, if ((payload >= 0) && (payload <= 1)) { strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic)); if (!payload) { - for(i = 1; i <= 4; i++) { + for(i = 1; i <= MAX_SWITCHES; i++) { send_button_power(1, i, 9); // Clear MQTT retain in broker } } @@ -1175,7 +1116,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) sysCfg.module = payload; if (new_modflg) { for (byte i = 0; i < MAX_GPIO_PIN; i++) { - sysCfg.my_module.gp.io[i] = 0; + sysCfg.my_gp.io[i] = 0; } } restartflag = 2; @@ -1207,11 +1148,11 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule)); if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) { for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if ((GPIO_USER == cmodule.gp.io[i]) && (sysCfg.my_module.gp.io[i] == payload)) { - sysCfg.my_module.gp.io[i] = 0; + if ((GPIO_USER == cmodule.gp.io[i]) && (sysCfg.my_gp.io[i] == payload)) { + sysCfg.my_gp.io[i] = 0; } } - sysCfg.my_module.gp.io[index] = payload; + sysCfg.my_gp.io[index] = payload; restartflag = 2; } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); @@ -1222,8 +1163,8 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, "), mqtt_data); } jsflg = 1; - snprintf_P(stemp1, sizeof(stemp1), sensors[sysCfg.my_module.gp.io[i]]); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), mqtt_data, i, sysCfg.my_module.gp.io[i], stemp1); + snprintf_P(stemp1, sizeof(stemp1), sensors[sysCfg.my_gp.io[i]]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), mqtt_data, i, sysCfg.my_gp.io[i], stemp1); } } if (jsflg) { @@ -1251,14 +1192,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } mqtt_data[0] = '\0'; } - else if (!sfl_flg && !strcasecmp_P(type, PSTR(D_CMND_PWM)) && (index > 0) && (index <= 5)) { + else if (!sfl_flg && !strcasecmp_P(type, PSTR(D_CMND_PWM)) && (index > 0) && (index <= MAX_PWMS)) { if ((payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) { sysCfg.pwmvalue[index -1] = payload; - analogWrite(pin[GPIO_PWM1 + index -1], pwm_inverted[index -1] ? PWM_RANGE - payload : payload); + analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? PWM_RANGE - payload : payload); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{")); bool first = true; - for (byte i = 0; i < 5; i++) { + for (byte i = 0; i < MAX_PWMS; i++) { if(pin[GPIO_PWM1 + i] < 99) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ", ", i+1, sysCfg.pwmvalue[i]); first = false; @@ -1428,7 +1369,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_FRIENDLYNAME "%d\":\"%s\"}"), index, sysCfg.friendlyname[index -1]); } - else if (!strcasecmp_P(type, PSTR(D_CMND_SWITCHMODE)) && (index > 0) && (index <= 4)) { + else if (!strcasecmp_P(type, PSTR(D_CMND_SWITCHMODE)) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { sysCfg.switchmode[index -1] = payload; } @@ -1624,7 +1565,7 @@ boolean send_button_power(byte key, byte device, byte state) mqtt_data[0] = '\0'; } else { if ((!strcmp(sysCfg.mqtt_topic, key_topic) || !strcmp(sysCfg.mqtt_grptopic, key_topic)) && (2 == state)) { - state = ~(power >> (device -1)) & 0x01; + state = ~(power >> (device -1)) &1; } snprintf_P(mqtt_data, sizeof(mqtt_data), getStateText(state)); } @@ -1660,17 +1601,19 @@ void do_cmnd_power(byte device, byte state) if ((device < 1) || (device > Maxdevice)) { device = 1; } - byte mask = 0x01 << (device -1); - pulse_timer[(device -1)&3] = 0; + if (device <= MAX_PULSETIMERS) { + pulse_timer[(device -1)] = 0; + } + power_t mask = 1 << (device -1); if (state <= 2) { if ((blink_mask & mask)) { - blink_mask &= (0xFF ^ mask); // Clear device mask + blink_mask &= (POWER_MASK ^ mask); // Clear device mask mqtt_publishPowerBlinkState(device); } if (sysCfg.flag.interlock && !interlockmutex) { // Clear all but masked relay interlockmutex = 1; for (byte i = 0; i < Maxdevice; i++) { - byte imask = 0x01 << i; + power_t imask = 1 << i; if ((power & imask) && (mask != imask)) { do_cmnd_power(i +1, 0); } @@ -1679,7 +1622,7 @@ void do_cmnd_power(byte device, byte state) } switch (state) { case 0: { // Off - power &= (0xFF ^ mask); + power &= (POWER_MASK ^ mask); break; } case 1: // On power |= mask; @@ -1691,11 +1634,13 @@ void do_cmnd_power(byte device, byte state) #ifdef USE_DOMOTICZ domoticz_updatePowerState(device); #endif // USE_DOMOTICZ - pulse_timer[(device -1)&3] = (power & mask) ? sysCfg.pulsetime[(device -1)&3] : 0; + if (device <= MAX_PULSETIMERS) { + pulse_timer[(device -1)] = (power & mask) ? sysCfg.pulsetime[(device -1)] : 0; + } } else if (3 == state) { // Blink if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (0xFF ^ mask)) | (power & mask); // Save state + blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); // Save state blink_power = (power >> (device -1))&1; // Prep to Toggle } blink_timer = 1; @@ -1706,7 +1651,7 @@ void do_cmnd_power(byte device, byte state) } else if (4 == state) { // No Blink byte flag = (blink_mask & mask); - blink_mask &= (0xFF ^ mask); // Clear device mask + blink_mask &= (POWER_MASK ^ mask); // Clear device mask mqtt_publishPowerBlinkState(device); if (flag) { do_cmnd_power(device, (blink_powersave >> (device -1))&1); // Restore state @@ -1720,12 +1665,12 @@ void do_cmnd_power(byte device, byte state) void stop_all_power_blink() { - byte mask; + power_t mask; for (byte i = 1; i <= Maxdevice; i++) { - mask = 0x01 << (i -1); + mask = 1 << (i -1); if (blink_mask & mask) { - blink_mask &= (0xFF ^ mask); // Clear device mask + blink_mask &= (POWER_MASK ^ mask); // Clear device mask mqtt_publishPowerBlinkState(i); do_cmnd_power(i, (blink_powersave >> (i -1))&1); // Restore state } @@ -2181,7 +2126,7 @@ void switch_handler() uint8_t button = NOT_PRESSED; uint8_t switchflag; - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { if (holdwallswitch[i]) { @@ -2196,13 +2141,13 @@ void switch_handler() switchflag = 3; switch (sysCfg.switchmode[i]) { case TOGGLE: - switchflag = 2; // Toggle + switchflag = 2; // Toggle break; case FOLLOW: - switchflag = button & 0x01; // Follow wall switch state + switchflag = button &1; // Follow wall switch state break; case FOLLOW_INV: - switchflag = ~button & 0x01; // Follow inverted wall switch state + switchflag = ~button &1; // Follow inverted wall switch state break; case PUSHBUTTON: if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) { @@ -2252,7 +2197,7 @@ void switch_handler() void stateloop() { - uint8_t power_now; + power_t power_now; timerxs = millis() + (1000 / STATES); state++; @@ -2301,7 +2246,7 @@ void stateloop() stop_all_power_blink(); } else { blink_power ^= 1; - power_now = (power & (0xFF ^ blink_mask)) | ((blink_power) ? blink_mask : 0); + power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); setRelay(power_now); } } @@ -2365,7 +2310,7 @@ void stateloop() } } } else { - if (sysCfg.ledstate &0x01) { + if (sysCfg.ledstate &1) { boolean tstate = power; if ((SONOFF_TOUCH == sysCfg.module) || (SONOFF_T11 == sysCfg.module) || (SONOFF_T12 == sysCfg.module) || (SONOFF_T13 == sysCfg.module)) { tstate = (!power) ? 1 : 0; @@ -2427,7 +2372,7 @@ void stateloop() savedatacounter--; if (savedatacounter <= 0) { if (sysCfg.flag.savestate) { - byte mask = 0xFF; + power_t mask = POWER_MASK; for (byte i = 0; i < MAX_PULSETIMERS; i++) { if ((sysCfg.pulsetime[i] > 0) && (sysCfg.pulsetime[i] < 30)) { mask &= ~(1 << i); @@ -2587,11 +2532,10 @@ void GPIO_init() } memcpy_P(&def_module, &modules[sysCfg.module], sizeof(def_module)); -// sysCfg.my_module.flag = def_module.flag; strlcpy(my_module.name, def_module.name, sizeof(my_module.name)); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (sysCfg.my_module.gp.io[i] > GPIO_NONE) { - my_module.gp.io[i] = sysCfg.my_module.gp.io[i]; + if (sysCfg.my_gp.io[i] > GPIO_NONE) { + my_module.gp.io[i] = sysCfg.my_gp.io[i]; } if ((def_module.gp.io[i] > GPIO_NONE) && (def_module.gp.io[i] < GPIO_USER)) { my_module.gp.io[i] = def_module.gp.io[i]; @@ -2608,16 +2552,16 @@ void GPIO_init() // addLog(LOG_LEVEL_DEBUG); if (mpin) { - if ((mpin >= GPIO_REL1_INV) && (mpin <= GPIO_REL4_INV)) { - rel_inverted[mpin - GPIO_REL1_INV] = 1; + if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { + bitSet(rel_inverted, mpin - GPIO_REL1_INV); mpin -= (GPIO_REL1_INV - GPIO_REL1); } - else if ((mpin >= GPIO_LED1_INV) && (mpin <= GPIO_LED4_INV)) { - led_inverted[mpin - GPIO_LED1_INV] = 1; + else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { + bitSet(led_inverted, mpin - GPIO_LED1_INV); mpin -= (GPIO_LED1_INV - GPIO_LED1); } - else if ((mpin >= GPIO_PWM1_INV) && (mpin <= GPIO_PWM5_INV)) { - pwm_inverted[mpin - GPIO_PWM1_INV] = 1; + else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { + bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); mpin -= (GPIO_PWM1_INV - GPIO_PWM1); } #ifdef USE_DHT @@ -2643,10 +2587,17 @@ void GPIO_init() analogWriteRange(PWM_RANGE); // Default is 1023 (Arduino.h) analogWriteFreq(PWM_FREQ); // Default is 1000 (core_esp8266_wiring_pwm.c) +#ifdef USE_I2C + i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); + if (i2c_flg) { + Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); + } +#endif // USE_I2C + Maxdevice = 1; if (sysCfg.flag.pwm_control) { sfl_flg = 0; - for (byte i = 0; i < 5; i++) { + for (byte i = 0; i < MAX_PWMS; i++) { if (pin[GPIO_PWM1 +i] < 99) { sfl_flg++; // Use Dimmer/Color control for all PWM as SetOption15 = 1 } @@ -2688,7 +2639,7 @@ void GPIO_init() if (!sfl_flg) { Maxdevice = 0; } - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_RELAYS; i++) { if (pin[GPIO_REL1 +i] < 99) { pinMode(pin[GPIO_REL1 +i], OUTPUT); Maxdevice++; @@ -2698,14 +2649,18 @@ void GPIO_init() // } } } - for (byte i = 0; i < 4; i++) { + for (byte i = 0; i < MAX_BUTTONS; i++) { if (pin[GPIO_KEY1 +i] < 99) { pinMode(pin[GPIO_KEY1 +i], (16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP); } + } + for (byte i = 0; i < MAX_LEDS; i++) { if (pin[GPIO_LED1 +i] < 99) { pinMode(pin[GPIO_LED1 +i], OUTPUT); - digitalWrite(pin[GPIO_LED1 +i], led_inverted[i]); + digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); } + } + for (byte i = 0; i < MAX_SWITCHES; i++) { if (pin[GPIO_SWT1 +i] < 99) { pinMode(pin[GPIO_SWT1 +i], (16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 :INPUT_PULLUP); lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check @@ -2721,10 +2676,10 @@ void GPIO_init() if (sfl_flg) { // Any Led light under Dimmer/Color control sl_init(); } else { - for (byte i = 0; i < 5; i++) { + for (byte i = 0; i < MAX_PWMS; i++) { if (pin[GPIO_PWM1 +i] < 99) { pinMode(pin[GPIO_PWM1 +i], OUTPUT); - analogWrite(pin[GPIO_PWM1 +i], pwm_inverted[i] ? PWM_RANGE - sysCfg.pwmvalue[i] : sysCfg.pwmvalue[i]); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? PWM_RANGE - sysCfg.pwmvalue[i] : sysCfg.pwmvalue[i]); } } } @@ -2764,13 +2719,6 @@ void GPIO_init() ds18x20_init(); } #endif // USE_DS18x20 - -#ifdef USE_I2C - i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) { - Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); - } -#endif // USE_I2C } extern "C" { @@ -2852,7 +2800,7 @@ void setup() setRelay(power); break; case 2: // All saved state toggle - power = sysCfg.power & ((1 << Maxdevice) -1) ^ 0xFF; + power = sysCfg.power & ((1 << Maxdevice) -1) ^ POWER_MASK; if (sysCfg.flag.savestate) { setRelay(power); } @@ -2874,7 +2822,7 @@ void setup() // Issue #526 for (byte i = 0; i < Maxdevice; i++) { - if ((pin[GPIO_REL1 +i] < 99) && (digitalRead(pin[GPIO_REL1 +i]) ^ rel_inverted[i])) { + if ((pin[GPIO_REL1 +i] < 99) && (digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i))) { bitSet(power, i); pulse_timer[i] = sysCfg.pulsetime[i]; } diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index a2b66caaf090..9d4304cf1826 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -1058,12 +1058,12 @@ void handleSave() String gpios = ""; for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (new_modflg) { - sysCfg.my_module.gp.io[i] = 0; + sysCfg.my_gp.io[i] = 0; } else { if (GPIO_USER == cmodule.gp.io[i]) { snprintf_P(stemp, sizeof(stemp), PSTR("g%d"), i); - sysCfg.my_module.gp.io[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(sysCfg.my_module.gp.io[i]); + sysCfg.my_gp.io[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str()); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(sysCfg.my_gp.io[i]); } } } diff --git a/sonoff/xdrv_domoticz.ino b/sonoff/xdrv_domoticz.ino index bcf330861f51..b791cc09e192 100644 --- a/sonoff/xdrv_domoticz.ino +++ b/sonoff/xdrv_domoticz.ino @@ -70,12 +70,12 @@ void mqtt_publishDomoticzPowerState(byte device) } if (sysCfg.flag.mqtt_enabled && sysCfg.domoticz_relay_idx[device -1]) { if (sfl_flg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":2,\"svalue\":\"%d\"}"), - sysCfg.domoticz_relay_idx[device -1], sysCfg.led_dimmer); - mqtt_publish(domoticz_in_topic); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%d\"}"), + sysCfg.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, sysCfg.led_dimmer); + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"\"}"), + sysCfg.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"\"}"), - sysCfg.domoticz_relay_idx[device -1], (power & (0x01 << (device -1))) ? 1 : 0); mqtt_publish(domoticz_in_topic); } } @@ -175,8 +175,7 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); if (2 == nvalue) { nvalue = domoticz["svalue1"]; -// if (sfl_flg && (sysCfg.led_dimmer == nvalue) && ((power >> i) &1)) { // Unable to power off using webpage due to Domoticz re-sends dimmer state - if (sfl_flg && (sysCfg.led_dimmer == nvalue)) { + if (sfl_flg && (sysCfg.led_dimmer == nvalue) && ((power >> i) &1)) { return 1; } snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_DIMMER)); diff --git a/sonoff/xdrv_ir_send.ino b/sonoff/xdrv_ir_send.ino index 1827b291fb71..282552b9ee5d 100644 --- a/sonoff/xdrv_ir_send.ino +++ b/sonoff/xdrv_ir_send.ino @@ -114,8 +114,8 @@ void ir_recv_check() mqtt_publish_topic_P(6, PSTR(D_IRRECEIVED)); #ifdef USE_DOMOTICZ unsigned long value = results.value | (diridx << 28); // [Protocol:4, Data:28] - domoticz_sensor(DZ_COUNT, value); // Send data as Domoticz Counter value -#endif // USE_DOMOTICZ + domoticz_sensor(DZ_COUNT, value); // Send data as Domoticz Counter value +#endif // USE_DOMOTICZ } irrecv->resume(); diff --git a/sonoff/xdrv_snfbridge.ino b/sonoff/xdrv_snfbridge.ino index 70fdb008dada..58d643137c6a 100644 --- a/sonoff/xdrv_snfbridge.ino +++ b/sonoff/xdrv_snfbridge.ino @@ -135,7 +135,7 @@ void sb_send(uint8_t idx, uint8_t key) Serial.write(sysCfg.sfb_code[idx][i]); } if (0 == idx) { - code = (0x10 << (key >> 2)) | (0x01 << (key & 3)); // 11,12,14,18,21,22,24,28,41,42,44,48,81,82,84,88 + code = (0x10 << (key >> 2)) | (1 << (key & 3)); // 11,12,14,18,21,22,24,28,41,42,44,48,81,82,84,88 } else { code = sysCfg.sfb_code[idx][8]; } diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index dcd8be6a5f4f..baf41c9c483c 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -317,9 +317,9 @@ void sl_prepPower() } } -void sl_setPower(uint8_t mpower) +void sl_setPower(power_t mpower) { - sl_power = ((mpower & (0x01 << (Maxdevice -1))) != 0); + sl_power = ((mpower & (1 << (Maxdevice -1))) != 0); if (sl_wakeupActive) { sl_wakeupActive--; } @@ -416,7 +416,7 @@ void sl_animate() uint16_t curcol = cur_col[i] * (PWM_RANGE / 255); // snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "Cur_Col%d %d, CurCol %d"), i, cur_col[i], curcol); // addLog(LOG_LEVEL_DEBUG); - analogWrite(pin[GPIO_PWM1 +i], pwm_inverted[i] ? PWM_RANGE - curcol : curcol); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? PWM_RANGE - curcol : curcol); } } } diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 140303c5e3dc..b8a86ce84f67 100755 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -460,7 +460,7 @@ void hue_config(String *path) void hue_light_status(byte device, String *response) { *response += FPSTR(HUE_LIGHT_STATUS_JSON); - response->replace("{state}", (power & (0x01 << (device-1))) ? "true" : "false"); + response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); if (sfl_flg) { sl_replaceHSB(response); @@ -566,7 +566,7 @@ void hue_lights(String *path) case true : do_cmnd_power(device, 1); response.replace("{res}", "true"); break; - default : response.replace("{res}", (power & (0x01 << (device-1))) ? "true" : "false"); + default : response.replace("{res}", (power & (1 << (device-1))) ? "true" : "false"); break; } resp = true; diff --git a/sonoff/xsns_bmp.ino b/sonoff/xsns_bmp.ino index e1bcd7ac81e1..e86a980dda65 100644 --- a/sonoff/xsns_bmp.ino +++ b/sonoff/xsns_bmp.ino @@ -404,6 +404,7 @@ double bmp_readPressure(void) switch (bmptype) { case BMP180_CHIPID: pressure = bmp180_readPressure(); + break; case BMP280_CHIPID: case BME280_CHIPID: pressure = bmp280_readPressure(); diff --git a/sonoff/xsns_ds18b20.ino b/sonoff/xsns_ds18b20.ino index f859ce743b5a..c5cfc55d2578 100644 --- a/sonoff/xsns_ds18b20.ino +++ b/sonoff/xsns_ds18b20.ino @@ -68,7 +68,7 @@ uint8_t dsb_read(void) uint8_t bitMask; uint8_t r = 0; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { + for (bitMask = 1; bitMask; bitMask <<= 1) { if (dsb_read_bit()) { r |= bitMask; } @@ -97,7 +97,7 @@ void dsb_write(uint8_t ByteToWrite) { uint8_t bitMask; - for (bitMask = 0x01; bitMask; bitMask <<= 1) { + for (bitMask = 1; bitMask; bitMask <<= 1) { dsb_write_bit((bitMask & ByteToWrite) ? 1 : 0); } }