From d7afc664f5b78769849484d2c229959790a649cd Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Mon, 14 May 2018 23:22:29 +0200 Subject: [PATCH] Add user entry DST/STD 5.13.1c * Add user entry DST/STD using commands TimeStd and TimeDst with options like 0,0,3,1,2,120 (#2721) --- README.md | 2 +- sonoff/_releasenotes.ino | 4 ++-- sonoff/i18n.h | 2 ++ sonoff/settings.h | 16 +++++++++------ sonoff/settings.ino | 42 +++++++++++++++++++++++++--------------- sonoff/sonoff.ino | 41 ++++++++++++++++++++++++++++++++++++--- sonoff/support.ino | 13 +++++++------ 7 files changed, 86 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 303fb872e..8c55a841e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! ### Development [![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota) -Current version is **5.13.1b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.13.1c** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### Quick install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index fc814d10a..77bc9575d 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,5 @@ -/* 5.13.1b - * Prep for user entry DST/STD (#2721) +/* 5.13.1c + * Add user entry DST/STD using commands TimeStd and TimeDst with options like 0,0,3,1,2,120 (#2721) * * 5.13.1a * Change user_config.h otaurl to http://sonoff.maddox.co.uk/tasmota/sonoff.bin (#2588, #2602) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index d0926e4c7..365fee826 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -227,6 +227,8 @@ #define D_JSON_RESET_AND_RESTARTING "Reset and Restarting" #define D_JSON_ONE_TO_RESET "1 to reset" #define D_CMND_TIMEZONE "Timezone" +#define D_CMND_TIMESTD "TimeStd" +#define D_CMND_TIMEDST "TimeDst" #define D_CMND_ALTITUDE "Altitude" #define D_CMND_LEDPOWER "LedPower" #define D_CMND_LEDSTATE "LedState" diff --git a/sonoff/settings.h b/sonoff/settings.h index 6dfc4cdeb..ec156c85a 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -20,7 +20,7 @@ #ifndef _SETTINGS_H_ #define _SETTINGS_H_ -#define PARAM8_SIZE 23 // Number of param bytes +#define PARAM8_SIZE 18 // Number of param bytes typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull... uint32_t data; // Allow bit manipulation using SetOption @@ -159,8 +159,7 @@ struct SYSCFG { uint8_t display_address[8]; // 2D8 uint8_t display_dimmer; // 2E0 uint8_t display_size; // 2E1 - TimeRule std_flags; // 2E2 - int16_t std_offset; // 2E4 offset from UTC in minutes + TimeRule tflag[2]; // 2E2 uint16_t pwm_frequency; // 2E6 power_t power; // 2E8 uint16_t pwm_value[MAX_PWMS]; // 2EC @@ -169,6 +168,10 @@ struct SYSCFG { 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 + int16_t toffset[2]; // 30E + + byte free_312[1]; // 312 + char state_text[4][11]; // 313 uint8_t energy_power_delta; // 33F uint16_t domoticz_update_timer; // 340 @@ -244,7 +247,9 @@ struct SYSCFG { char ntp_server[3][33]; // 4CE byte ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 - TimeRule dst_flags; // 542 + + byte free_542[2]; // 542 + uint32_t ip_address[4]; // 544 unsigned long energy_kWhtotal; // 554 char mqtt_fulltopic[100]; // 558 @@ -254,9 +259,8 @@ struct SYSCFG { uint16_t pulse_counter_debounce; // 5D2 uint8_t rf_code[17][9]; // 5D4 - byte free_66d[1]; // 66D + byte free_66d[3]; // 66D - int16_t dst_offset; // 66E Timer timer[MAX_TIMERS]; // 670 int latitude; // 6B0 int longitude; // 6B4 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 78a48e657..2d3f3c3d8 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -522,7 +522,7 @@ void SettingsDefaultSet2() Settings.latitude = (int)((double)LATITUDE * 1000000); Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsDefaultSet_5_13_1a(); + SettingsDefaultSet_5_13_1c(); } /********************************************************************************************/ @@ -654,20 +654,30 @@ void SettingsDefaultSet_5_10_1() Settings.display_size = 1; } -void SettingsDefaultSet_5_13_1a() +void SettingsResetStd() { - Settings.dst_flags.hemis = TIME_DST_HEMISPHERE; - Settings.dst_flags.week = TIME_DST_WEEK; - Settings.dst_flags.dow = TIME_DST_DAY; - Settings.dst_flags.month = TIME_DST_MONTH; - Settings.dst_flags.hour = TIME_DST_HOUR; - Settings.dst_offset = TIME_DST_OFFSET; - Settings.std_flags.hemis = TIME_STD_HEMISPHERE; - Settings.std_flags.week = TIME_STD_WEEK; - Settings.std_flags.dow = TIME_STD_DAY; - Settings.std_flags.month = TIME_STD_MONTH; - Settings.std_flags.hour = TIME_STD_HOUR; - Settings.std_offset = TIME_STD_OFFSET; + Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; + Settings.tflag[0].week = TIME_STD_WEEK; + Settings.tflag[0].dow = TIME_STD_DAY; + Settings.tflag[0].month = TIME_STD_MONTH; + Settings.tflag[0].hour = TIME_STD_HOUR; + Settings.toffset[0] = TIME_STD_OFFSET; +} + +void SettingsResetDst() +{ + Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; + Settings.tflag[1].week = TIME_DST_WEEK; + Settings.tflag[1].dow = TIME_DST_DAY; + Settings.tflag[1].month = TIME_DST_MONTH; + Settings.tflag[1].hour = TIME_DST_HOUR; + Settings.toffset[1] = TIME_DST_OFFSET; +} + +void SettingsDefaultSet_5_13_1c() +{ + SettingsResetStd(); + SettingsResetDst(); } /********************************************************************************************/ @@ -874,8 +884,8 @@ void SettingsDelta() Settings.energy_kWhyesterday /= 1000; RtcSettings.energy_kWhtoday /= 1000; } - if (Settings.version < 0x050D0102) { - SettingsDefaultSet_5_13_1a(); + if (Settings.version < 0x050D0103) { + SettingsDefaultSet_5_13_1c(); } Settings.version = VERSION; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 858ff8579..7d41205b7 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x050D0102 // 5.13.1b +#define VERSION 0x050D0103 // 5.13.1c // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) @@ -83,7 +83,7 @@ enum TasmotaCommands { CMND_COUNTERDEBOUNCE, CMND_SLEEP, CMND_UPGRADE, CMND_UPLOAD, CMND_OTAURL, CMND_SERIALLOG, CMND_SYSLOG, CMND_LOGHOST, CMND_LOGPORT, CMND_IPADDRESS, CMND_NTPSERVER, CMND_AP, CMND_SSID, CMND_PASSWORD, CMND_HOSTNAME, CMND_WIFICONFIG, CMND_FRIENDLYNAME, CMND_SWITCHMODE, CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_EMULATION, - CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, + CMND_TELEPERIOD, CMND_RESTART, CMND_RESET, CMND_TIMEZONE, CMND_TIMESTD, CMND_TIMEDST, CMND_ALTITUDE, CMND_LEDPOWER, CMND_LEDSTATE, CMND_I2CSCAN, CMND_SERIALSEND, CMND_BAUDRATE, CMND_SERIALDELIMITER }; const char kTasmotaCommands[] PROGMEM = D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" @@ -93,7 +93,7 @@ const char kTasmotaCommands[] PROGMEM = D_CMND_COUNTERDEBOUNCE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" D_CMND_SERIALLOG "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_EMULATION "|" - D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" + D_CMND_TELEPERIOD "|" D_CMND_RESTART "|" D_CMND_RESET "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER; // Global variables @@ -177,6 +177,7 @@ uint8_t light_type = 0; // Light types bool pwm_present = false; // Any PWM channel configured with SetOption15 0 boolean mdns_begun = false; unsigned long features = 0UL; +uint8_t ntp_force_sync = 0; // Force NTP sync char my_version[33]; // Composed version string char my_hostname[33]; // Composed Wifi hostname @@ -1046,6 +1047,40 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) if ((data_len > 0) && (((payload >= -13) && (payload <= 14)) || (99 == payload))) Settings.timezone = payload; snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.timezone); } + else if ((CMND_TIMESTD == command_code) || (CMND_TIMEDST == command_code)) { + // TimeStd 0/1, 0/1/2/3/4, 1..12, 1..7, 0..23, +/-780 + uint8_t ts = 0; + if (CMND_TIMEDST == command_code) { ts = 1; } + if (data_len > 0) { + if (strstr(dataBuf, ",")) { // Parameter entry + uint8_t tpos = 0; + int value = strtol(dataBuf, &p, 10); + while (p && (tpos < 7)) { + tpos++; + if (1 == tpos) { Settings.tflag[ts].hemis = value &1; } + if (2 == tpos) { Settings.tflag[ts].week = (value < 0) ? 0 : (value > 4) ? 4 : value; } + if (3 == tpos) { Settings.tflag[ts].month = (value < 1) ? 1 : (value > 12) ? 12 : value; } + if (4 == tpos) { Settings.tflag[ts].dow = (value < 1) ? 1 : (value > 7) ? 7 : value; } + if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } + if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } + p++; // Skip comma + value = strtol(p, &p, 10); + } + ntp_force_sync = 1; + } else { + if (0 == payload) { + if (0 == ts) { + SettingsResetStd(); + } else { + SettingsResetDst(); + } + } + ntp_force_sync = 1; + } + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d\"}}"), + command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); + } else if (CMND_ALTITUDE == command_code) { if ((data_len > 0) && ((payload >= -30000) && (payload <= 30000))) Settings.altitude = payload; snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.altitude); diff --git a/sonoff/support.ino b/sonoff/support.ino index 9564f83aa..10f347a9d 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1357,9 +1357,10 @@ void RtcSecond() if ((ntp_sync_minute > 59) && (RtcTime.minute > 2)) ntp_sync_minute = 1; // If sync prepare for a new cycle uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id - if ((WL_CONNECTED == WiFi.status()) && (offset == RtcTime.second) && ((RtcTime.year < 2016) || (ntp_sync_minute == RtcTime.minute))) { + if ((WL_CONNECTED == WiFi.status()) && (offset == RtcTime.second) && ((RtcTime.year < 2016) || (ntp_sync_minute == RtcTime.minute) || ntp_force_sync)) { ntp_time = sntp_get_current_timestamp(); if (ntp_time > 1451602800) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) + ntp_force_sync = 0; utc_time = ntp_time; ntp_sync_minute = 60; // Sync so block further requests if (restart_time == 0) { @@ -1367,8 +1368,8 @@ void RtcSecond() } BreakTime(utc_time, tmpTime); RtcTime.year = tmpTime.year + 1970; - daylight_saving_time = RuleToTime(Settings.dst_flags, RtcTime.year); - standard_time = RuleToTime(Settings.std_flags, RtcTime.year); + daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); AddLog(LOG_LEVEL_DEBUG); @@ -1389,9 +1390,9 @@ void RtcSecond() if (local_time > 1451602800) { // 2016-01-01 int32_t time_offset = Settings.timezone * SECS_PER_HOUR; if (99 == Settings.timezone) { - dstoffset = Settings.dst_offset * SECS_PER_MIN; - stdoffset = Settings.std_offset * SECS_PER_MIN; - if (Settings.dst_flags.hemis) { + dstoffset = Settings.toffset[1] * SECS_PER_MIN; + stdoffset = Settings.toffset[0] * SECS_PER_MIN; + if (Settings.tflag[1].hemis) { // Southern hemisphere if ((utc_time >= (standard_time - dstoffset)) && (utc_time < (daylight_saving_time - stdoffset))) { time_offset = stdoffset; // Standard Time