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)
This commit is contained in:
arendst 2017-10-10 15:40:02 +02:00
parent b7a5b8c358
commit ca431184e6
14 changed files with 379 additions and 328 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.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

View File

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

View File

@ -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;
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
int8_t timezone;
char otaUrl[101];
byte free_09D[1]; // 09D
char mqtt_prefix[3][11]; // was ex_friendlyname[33] until 3.2.5
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 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;
byte free_1A7[1]; // 1A7
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;
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
uint8_t power;
uint8_t ledstate;
byte free_2E6[2]; // 2E6
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
power_t power; // 2E8
uint16_t domoticz_update_timer;
unsigned long domoticz_relay_idx[4];
unsigned long domoticz_key_idx[4];
byte free_2EC[10]; // 2EC
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
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
// 3.0.6
uint16_t mqtt_retry; // was ex_pulsetime until 4.0.4
byte free_33F[1]; // 33F
// 3.1.1
uint8_t poweronstate;
uint16_t domoticz_update_timer; // 340
// 3.1.6
uint16_t blinktime;
uint16_t blinkcount;
byte free_342[2]; // 342
// 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;
unsigned long domoticz_relay_idx[4]; // 344
unsigned long domoticz_key_idx[4]; // 354
// 3.2.5
char friendlyname[4][33];
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
// 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
byte free_399[1]; // 399
// 3.2.12
uint8_t sleep;
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
// 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;
byte free_3A9[1]; // 3A9
// 3.9.7
uint8_t ex_emulation; // Not used since 5.0.2
uint16_t ws_wakeup; // 3AA Not used since 5.8.0
char friendlyname[4][33]; // 3AC
char switch_topic[33]; // 430
// 3.9.20
char web_password[33];
byte free_451[2]; // 451
// 3.9.21
uint8_t switchmode[4];
uint8_t sleep; // 453
uint16_t domoticz_switch_idx[4]; // 454
uint16_t domoticz_sensor_idx[12]; // 45C
uint8_t module; // 474
// 4.0.4
char ntp_server[3][33];
uint16_t pulsetime[MAX_PULSETIMERS];
byte free_475[15]; // 475
// 4.0.7
uint16_t pwmvalue[5];
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
// 4.0.9
uint32_t ip_address[4];
byte free_49F[2]; // 49F
// 5.0.4
unsigned long hlw_kWhtotal;
uint8_t led_fade; // 4A1
uint8_t led_speed; // 4A2
uint8_t led_scheme; // 4A3
uint8_t led_width; // 4A4
// 5.0.4a
char mqtt_fulltopic[101];
byte free_4A5[1]; // 4A5
// 5.1.1
unsigned long pCounter[MAX_COUNTERS];
uint16_t pCounterType;
uint16_t pCounterDebounce;
uint16_t led_wakeup; // 4A6
// 5.4.1
uint8_t sfb_code[17][9];
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

View File

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

102
sonoff/sonoff.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************************\
* 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 <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
#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

View File

@ -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 <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
#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 <PubSubClient.h> // 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];
}

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

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

View File

@ -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();

View File

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