2020-05-23 12:09:16 +01:00
/*
2019-10-27 11:04:08 +00:00
tasmota . ino - Tasmota firmware for iTead Sonoff , Wemos and NodeMCU hardware
2017-05-13 12:02:10 +01:00
2019-12-31 13:23:34 +00:00
Copyright ( C ) 2020 Theo Arends
2017-05-13 12:02:10 +01:00
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/>.
*/
2017-07-15 14:07:30 +01:00
2020-07-16 17:21:19 +01:00
/*********************************************************************************************\
* Preferred IDE is Visual Studio Code with PlatformIO extension which doesn ' t need prerequisites
*
* Limited support for Arduino IDE needs Prerequisites :
* - Change libraries / PubSubClient / src / PubSubClient . h
* # define MQTT_MAX_PACKET_SIZE 1200
*
* Arduino IDE 1.8 .12 and up parameters for partly support
* - Select IDE Tools - Board : " Generic ESP8266 Module "
* - Select IDE Tools - Flash Mode : " DOUT (compatible) "
* - Select IDE Tools - Flash Size : " 1M (FS:none OTA:~502KB) "
* - Select IDE Tools - LwIP Variant : " v2 Higher Bandwidth (no feature) "
* - Select IDE Tools - VTables : " Flash "
* - Select IDE Tools - Espressif FW : " nonos-sdk-2.2.1+100 (190703) "
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
// Location specific includes
2020-07-17 10:49:56 +01:00
# include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_7_1)
2020-04-10 17:24:08 +01:00
# include "tasmota_compat.h"
2019-10-27 11:04:08 +00:00
# include "tasmota_version.h" // Tasmota version information
# include "tasmota.h" // Enumeration used in my_user_config.h
2018-10-23 14:51:51 +01:00
# include "my_user_config.h" // Fixed user configurable options
2020-06-10 19:14:46 +01:00
# ifdef USE_TLS
2020-04-10 09:52:22 +01:00
# include <t_bearssl.h> // We need to include before "tasmota_globals.h" to take precedence over the BearSSL version in Arduino
2020-06-10 19:14:46 +01:00
# endif // USE_TLS
2020-04-09 14:32:23 +01:00
# include "tasmota_globals.h" // Function prototypes and global configuration
2018-10-23 14:51:51 +01:00
# include "i18n.h" // Language support configured by my_user_config.h
2019-10-27 11:04:08 +00:00
# include "tasmota_template.h" // Hardware configuration
2017-03-03 11:35:23 +00:00
2018-02-27 13:59:46 +00:00
// Libraries
2018-11-20 14:00:24 +00:00
# include <ESP8266HTTPClient.h> // Ota
2017-01-28 13:41:01 +00:00
# include <ESP8266httpUpdate.h> // Ota
2017-06-04 16:40:27 +01:00
# include <StreamString.h> // Webserver, Updater
2020-09-24 07:51:43 +01:00
# include <JsonParser.h>
# include <JsonGenerator.h>
2018-03-21 16:58:39 +00:00
# ifdef USE_ARDUINO_OTA
# include <ArduinoOTA.h> // Arduino OTA
# ifndef USE_DISCOVERY
# define USE_DISCOVERY
# endif
# endif // USE_ARDUINO_OTA
2017-01-28 13:41:01 +00:00
# ifdef USE_DISCOVERY
2018-03-21 16:58:39 +00:00
# include <ESP8266mDNS.h> // MQTT, Webserver, Arduino OTA
2017-01-28 13:41:01 +00:00
# endif // USE_DISCOVERY
2020-09-03 19:31:31 +01:00
//#ifdef USE_I2C
2017-01-28 13:41:01 +00:00
# include <Wire.h> // I2C support library
2020-09-03 19:31:31 +01:00
//#endif // USE_I2C
2017-07-15 14:07:30 +01:00
# ifdef USE_SPI
2017-05-10 13:19:36 +01:00
# include <SPI.h> // SPI support, TFT
2017-04-29 13:40:53 +01:00
# endif // USE_SPI
2019-02-17 09:42:55 +00:00
2017-10-18 17:22:34 +01:00
// Structs
2017-02-19 16:49:17 +00:00
# include "settings.h"
2017-01-28 13:41:01 +00:00
2019-12-02 09:44:27 +00:00
/*********************************************************************************************\
* Global variables
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-08-27 15:07:23 +01:00
WiFiUDP PortUdp ; // UDP Syslog and Alexa
2018-05-17 14:36:45 +01:00
unsigned long feature_drv1 ; // Compiled driver feature map
unsigned long feature_drv2 ; // Compiled driver feature map
unsigned long feature_sns1 ; // Compiled sensor feature map
unsigned long feature_sns2 ; // Compiled sensor feature map
2019-08-07 11:56:32 +01:00
unsigned long feature5 ; // Compiled feature map
2020-02-10 14:18:11 +00:00
unsigned long feature6 ; // Compiled feature map
2020-08-17 15:25:24 +01:00
unsigned long feature7 ; // Compiled feature map
2018-08-27 11:01:20 +01:00
unsigned long serial_polling_window = 0 ; // Serial polling window
unsigned long state_second = 0 ; // State second timer
unsigned long state_50msecond = 0 ; // State 50msecond timer
unsigned long state_100msecond = 0 ; // State 100msecond timer
unsigned long state_250msecond = 0 ; // State 250msecond timer
unsigned long pulse_timer [ MAX_PULSETIMERS ] = { 0 } ; // Power off timer
unsigned long blink_timer = 0 ; // Power cycle timer
unsigned long backlog_delay = 0 ; // Command backlog delay
power_t power = 0 ; // Current copy of Settings.power
2019-09-04 11:20:04 +01:00
power_t last_power = 0 ; // Last power set state
2018-08-27 15:07:23 +01:00
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
power_t latching_power = 0 ; // Power state at latching start
power_t rel_inverted = 0 ; // Relay inverted flag (1 = (0 = On, 1 = Off))
2017-10-18 17:22:34 +01:00
int serial_in_byte_counter = 0 ; // Index in receive buffer
int ota_state_flag = 0 ; // OTA state flag
int ota_result = 0 ; // OTA result
2019-10-27 11:04:08 +00:00
int restart_flag = 0 ; // Tasmota restart flag
2017-10-18 17:22:34 +01:00
int wifi_state_flag = WIFI_RESTART ; // Wifi state flag
2018-08-27 15:07:23 +01:00
int blinks = 201 ; // Number of LED blinks
uint32_t uptime = 0 ; // Counting every second until 4294967295 = 130 year
2018-11-24 16:16:27 +00:00
uint32_t loop_load_avg = 0 ; // Indicative loop load average
2018-08-27 15:07:23 +01:00
uint32_t global_update = 0 ; // Timestamp of last global temperature and humidity update
2019-10-14 15:12:59 +01:00
uint32_t web_log_index = 1 ; // Index in Web log buffer (should never be 0)
2020-06-28 11:23:18 +01:00
float global_temperature_celsius = NAN ; // Provide a global temperature to be used by some sensors
2020-06-12 15:51:21 +01:00
float global_humidity = 0.0f ; // Provide a global humidity to be used by some sensors
2020-06-28 11:23:18 +01:00
float global_pressure_hpa = 0.0f ; // Provide a global pressure to be used by some sensors
2019-11-13 08:25:09 +00:00
uint16_t tele_period = 9999 ; // Tele period timer
2018-08-27 15:07:23 +01:00
uint16_t blink_counter = 0 ; // Number of blink cycles
uint16_t seriallog_timer = 0 ; // Timer to disable Seriallog
uint16_t syslog_timer = 0 ; // Timer to re-enable syslog_level
2020-04-29 13:01:02 +01:00
uint16_t gpio_pin [ MAX_GPIO_PIN ] = { 0 } ; // GPIO functions indexed by pin number
2018-08-27 15:07:23 +01:00
int16_t save_data_counter ; // Counter and flag for config save to Flash
RulesBitfield rules_flag ; // Rule state flags (16 bits)
2020-01-18 15:57:48 +00:00
uint8_t mqtt_cmnd_blocked = 0 ; // Ignore flag for publish command
uint8_t mqtt_cmnd_blocked_reset = 0 ; // Count down to reset if needed
2018-08-27 15:07:23 +01:00
uint8_t state_250mS = 0 ; // State 250msecond per second flag
2017-10-18 17:22:34 +01:00
uint8_t latching_relay_pulse = 0 ; // Latching relay pulse timer
2020-04-10 17:24:08 +01:00
uint8_t ssleep ; // Current copy of Settings.sleep
2018-07-07 16:30:58 +01:00
uint8_t blinkspeed = 1 ; // LED blink rate
2019-06-08 10:38:45 +01:00
uint8_t active_device = 1 ; // Active device in ExecuteCommandPower
2019-05-21 17:11:39 +01:00
uint8_t leds_present = 0 ; // Max number of LED supported
2017-10-18 17:22:34 +01:00
uint8_t led_inverted = 0 ; // LED inverted flag (1 = (0 = On, 1 = Off))
2019-05-21 17:11:39 +01:00
uint8_t led_power = 0 ; // LED power state
uint8_t ledlnk_inverted = 0 ; // Link LED inverted flag (1 = (0 = On, 1 = Off))
2017-10-18 17:22:34 +01:00
uint8_t pwm_inverted = 0 ; // PWM inverted flag (1 = inverted)
2018-09-04 15:22:34 +01:00
uint8_t energy_flg = 0 ; // Energy monitor configured
2019-10-06 16:19:05 +01:00
uint8_t light_flg = 0 ; // Light module configured
2017-10-18 17:22:34 +01:00
uint8_t light_type = 0 ; // Light types
2019-01-28 13:08:33 +00:00
uint8_t serial_in_byte ; // Received byte
uint8_t ota_retry_counter = OTA_ATTEMPTS ; // OTA retry counter
uint8_t devices_present = 0 ; // Max number of devices supported
2020-07-31 10:53:12 +01:00
uint8_t masterlog_level = 0 ; // Master log level used to override set log level
2019-01-28 13:08:33 +00:00
uint8_t seriallog_level ; // Current copy of Settings.seriallog_level
uint8_t syslog_level ; // Current copy of Settings.syslog_level
2019-02-11 18:21:49 +00:00
uint8_t my_module_type ; // Current copy of Settings.module or user template type
2019-09-30 10:21:43 +01:00
uint8_t last_source = 0 ; // Last command source
2019-09-29 17:00:01 +01:00
uint8_t shutters_present = 0 ; // Number of actual define shutters
2020-01-14 11:47:48 +00:00
uint8_t prepped_loglevel = 0 ; // Delayed log level message
2019-01-28 13:08:33 +00:00
//uint8_t mdns_delayed_start = 0; // mDNS delayed start
2020-05-11 14:27:29 +01:00
bool serial_local = false ; // Handle serial locally
bool serial_buffer_overrun = false ; // Serial buffer overrun
2019-01-28 13:08:33 +00:00
bool fallback_topic_flag = false ; // Use Topic or FallbackTopic
bool backlog_mutex = false ; // Command backlog pending
bool interlock_mutex = false ; // Interlock power command pending
bool stop_flash_rotate = false ; // Allow flash configuration rotation
bool blinkstate = false ; // LED state
2019-07-06 11:53:07 +01:00
//bool latest_uptime_flag = true; // Signal latest uptime
2019-01-28 13:08:33 +00:00
bool pwm_present = false ; // Any PWM channel configured with SetOption15 0
bool i2c_flg = false ; // I2C configured
bool spi_flg = false ; // SPI configured
bool soft_spi_flg = false ; // Software SPI configured
bool ntp_force_sync = false ; // Force NTP sync
2019-12-02 09:31:33 +00:00
bool is_8285 = false ; // Hardware device ESP8266EX (0) or ESP8285 (1)
2020-03-05 23:51:22 +00:00
bool skip_light_fade ; // Temporarily skip light fading
2020-08-10 15:19:44 +01:00
bool restart_halt = false ; // Do not restart but stay in wait loop
2019-01-07 15:33:18 +00:00
myio my_module ; // Active copy of Module GPIOs (17 x 8 bits)
2018-08-27 15:07:23 +01:00
StateBitfield global_state ; // Global states (currently Wifi and Mqtt) (8 bits)
2018-01-10 13:10:25 +00:00
char my_version [ 33 ] ; // Composed version string
2020-01-23 09:33:08 +00:00
char my_image [ 33 ] ; // Code image and/or commit
2017-10-18 17:22:34 +01:00
char my_hostname [ 33 ] ; // Composed Wifi hostname
2019-12-22 14:23:52 +00:00
char mqtt_client [ TOPSZ ] ; // Composed MQTT Clientname
char mqtt_topic [ TOPSZ ] ; // Composed MQTT topic
2018-02-08 11:45:26 +00:00
char serial_in_buffer [ INPUT_BUFFER_SIZE ] ; // Receive buffer
2018-01-18 15:19:28 +00:00
char mqtt_data [ MESSZ ] ; // MQTT publish buffer and web page ajax buffer
char log_data [ LOGSZ ] ; // Logging
2018-01-30 13:14:55 +00:00
char web_log [ WEB_LOG_SIZE ] = { ' \0 ' } ; // Web log buffer
2019-09-09 16:24:27 +01:00
# ifdef SUPPORT_IF_STATEMENT
# include <LinkedList.h>
2019-10-14 15:12:59 +01:00
LinkedList < String > backlog ; // Command backlog implemented with LinkedList
2019-09-09 16:24:27 +01:00
# define BACKLOG_EMPTY (backlog.size() == 0)
# else
2019-10-14 15:12:59 +01:00
uint8_t backlog_index = 0 ; // Command backlog index
uint8_t backlog_pointer = 0 ; // Command backlog pointer
String backlog [ MAX_BACKLOG ] ; // Command backlog buffer
2019-09-09 16:24:27 +01:00
# define BACKLOG_EMPTY (backlog_pointer == backlog_index)
# endif
2018-11-24 16:16:27 +00:00
2017-07-25 17:05:47 +01:00
/*********************************************************************************************\
2019-12-02 09:44:27 +00:00
* Main
2017-07-25 17:05:47 +01:00
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-11-24 16:43:18 +00:00
2020-05-11 15:45:22 +01:00
void setup ( void ) {
2020-04-17 17:27:31 +01:00
# ifdef ESP32
2020-04-18 15:34:29 +01:00
# ifdef DISABLE_ESP32_BROWNOUT
DisableBrownout ( ) ; // Workaround possible weak LDO resulting in brownout detection during Wifi connection
2020-04-17 17:27:31 +01:00
# endif
# endif
2020-06-15 17:27:04 +01:00
global_state . data = 0xF ; // Init global state (wifi_down, mqtt_down) to solve possible network issues
2020-04-18 15:34:29 +01:00
2018-09-04 15:22:34 +01:00
RtcRebootLoad ( ) ;
2019-10-16 18:00:20 +01:00
if ( ! RtcRebootValid ( ) ) {
RtcReboot . fast_reboot_count = 0 ;
}
2020-07-15 15:09:32 +01:00
# ifdef FIRMWARE_MINIMAL
RtcReboot . fast_reboot_count = 0 ; // Disable fast reboot and quick power cycle detection
# else
2018-09-04 15:22:34 +01:00
RtcReboot . fast_reboot_count + + ;
2020-07-15 15:09:32 +01:00
# endif
2018-09-04 15:22:34 +01:00
RtcRebootSave ( ) ;
2018-08-30 13:27:33 +01:00
2019-12-29 12:27:48 +00:00
Serial . begin ( APP_BAUDRATE ) ;
2020-05-11 15:45:22 +01:00
// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars
2017-01-28 13:41:01 +00:00
seriallog_level = LOG_LEVEL_INFO ; // Allow specific serial messages until config loaded
2018-11-07 14:03:41 +00:00
snprintf_P ( my_version , sizeof ( my_version ) , PSTR ( " %d.%d.%d " ) , VERSION > > 24 & 0xff , VERSION > > 16 & 0xff , VERSION > > 8 & 0xff ) ; // Release version 6.3.0
if ( VERSION & 0xff ) { // Development or patched version 6.3.0.10
2018-08-17 10:10:21 +01:00
snprintf_P ( my_version , sizeof ( my_version ) , PSTR ( " %s.%d " ) , my_version , VERSION & 0xff ) ;
}
2020-01-23 09:57:29 +00:00
// Thehackbox inserts "release" or "commit number" before compiling using sed -i -e 's/PSTR("(%s)")/PSTR("(85cff52-%s)")/g' tasmota.ino
snprintf_P ( my_image , sizeof ( my_image ) , PSTR ( " (%s) " ) , CODE_IMAGE_STR ) ; // Results in (85cff52-tasmota) or (release-tasmota)
2017-10-18 17:22:34 +01:00
SettingsLoad ( ) ;
SettingsDelta ( ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
OsWatchInit ( ) ;
2017-02-28 15:01:48 +00:00
2018-05-17 14:36:45 +01:00
GetFeatures ( ) ;
2018-10-23 14:51:51 +01:00
if ( 1 = = RtcReboot . fast_reboot_count ) { // Allow setting override only when all is well
2019-10-18 14:18:39 +01:00
UpdateQuickPowerCycle ( true ) ;
2018-10-23 14:51:51 +01:00
XdrvCall ( FUNC_SETTINGS_OVERRIDE ) ;
}
2019-01-03 16:30:54 +00:00
// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
2017-10-18 17:22:34 +01:00
seriallog_level = Settings . seriallog_level ;
2017-08-24 10:09:52 +01:00
seriallog_timer = SERIALLOG_TIMER ;
2018-09-12 23:00:35 +01:00
syslog_level = Settings . syslog_level ;
2019-11-03 11:33:36 +00:00
stop_flash_rotate = Settings . flag . stop_flash_rotate ; // SetOption12 - Switch between dynamic or fixed slot flash save location
2017-10-18 17:22:34 +01:00
save_data_counter = Settings . save_data ;
2020-04-10 17:24:08 +01:00
ssleep = Settings . sleep ;
2018-11-16 08:36:41 +00:00
# ifndef USE_EMULATION
Settings . flag2 . emulation = 0 ;
2019-05-20 14:09:42 +01:00
# else
# ifndef USE_EMULATION_WEMO
if ( EMUL_WEMO = = Settings . flag2 . emulation ) { Settings . flag2 . emulation = 0 ; }
# endif
# ifndef USE_EMULATION_HUE
if ( EMUL_HUE = = Settings . flag2 . emulation ) { Settings . flag2 . emulation = 0 ; }
# endif
2018-11-16 08:36:41 +00:00
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
2019-11-10 11:05:09 +00:00
if ( Settings . param [ P_BOOT_LOOP_OFFSET ] ) { // SetOption36
2019-01-30 13:34:31 +00:00
// Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts)
if ( RtcReboot . fast_reboot_count > Settings . param [ P_BOOT_LOOP_OFFSET ] ) { // Restart twice
2019-11-03 12:51:22 +00:00
Settings . flag3 . user_esp8285_enable = 0 ; // SetOption51 - Enable ESP8285 user GPIO's - Disable ESP8285 Generic GPIOs interfering with flash SPI
2019-01-30 13:34:31 +00:00
if ( RtcReboot . fast_reboot_count > Settings . param [ P_BOOT_LOOP_OFFSET ] + 1 ) { // Restart 3 times
2019-06-30 15:44:36 +01:00
for ( uint32_t i = 0 ; i < MAX_RULE_SETS ; i + + ) {
2019-01-30 13:34:31 +00:00
if ( bitRead ( Settings . rule_stop , i ) ) {
bitWrite ( Settings . rule_enabled , i , 0 ) ; // Disable rules causing boot loop
}
2018-08-30 13:27:33 +01:00
}
}
2019-01-30 13:34:31 +00:00
if ( RtcReboot . fast_reboot_count > Settings . param [ P_BOOT_LOOP_OFFSET ] + 2 ) { // Restarted 4 times
Settings . rule_enabled = 0 ; // Disable all rules
2018-08-30 13:47:48 +01:00
}
2019-01-30 13:34:31 +00:00
if ( RtcReboot . fast_reboot_count > Settings . param [ P_BOOT_LOOP_OFFSET ] + 3 ) { // Restarted 5 times
2020-04-25 10:37:36 +01:00
for ( uint32_t i = 0 ; i < ARRAY_SIZE ( Settings . my_gp . io ) ; i + + ) {
2019-01-30 13:34:31 +00:00
Settings . my_gp . io [ i ] = GPIO_NONE ; // Reset user defined GPIO disabling sensors
}
}
if ( RtcReboot . fast_reboot_count > Settings . param [ P_BOOT_LOOP_OFFSET ] + 4 ) { // Restarted 6 times
2020-06-17 13:06:46 +01:00
Settings . module = Settings . fallback_module ; // Reset module to fallback module
// Settings.last_module = Settings.fallback_module;
2019-01-30 13:34:31 +00:00
}
2020-08-13 16:15:57 +01:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( " FRC: " D_LOG_SOME_SETTINGS_RESET " (%d) " ) , RtcReboot . fast_reboot_count ) ;
2018-08-28 09:26:33 +01:00
}
}
2019-12-16 14:13:57 +00:00
Format ( mqtt_client , SettingsText ( SET_MQTT_CLIENT ) , sizeof ( mqtt_client ) ) ;
Format ( mqtt_topic , SettingsText ( SET_MQTT_TOPIC ) , sizeof ( mqtt_topic ) ) ;
if ( strstr ( SettingsText ( SET_HOSTNAME ) , " % " ) ! = nullptr ) {
SettingsUpdateText ( SET_HOSTNAME , WIFI_HOSTNAME ) ;
2020-04-13 16:45:06 +01:00
snprintf_P ( my_hostname , sizeof ( my_hostname ) - 1 , SettingsText ( SET_HOSTNAME ) , mqtt_topic , ESP_getChipId ( ) & 0x1FFF ) ;
2017-01-28 13:41:01 +00:00
} else {
2019-12-16 14:13:57 +00:00
snprintf_P ( my_hostname , sizeof ( my_hostname ) - 1 , SettingsText ( SET_HOSTNAME ) ) ;
2017-01-28 13:41:01 +00:00
}
2018-09-05 14:38:48 +01:00
2019-12-02 09:31:33 +00:00
GetEspHardwareType ( ) ;
2018-09-05 14:38:48 +01:00
GpioInit ( ) ;
2019-12-30 13:23:37 +00:00
// SetSerialBaudrate(Settings.baudrate * 300); // Allow reset of serial interface if current baudrate is different from requested baudrate
2017-10-18 17:22:34 +01:00
WifiConnect ( ) ;
2017-01-28 13:41:01 +00:00
2020-01-11 14:39:56 +00:00
SetPowerOnState ( ) ;
2017-01-28 13:41:01 +00:00
2020-05-17 16:10:17 +01:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( D_PROJECT " %s %s " D_VERSION " %s%s- " ARDUINO_CORE_RELEASE ) , PROJECT , SettingsText ( SET_DEVICENAME ) , my_version , my_image ) ;
2019-02-08 13:55:45 +00:00
# ifdef FIRMWARE_MINIMAL
2019-03-08 14:15:42 +00:00
AddLog_P2 ( LOG_LEVEL_INFO , PSTR ( D_WARNING_MINIMAL_VERSION ) ) ;
2019-02-08 13:55:45 +00:00
# endif // FIRMWARE_MINIMAL
2017-12-01 14:59:53 +00:00
2019-12-20 14:12:44 +00:00
memcpy_P ( log_data , VERSION_MARKER , 1 ) ; // Dummy for compiler saving VERSION_MARKER
2017-12-01 14:59:53 +00:00
RtcInit ( ) ;
2018-03-21 16:58:39 +00:00
# ifdef USE_ARDUINO_OTA
ArduinoOTAInit ( ) ;
# endif // USE_ARDUINO_OTA
2018-06-04 17:10:38 +01:00
XdrvCall ( FUNC_INIT ) ;
2018-01-24 16:31:20 +00:00
XsnsCall ( FUNC_INIT ) ;
2020-06-16 09:36:16 +01:00
# ifdef USE_SCRIPT
2020-07-02 05:46:04 +01:00
if ( bitRead ( Settings . rule_enabled , 0 ) ) Run_Scripter ( " >BS " , 3 , 0 ) ;
2020-06-16 09:36:16 +01:00
# endif
2020-06-14 11:36:44 +01:00
rules_flag . system_init = 1 ;
2017-01-28 13:41:01 +00:00
}
2020-05-11 15:45:22 +01:00
void BacklogLoop ( void ) {
2019-10-04 13:46:31 +01:00
if ( TimeReached ( backlog_delay ) ) {
if ( ! BACKLOG_EMPTY & & ! backlog_mutex ) {
# ifdef SUPPORT_IF_STATEMENT
2019-12-06 15:12:13 +00:00
backlog_mutex = true ;
String cmd = backlog . shift ( ) ;
backlog_mutex = false ;
ExecuteCommand ( ( char * ) cmd . c_str ( ) , SRC_BACKLOG ) ;
2019-10-04 13:46:31 +01:00
# else
2019-12-06 15:12:13 +00:00
backlog_mutex = true ;
2019-10-04 13:46:31 +01:00
ExecuteCommand ( ( char * ) backlog [ backlog_pointer ] . c_str ( ) , SRC_BACKLOG ) ;
2020-09-03 14:11:14 +01:00
backlog [ backlog_pointer ] = ( const char * ) nullptr ; // force deallocation of the String internal memory
2019-10-04 13:46:31 +01:00
backlog_pointer + + ;
if ( backlog_pointer > = MAX_BACKLOG ) { backlog_pointer = 0 ; }
backlog_mutex = false ;
2019-12-06 15:12:13 +00:00
# endif
2019-10-04 13:46:31 +01:00
}
}
}
2020-05-11 15:45:22 +01:00
void SleepDelay ( uint32_t mseconds ) {
if ( mseconds ) {
for ( uint32_t wait = 0 ; wait < mseconds ; wait + + ) {
delay ( 1 ) ;
if ( Serial . available ( ) ) { break ; } // We need to service serial buffer ASAP as otherwise we get uart buffer overrun
}
} else {
delay ( 0 ) ;
}
}
void loop ( void ) {
2018-11-18 14:02:52 +00:00
uint32_t my_sleep = millis ( ) ;
2018-02-27 13:59:46 +00:00
XdrvCall ( FUNC_LOOP ) ;
2018-12-11 13:24:52 +00:00
XsnsCall ( FUNC_LOOP ) ;
2018-02-27 13:59:46 +00:00
2017-10-18 17:22:34 +01:00
OsWatchLoop ( ) ;
2017-09-02 13:37:02 +01:00
2019-01-07 11:38:47 +00:00
ButtonLoop ( ) ;
2018-12-28 15:35:19 +00:00
SwitchLoop ( ) ;
2020-02-21 15:09:21 +00:00
# ifdef USE_DEVICE_GROUPS
DeviceGroupsLoop ( ) ;
# endif // USE_DEVICE_GROUPS
2019-10-09 16:52:52 +01:00
BacklogLoop ( ) ;
2018-12-28 15:35:19 +00:00
2018-08-26 14:42:35 +01:00
if ( TimeReached ( state_50msecond ) ) {
SetNextTimeInterval ( state_50msecond , 50 ) ;
2020-07-01 09:22:20 +01:00
# ifdef ROTARY_V1
RotaryHandler ( ) ;
2020-07-01 09:24:46 +01:00
# endif // ROTARY_V1
2018-08-26 16:10:18 +01:00
XdrvCall ( FUNC_EVERY_50_MSECOND ) ;
XsnsCall ( FUNC_EVERY_50_MSECOND ) ;
2018-08-26 14:42:35 +01:00
}
if ( TimeReached ( state_100msecond ) ) {
SetNextTimeInterval ( state_100msecond , 100 ) ;
Every100mSeconds ( ) ;
2018-08-26 16:10:18 +01:00
XdrvCall ( FUNC_EVERY_100_MSECOND ) ;
XsnsCall ( FUNC_EVERY_100_MSECOND ) ;
2018-08-26 14:42:35 +01:00
}
if ( TimeReached ( state_250msecond ) ) {
SetNextTimeInterval ( state_250msecond , 250 ) ;
Every250mSeconds ( ) ;
2018-08-26 16:10:18 +01:00
XdrvCall ( FUNC_EVERY_250_MSECOND ) ;
XsnsCall ( FUNC_EVERY_250_MSECOND ) ;
2019-10-18 11:47:22 +01:00
}
if ( TimeReached ( state_second ) ) {
SetNextTimeInterval ( state_second , 1000 ) ;
PerformEverySecond ( ) ;
XdrvCall ( FUNC_EVERY_SECOND ) ;
XsnsCall ( FUNC_EVERY_SECOND ) ;
2018-08-26 14:42:35 +01:00
}
2018-02-27 13:59:46 +00:00
2019-01-28 13:08:33 +00:00
if ( ! serial_local ) { SerialInput ( ) ; }
2017-01-28 13:41:01 +00:00
2018-03-21 16:58:39 +00:00
# ifdef USE_ARDUINO_OTA
2020-01-03 15:50:56 +00:00
ArduinoOtaLoop ( ) ;
2018-03-21 16:58:39 +00:00
# endif // USE_ARDUINO_OTA
2018-11-18 14:02:52 +00:00
uint32_t my_activity = millis ( ) - my_sleep ;
2018-12-01 17:53:42 +00:00
2020-05-11 15:45:22 +01:00
if ( Settings . flag3 . sleep_normal ) { // SetOption60 - Enable normal sleep instead of dynamic sleep
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
SleepDelay ( ssleep ) ; // https://github.com/esp8266/Arduino/issues/2021
2018-11-22 11:25:18 +00:00
} else {
2020-04-10 17:24:08 +01:00
if ( my_activity < ( uint32_t ) ssleep ) {
2020-05-11 15:45:22 +01:00
SleepDelay ( ( uint32_t ) ssleep - my_activity ) ; // Provide time for background tasks like wifi
2018-12-01 16:47:25 +00:00
} else {
2020-06-15 17:27:04 +01:00
if ( global_state . network_down ) {
2020-05-11 15:45:22 +01:00
SleepDelay ( my_activity / 2 ) ; // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period
2018-12-01 16:47:25 +00:00
}
2018-11-22 11:25:18 +00:00
}
}
2018-11-25 16:31:53 +00:00
2020-05-11 15:45:22 +01:00
if ( ! my_activity ) { my_activity + + ; } // We cannot divide by 0
2020-04-10 17:24:08 +01:00
uint32_t loop_delay = ssleep ;
2020-05-11 15:45:22 +01:00
if ( ! loop_delay ) { loop_delay + + ; } // We cannot divide by 0
uint32_t loops_per_second = 1000 / loop_delay ; // We need to keep track of this many loops per second
2018-11-25 16:31:53 +00:00
uint32_t this_cycle_ratio = 100 * my_activity / loop_delay ;
2018-12-01 16:47:25 +00:00
loop_load_avg = loop_load_avg - ( loop_load_avg / loops_per_second ) + ( this_cycle_ratio / loops_per_second ) ; // Take away one loop average away and add the new one
2017-08-08 15:08:08 +01:00
}