2020-05-23 12:09:16 +01:00
/*
2021-07-19 18:24:53 +01:00
tasmota . ino - Tasmota firmware for iTead Sonoff , Wemos , NodeMCU , ESP8266 and ESP32 hardwares
2017-05-13 12:02:10 +01:00
2021-01-01 12:44:04 +00:00
Copyright ( C ) 2021 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
2017-10-18 17:22:34 +01:00
// Location specific includes
2020-11-01 14:24:12 +00:00
# ifndef ESP32_STAGE // ESP32 Stage has no core_version.h file. Disable include via PlatformIO Option
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)
2024-04-15 14:12:17 +01:00
# endif // ESP32_STAGE
2022-06-02 13:17:39 +01:00
# include "include/tasmota_compat.h"
# include "include/tasmota_version.h" // Tasmota version information
# include "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
2024-04-15 14:12:17 +01:00
# include <t_bearssl.h> // We need to include before "tasmota_globals.h" to take precedence over the BearSSL version in Arduino
# endif // USE_TLS
2022-06-02 13:17:39 +01:00
# include "include/tasmota_globals.h" // Function prototypes and global configuration
# include "include/i18n.h" // Language support configured by my_user_config.h
# include "include/tasmota_template.h" // Hardware configuration
2017-03-03 11:35:23 +00:00
2022-12-10 12:44:16 +00:00
// ------------------------------------------------------------------------------------------
// If IPv6 is not support by the underlying esp-idf, disable it
// ------------------------------------------------------------------------------------------
# if !LWIP_IPV6
2024-04-15 14:12:17 +01:00
# undef USE_IPV6
2022-12-10 12:44:16 +00:00
# endif
2018-02-27 13:59:46 +00:00
// Libraries
2024-04-05 22:44:21 +01:00
# include <WiFiHelper.h>
2018-11-20 14:00:24 +00:00
# include <ESP8266HTTPClient.h> // Ota
2017-01-28 13:41:01 +00:00
# include <ESP8266httpUpdate.h> // Ota
2021-11-23 21:15:08 +00:00
# ifdef ESP32
2024-04-15 14:12:17 +01:00
# ifdef USE_TLS
# include "HTTPUpdateLight.h" // Ota over HTTPS for ESP32
# endif // USE_TLS
# endif // ESP32
2017-06-04 16:40:27 +01:00
# include <StreamString.h> // Webserver, Updater
2021-01-24 15:35:36 +00:00
# include <ext_printf.h>
2021-01-25 15:02:56 +00:00
# include <SBuffer.hpp>
2021-11-06 08:37:40 +00:00
# include <LList.h>
2020-09-24 07:51:43 +01:00
# include <JsonParser.h>
# include <JsonGenerator.h>
2023-04-27 15:35:47 +01:00
# ifdef ESP8266
2018-03-21 16:58:39 +00:00
# ifdef USE_ARDUINO_OTA
2024-04-15 14:12:17 +01:00
# include <ArduinoOTA.h> // Arduino OTA
# ifndef USE_DISCOVERY
# define USE_DISCOVERY
# endif // USE_DISCOVERY
2018-03-21 16:58:39 +00:00
# endif // USE_ARDUINO_OTA
2023-04-27 15:35:47 +01:00
# endif // ESP8266
2017-01-28 13:41:01 +00:00
# ifdef USE_DISCOVERY
2024-04-15 14:12:17 +01:00
# include <ESP8266mDNS.h> // MQTT, Webserver, Arduino OTA
2017-01-28 13:41:01 +00:00
# endif // USE_DISCOVERY
2024-04-15 14:12:17 +01:00
# include <Wire.h> // I2C support library
2017-07-15 14:07:30 +01:00
# ifdef USE_SPI
2024-04-15 14:12:17 +01:00
# include <SPI.h> // SPI support, TFT, SDcard
2017-04-29 13:40:53 +01:00
# endif // USE_SPI
2019-02-17 09:42:55 +00:00
2021-01-20 14:43:26 +00:00
# ifdef USE_UFILESYS
# ifdef ESP8266
# include <LittleFS.h>
# include <SPI.h>
# ifdef USE_SDCARD
# include <SD.h>
2021-04-14 12:41:10 +01:00
# include <SdFat.h>
2021-01-20 14:43:26 +00:00
# endif // USE_SDCARD
# endif // ESP8266
# ifdef ESP32
2021-07-18 22:14:10 +01:00
# include <LittleFS.h>
2021-01-20 14:43:26 +00:00
# ifdef USE_SDCARD
# include <SD.h>
2024-06-11 12:25:47 +01:00
# ifdef SOC_SDMMC_HOST_SUPPORTED
2022-04-19 18:17:04 +01:00
# include <SD_MMC.h>
2024-06-11 12:25:47 +01:00
# endif // SOC_SDMMC_HOST_SUPPORTED
2021-01-20 14:43:26 +00:00
# endif // USE_SDCARD
# include "FFat.h"
# include "FS.h"
# endif // ESP32
# endif // USE_UFILESYS
2024-04-15 14:12:17 +01:00
# ifdef ESP32
2023-10-24 15:32:39 +01:00
# include "include/tasconsole.h"
# if SOC_USB_SERIAL_JTAG_SUPPORTED
# include "hal/usb_serial_jtag_ll.h"
# include "esp_private/rtc_clk.h"
# endif // SOC_USB_SERIAL_JTAG_SUPPORTED
2021-10-12 09:58:06 +01:00
# ifdef CONFIG_IDF_TARGET_ESP32
2024-01-19 22:19:56 +00:00
# include "driver/gpio.h"
2021-10-12 09:58:06 +01:00
# include "soc/efuse_reg.h"
2024-01-19 22:19:56 +00:00
# include "bootloader_common.h"
2021-10-12 09:58:06 +01:00
# endif
2024-04-15 14:12:17 +01:00
# endif // ESP32
// Structs
# include "include/tasmota_types.h"
2021-10-12 09:58:06 +01:00
2019-12-02 09:44:27 +00:00
/*********************************************************************************************\
* Global variables
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-04-12 10:49:53 +01:00
const uint32_t VERSION_MARKER [ ] PROGMEM = { 0x5AA55AA5 , 0xFFFFFFFF , 0xA55AA55A } ;
2022-08-07 14:52:23 +01:00
struct WIFI {
2023-05-16 17:55:55 +01:00
int last_tx_pwr ;
2022-08-07 14:52:23 +01:00
uint32_t last_event = 0 ; // Last wifi connection event
uint32_t downtime = 0 ; // Wifi down duration
uint16_t link_count = 0 ; // Number of wifi re-connect
uint8_t counter ;
uint8_t retry_init ;
uint8_t retry ;
uint8_t max_retry ;
uint8_t status ;
uint8_t config_type = 0 ;
uint8_t config_counter = 0 ;
uint8_t scan_state ;
uint8_t bssid [ 6 ] ;
int8_t best_network_db ;
uint8_t wifiTest = WIFI_NOT_TESTING ;
uint8_t wifi_test_counter = 0 ;
uint16_t save_data_counter = 0 ;
uint8_t old_wificonfig = MAX_WIFI_OPTION ; // means "nothing yet saved here"
2022-10-15 13:33:21 +01:00
uint8_t phy_mode = 0 ;
2022-08-07 14:52:23 +01:00
bool wifi_test_AP_TIMEOUT = false ;
bool wifi_Test_Restart = false ;
bool wifi_Test_Save_SSID2 = false ;
} Wifi ;
2022-06-02 13:17:39 +01:00
typedef struct {
uint16_t valid ; // 280 (RTC memory offset 100 - sizeof(RTCRBT))
uint8_t fast_reboot_count ; // 282
uint8_t free_003 [ 1 ] ; // 283
} TRtcReboot ;
TRtcReboot RtcReboot ;
# ifdef ESP32
2022-11-14 16:11:38 +00:00
static RTC_NOINIT_ATTR TRtcReboot RtcDataReboot ;
2022-06-02 13:17:39 +01:00
# endif // ESP32
typedef struct {
uint16_t valid ; // 290 (RTC memory offset 100)
uint8_t oswatch_blocked_loop ; // 292
uint8_t ota_loader ; // 293
2022-08-05 14:25:39 +01:00
uint32_t ex_energy_kWhtoday ; // 294
uint32_t ex_energy_kWhtotal ; // 298
2022-06-02 13:17:39 +01:00
volatile uint32_t pulse_counter [ MAX_COUNTERS ] ; // 29C - See #9521 why volatile
power_t power ; // 2AC
EnergyUsage energy_usage ; // 2B0
uint32_t nextwakeup ; // 2C8
uint32_t baudrate ; // 2CC
uint32_t ultradeepsleep ; // 2D0
uint16_t deepsleep_slip ; // 2D4
uint8_t improv_state ; // 2D6
uint8_t free_2d7 [ 1 ] ; // 2D7
int32_t energy_kWhtoday_ph [ 3 ] ; // 2D8
int32_t energy_kWhtotal_ph [ 3 ] ; // 2E4
int32_t energy_kWhexport_ph [ 3 ] ; // 2F0
2022-06-16 15:15:54 +01:00
uint32_t utc_time ; // 2FC
2022-06-02 13:17:39 +01:00
} TRtcSettings ;
TRtcSettings RtcSettings ;
# ifdef ESP32
2022-11-14 16:11:38 +00:00
static RTC_NOINIT_ATTR TRtcSettings RtcDataSettings ;
2022-06-02 13:17:39 +01:00
# endif // ESP32
struct TIME_T {
2022-10-16 16:56:58 +01:00
uint32_t nanos ;
2022-06-02 13:17:39 +01:00
uint8_t second ;
uint8_t minute ;
uint8_t hour ;
uint8_t day_of_week ; // sunday is day 1
uint8_t day_of_month ;
uint8_t month ;
char name_of_month [ 4 ] ;
uint16_t day_of_year ;
uint16_t year ;
uint32_t days ;
uint32_t valid ;
} RtcTime ;
struct XDRVMAILBOX {
bool grpflg ;
bool usridx ;
uint16_t command_code ;
uint32_t index ;
uint32_t data_len ;
int32_t payload ;
char * topic ;
char * data ;
char * command ;
} XdrvMailbox ;
2018-08-27 15:07:23 +01:00
WiFiUDP PortUdp ; // UDP Syslog and Alexa
2022-05-06 13:57:03 +01:00
# ifdef ESP32
2023-10-24 15:32:39 +01:00
/*
# if CONFIG_IDF_TARGET_ESP32C3 || // support USB via HWCDC using JTAG interface
CONFIG_IDF_TARGET_ESP32C6 | | // support USB via HWCDC using JTAG interface
CONFIG_IDF_TARGET_ESP32S2 | | // support USB via USBCDC
CONFIG_IDF_TARGET_ESP32S3 // support USB via HWCDC using JTAG interface or USBCDC
*/
# if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
//#if CONFIG_TINYUSB_CDC_ENABLED // This define is not recognized here so use USE_USB_CDC_CONSOLE
# ifdef USE_USB_CDC_CONSOLE
//#warning **** TasConsole use USB ****
bool tasconsole_serial = false ;
# if ARDUINO_USB_MODE
//#warning **** TasConsole ARDUINO_USB_MODE ****
2024-04-12 15:01:00 +01:00
# if !ARDUINO_USB_CDC_ON_BOOT
2024-03-10 14:20:43 +00:00
HWCDC HWCDCSerial ;
2024-04-12 15:01:00 +01:00
# endif // ARDUINO_USB_CDC_ON_BOOT
2023-10-28 12:15:31 +01:00
TASCONSOLE TasConsole { HWCDCSerial } ; // ESP32C3/C6/S3 embedded USB using JTAG interface
2023-10-24 15:32:39 +01:00
//#warning **** TasConsole uses HWCDC ****
# else // No ARDUINO_USB_MODE
# include "USB.h"
# include "USBCDC.h"
2024-04-15 12:00:09 +01:00
# if !ARDUINO_USB_CDC_ON_BOOT
USBCDC USBSerial ; // Already defined in USBCDC.cpp
# endif // ARDUINO_USB_CDC_ON_BOOT
2023-10-24 15:32:39 +01:00
TASCONSOLE TasConsole { USBSerial } ; // ESP32Sx embedded USB interface
//#warning **** TasConsole uses USBCDC ****
# endif // ARDUINO_USB_MODE
2024-04-15 14:12:17 +01:00
# else // No USE_USB_CDC_CONSOLE
2023-10-24 15:32:39 +01:00
TASCONSOLE TasConsole { Serial } ;
bool tasconsole_serial = true ;
//#warning **** TasConsole uses Serial ****
# endif // USE_USB_CDC_CONSOLE
# else // No ESP32C3, S2 or S3
TASCONSOLE TasConsole { Serial } ;
bool tasconsole_serial = true ;
//#warning **** TasConsole uses Serial ****
# endif // ESP32C3, S2 or S3
2022-05-06 13:57:03 +01:00
# else // No ESP32
HardwareSerial TasConsole = Serial ; // Only serial interface
# endif // ESP32
2022-10-12 10:02:54 +01:00
char EmptyStr [ 1 ] = { 0 } ; // Provide a pointer destination to an empty char string
2021-09-30 18:51:40 +01:00
struct TasmotaGlobal_t {
2020-10-29 11:21:24 +00:00
uint32_t global_update ; // Timestamp of last global temperature and humidity update
2020-10-28 16:32:07 +00:00
uint32_t baudrate ; // Current Serial baudrate
uint32_t pulse_timer [ MAX_PULSETIMERS ] ; // Power off timer
uint32_t blink_timer ; // Power cycle timer
2020-11-27 13:43:45 +00:00
uint32_t backlog_timer ; // Timer for next command in backlog
2020-10-28 16:32:07 +00:00
uint32_t loop_load_avg ; // Indicative loop load average
2020-12-18 15:30:37 +00:00
uint32_t log_buffer_pointer ; // Index in log buffer
2020-10-28 16:32:07 +00:00
uint32_t uptime ; // Counting every second until 4294967295 = 130 year
2021-03-23 10:21:38 +00:00
uint32_t zc_time ; // Zero-cross moment (microseconds)
uint32_t zc_offset ; // Zero cross moment offset due to monitoring chip processing (microseconds)
uint32_t zc_code_offset ; // Zero cross moment offset due to executing power code (microseconds)
uint32_t zc_interval ; // Zero cross interval around 8333 (60Hz) or 10000 (50Hz) (microseconds)
2020-12-20 12:22:01 +00:00
GpioOptionABits gpio_optiona ; // GPIO Option_A flags
2021-01-01 16:04:36 +00:00
void * log_buffer_mutex ; // Control access to log buffer
2020-10-28 16:32:07 +00:00
2021-06-11 17:14:12 +01:00
power_t power ; // Current copy of Settings->power
2023-04-19 15:17:04 +01:00
power_t power_latching ; // Current state of single pin latching power
2020-10-28 18:03:39 +00:00
power_t rel_inverted ; // Relay inverted flag (1 = (0 = On, 1 = Off))
2022-07-09 14:55:27 +01:00
power_t rel_bistable ; // Relay bistable bitmap
2020-10-28 18:03:39 +00:00
power_t last_power ; // Last power set state
power_t blink_power ; // Blink power state
power_t blink_powersave ; // Blink start power save state
power_t blink_mask ; // Blink relay active mask
2022-11-03 16:26:54 +00:00
power_t power_on_delay_state ;
2020-10-28 18:03:39 +00:00
2020-10-29 11:21:24 +00:00
int serial_in_byte_counter ; // Index in receive buffer
2020-10-28 18:03:39 +00:00
float temperature_celsius ; // Provide a global temperature to be used by some sensors
float humidity ; // Provide a global humidity to be used by some sensors
float pressure_hpa ; // Provide a global pressure to be used by some sensors
2020-10-29 12:58:50 +00:00
uint16_t gpio_pin [ MAX_GPIO_PIN ] ; // GPIO functions indexed by pin number
2020-10-30 11:29:48 +00:00
myio my_module ; // Active copy of Module GPIOs (17 x 16 bits)
2020-10-29 12:37:09 +00:00
uint16_t blink_counter ; // Number of blink cycles
uint16_t seriallog_timer ; // Timer to disable Seriallog
uint16_t syslog_timer ; // Timer to re-enable syslog_level
uint16_t tele_period ; // Tele period timer
2020-10-29 12:58:50 +00:00
int16_t save_data_counter ; // Counter and flag for config save to Flash
RulesBitfield rules_flag ; // Rule state flags (16 bits)
2020-10-29 12:37:09 +00:00
2022-06-22 22:45:25 +01:00
StateBitfield global_state ; // Global states (currently Wifi and Mqtt) (8 bits)
uint16_t pwm_inverted ; // PWM inverted flag (1 = inverted) - extended to 16 bits for ESP32
# ifdef ESP32
int16_t pwm_cur_value [ MAX_PWMS ] ; // Current effective values of PWMs as applied to GPIOs
int16_t pwm_cur_phase [ MAX_PWMS ] ; // Current phase values of PWMs as applied to GPIOs
int16_t pwm_value [ MAX_PWMS ] ; // Wanted values of PWMs after update - -1 means no change
int16_t pwm_phase [ MAX_PWMS ] ; // Wanted phase of PWMs after update - -1 means no change
2024-04-15 14:12:17 +01:00
# endif // ESP32
2022-06-22 22:45:25 +01:00
2020-10-30 11:29:48 +00:00
bool serial_local ; // Handle serial locally
bool fallback_topic_flag ; // Use Topic or FallbackTopic
2024-07-08 14:53:15 +01:00
bool no_mqtt_response ; // Respond with rule processing only
2021-04-07 16:55:33 +01:00
bool backlog_nodelay ; // Execute all backlog commands with no delay
2020-10-30 11:29:48 +00:00
bool backlog_mutex ; // Command backlog pending
2024-07-08 14:53:15 +01:00
bool backlog_no_mqtt_response ; // Set respond with rule processing only
2020-10-30 11:29:48 +00:00
bool stop_flash_rotate ; // Allow flash configuration rotation
bool blinkstate ; // LED state
bool pwm_present ; // Any PWM channel configured with SetOption15 0
bool i2c_enabled ; // I2C configured
2024-09-19 13:47:18 +01:00
bool i2c_enabled_2 ; // I2C configured, second controller, Wire1
2021-03-10 21:20:21 +00:00
# ifdef ESP32
2022-05-11 13:31:39 +01:00
bool ota_factory ; // Select safeboot binary
2021-03-10 21:20:21 +00:00
# endif
2020-10-30 11:29:48 +00:00
bool ntp_force_sync ; // Force NTP sync
bool skip_light_fade ; // Temporarily skip light fading
bool restart_halt ; // Do not restart but stay in wait loop
2023-07-03 20:07:45 +01:00
bool restart_deepsleep ; // Do not restart but do deepsleep
2020-11-01 11:12:27 +00:00
bool module_changed ; // Indicate module changed since last restart
2021-01-14 16:03:01 +00:00
bool wifi_stay_asleep ; // Allow sleep only incase of ESP32 BLE
2021-02-15 15:51:13 +00:00
bool no_autoexec ; // Disable autoexec
2020-10-30 11:29:48 +00:00
2022-06-22 22:45:25 +01:00
uint8_t user_globals [ 3 ] ; // User set global temp/hum/press
2023-05-24 15:21:59 +01:00
uint8_t busy_time ; // Time in ms to allow executing of time critical functions
2021-11-03 10:58:05 +00:00
uint8_t init_state ; // Tasmota init state
uint8_t heartbeat_inverted ; // Heartbeat pulse inverted flag
2024-05-21 14:58:16 +01:00
uint8_t spi_enabled ; // SPI configured (bus1)
uint8_t spi_enabled2 ; // SPI configured (bus2)
2020-12-31 15:17:30 +00:00
uint8_t soft_spi_enabled ; // Software SPI configured
2020-10-29 11:39:44 +00:00
uint8_t blinks ; // Number of LED blinks
uint8_t restart_flag ; // Tasmota restart flag
2020-10-29 11:58:22 +00:00
uint8_t ota_state_flag ; // OTA state flag
2020-10-29 11:39:44 +00:00
uint8_t wifi_state_flag ; // Wifi state flag
2020-10-29 12:58:50 +00:00
uint8_t mqtt_cmnd_blocked ; // Ignore flag for publish command
uint8_t mqtt_cmnd_blocked_reset ; // Count down to reset if needed
uint8_t state_250mS ; // State 250msecond per second flag
uint8_t latching_relay_pulse ; // Latching relay pulse timer
uint8_t active_device ; // Active device in ExecuteCommandPower
2021-06-11 17:14:12 +01:00
uint8_t sleep ; // Current copy of Settings->sleep
2020-10-30 11:29:48 +00:00
uint8_t leds_present ; // Max number of LED supported
uint8_t led_inverted ; // LED inverted flag (1 = (0 = On, 1 = Off))
uint8_t led_power ; // LED power state
uint8_t ledlnk_inverted ; // Link LED inverted flag (1 = (0 = On, 1 = Off))
2022-01-27 20:30:05 +00:00
// uint8_t pwm_inverted; // PWM inverted flag (1 = inverted) -- TODO
2020-10-30 11:29:48 +00:00
uint8_t energy_driver ; // Energy monitor configured
uint8_t light_driver ; // Light module configured
uint8_t light_type ; // Light types
uint8_t serial_in_byte ; // Received byte
2022-11-20 11:52:24 +00:00
uint8_t serial_skip ; // Skip number of received messages
2020-10-30 11:29:48 +00:00
uint8_t devices_present ; // Max number of devices supported
2023-05-19 14:20:21 +01:00
uint8_t maxlog_level ; // Max allowed log level
2020-10-30 11:29:48 +00:00
uint8_t masterlog_level ; // Master log level used to override set log level
2021-06-11 17:14:12 +01:00
uint8_t seriallog_level ; // Current copy of Settings->seriallog_level
uint8_t syslog_level ; // Current copy of Settings->syslog_level
2020-12-22 14:26:07 +00:00
uint8_t templog_level ; // Temporary log level to be used by HTTP cm and Telegram
2021-06-11 17:14:12 +01:00
uint8_t module_type ; // Current copy of Settings->module or user template type
2022-01-07 15:17:53 +00:00
uint8_t emulated_module_type ; // Emulated module type as requested by ESP32
2020-10-30 11:29:48 +00:00
uint8_t last_source ; // Last command source
uint8_t shutters_present ; // Number of actual define shutters
2021-05-11 10:01:46 +01:00
uint8_t discovery_counter ; // Delayed discovery counter
2022-11-03 16:26:54 +00:00
uint8_t power_on_delay ; // Delay relay power on to reduce power surge (SetOption47)
2021-11-29 20:53:24 +00:00
# ifdef USE_PWM_DIMMER
uint8_t restore_powered_off_led_counter ; // Seconds before powered-off LED (LEDLink) is restored
2022-05-17 14:11:56 +01:00
uint8_t pwm_dimmer_led_bri ; // Adjusted brightness LED level
2021-11-29 20:53:24 +00:00
# endif // USE_PWM_DIMMER
2021-06-06 16:26:01 +01:00
String mqtt_data ; // Buffer filled by Response functions
2020-10-30 11:29:48 +00:00
char version [ 16 ] ; // Composed version string like 255.255.255.255
char image_name [ 33 ] ; // Code image and/or commit
char hostname [ 33 ] ; // Composed Wifi hostname
char serial_in_buffer [ INPUT_BUFFER_SIZE ] ; // Receive buffer
char mqtt_client [ 99 ] ; // Composed MQTT Clientname
char mqtt_topic [ TOPSZ ] ; // Composed MQTT topic
2021-06-11 15:02:49 +01:00
# ifdef PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
2021-06-11 17:14:12 +01:00
char * log_buffer = nullptr ; // Log buffer in IRAM
2021-06-11 15:02:49 +01:00
# else
char log_buffer [ LOG_BUFFER_SIZE ] ; // Log buffer in DRAM
# endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
2022-01-09 18:22:23 +00:00
# ifdef USE_BERRY
2024-01-18 15:32:28 +00:00
bool berry_fast_loop_enabled = false ; // is Berry fast loop enabled, i.e. control is passed at each loop iteration
2024-04-15 14:12:17 +01:00
# endif // USE_BERRY
2024-05-05 17:21:03 +01:00
} TasmotaGlobal = { 0 } ;
2020-10-28 16:32:07 +00:00
2021-06-11 17:14:12 +01:00
TSettings * Settings = nullptr ;
2024-01-21 21:07:49 +00:00
LList < char * > backlog ; // Command backlog implemented with TasmotaLList
# define BACKLOG_EMPTY (backlog.isEmpty())
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
2024-10-09 16:31:33 +01:00
# ifdef ESP32
// IDF5.3 fix esp_gpio_reserve used in init PSRAM. Needed by Tasmota.ino esp_gpio_revoke
# include "esp_private/esp_gpio_reserve.h"
# endif // ESP32
2020-05-11 15:45:22 +01:00
void setup ( void ) {
2020-04-17 17:27:31 +01:00
# ifdef ESP32
2023-08-21 15:00:20 +01:00
# ifdef CONFIG_IDF_TARGET_ESP32
2024-01-19 22:19:56 +00:00
2020-04-18 15:34:29 +01:00
# ifdef DISABLE_ESP32_BROWNOUT
DisableBrownout ( ) ; // Workaround possible weak LDO resulting in brownout detection during Wifi connection
2021-12-17 17:01:27 +00:00
# endif // DISABLE_ESP32_BROWNOUT
2020-04-17 17:27:31 +01:00
2021-10-11 18:36:39 +01:00
// restore GPIO16/17 if no PSRAM is found
if ( ! FoundPSRAM ( ) ) {
2021-10-12 09:58:06 +01:00
// test if the CPU is not pico
2024-01-19 22:19:56 +00:00
uint32_t pkg_version = bootloader_common_get_chip_ver_pkg ( ) ;
2024-10-10 11:30:51 +01:00
if ( pkg_version < = 3 ) { // D0WD, S0WD, D2WD
gpio_reset_pin ( GPIO_NUM_16 ) ; // D0WD_PSRAM_CS_IO
gpio_reset_pin ( GPIO_NUM_17 ) ; // D0WD_PSRAM_CLK_IO
// IDF5.3 fix esp_gpio_reserve used in init PSRAM
esp_gpio_revoke ( BIT64 ( GPIO_NUM_16 ) | BIT64 ( GPIO_NUM_17 ) ) ;
2021-10-12 09:58:06 +01:00
}
2021-10-11 18:36:39 +01:00
}
2021-12-17 17:01:27 +00:00
# endif // CONFIG_IDF_TARGET_ESP32
# endif // ESP32
2024-05-12 20:12:08 +01:00
# ifdef USE_ESP32_WDT
enableLoopWDT ( ) ; // enabled WDT Watchdog on Arduino `loop()` - must return before 5s or called `feedLoopWDT();` - included in `yield()`
# endif // USE_ESP32_WDT
2020-12-17 15:41:04 +00:00
RtcPreInit ( ) ;
2021-01-11 16:56:18 +00:00
SettingsInit ( ) ;
2020-12-17 15:41:04 +00:00
2021-09-02 11:25:53 +01:00
# ifdef USE_EMERGENCY_RESET
EmergencyReset ( ) ;
# endif // USE_EMERGENCY_RESET
2020-10-28 16:32:07 +00:00
TasmotaGlobal . baudrate = APP_BAUDRATE ;
2020-12-07 16:03:22 +00:00
TasmotaGlobal . seriallog_timer = SERIALLOG_TIMER ;
2020-10-28 18:03:39 +00:00
TasmotaGlobal . temperature_celsius = NAN ;
2020-10-29 11:39:44 +00:00
TasmotaGlobal . blinks = 201 ;
TasmotaGlobal . wifi_state_flag = WIFI_RESTART ;
2020-10-29 12:37:09 +00:00
TasmotaGlobal . tele_period = 9999 ;
2020-10-29 12:58:50 +00:00
TasmotaGlobal . active_device = 1 ;
2020-10-30 11:29:48 +00:00
TasmotaGlobal . global_state . data = 0xF ; // Init global state (wifi_down, mqtt_down) to solve possible network issues
2023-05-19 14:20:21 +01:00
TasmotaGlobal . maxlog_level = LOG_LEVEL_DEBUG_MORE ;
2024-05-05 20:08:24 +01:00
TasmotaGlobal . seriallog_level = ( SERIAL_LOG_LEVEL > LOG_LEVEL_INFO ) ? SERIAL_LOG_LEVEL : LOG_LEVEL_INFO ; // Allow specific serial messages until config loaded and allow more logging than INFO
2023-04-19 15:17:04 +01:00
TasmotaGlobal . power_latching = 0x80000000 ;
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
2020-11-27 15:43:56 +00:00
RtcReboot . fast_reboot_count = 0 ; // Disable fast reboot and quick power cycle detection
2024-04-15 14:12:17 +01:00
# else // No FIRMWARE_MINIMAL
2020-11-27 15:43:56 +00:00
if ( ResetReason ( ) = = REASON_DEEP_SLEEP_AWAKE ) {
RtcReboot . fast_reboot_count = 0 ; // Disable fast reboot and quick power cycle detection
} else {
RtcReboot . fast_reboot_count + + ;
}
2024-04-15 14:12:17 +01:00
# endif // FIRMWARE_MINIMAL
2018-09-04 15:22:34 +01:00
RtcRebootSave ( ) ;
2018-08-30 13:27:33 +01:00
2021-01-05 10:49:13 +00:00
if ( RtcSettingsLoad ( 0 ) ) {
2020-12-07 14:33:09 +00:00
uint32_t baudrate = ( RtcSettings . baudrate / 300 ) * 300 ; // Make it a valid baudrate
if ( baudrate ) { TasmotaGlobal . baudrate = baudrate ; }
}
2017-01-28 13:41:01 +00:00
2022-05-06 13:57:03 +01:00
// Init settings and logging preparing for AddLog use
2021-06-11 15:02:49 +01:00
# ifdef PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
ESP . setIramHeap ( ) ;
2024-05-05 17:26:21 +01:00
Settings = ( TSettings * ) calloc ( 1 , sizeof ( TSettings ) ) ; // Allocate in "new" 16k heap space
2021-06-11 15:02:49 +01:00
TasmotaGlobal . log_buffer = ( char * ) malloc ( LOG_BUFFER_SIZE ) ; // Allocate in "new" 16k heap space
ESP . resetHeap ( ) ;
if ( TasmotaGlobal . log_buffer = = nullptr ) {
TasmotaGlobal . log_buffer = ( char * ) malloc ( LOG_BUFFER_SIZE ) ; // Allocate in "old" heap space as fallback
}
if ( TasmotaGlobal . log_buffer ! = nullptr ) {
TasmotaGlobal . log_buffer [ 0 ] = ' \0 ' ;
}
# endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
2021-06-11 17:14:12 +01:00
if ( Settings = = nullptr ) {
2024-05-05 17:26:21 +01:00
Settings = ( TSettings * ) calloc ( 1 , sizeof ( TSettings ) ) ;
2021-06-11 17:14:12 +01:00
}
2021-06-11 15:02:49 +01:00
2023-10-24 15:32:39 +01:00
# ifdef ESP32
# if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
# ifdef USE_USB_CDC_CONSOLE
2023-10-24 15:41:36 +01:00
bool is_connected_to_USB = false ;
2024-04-30 16:58:30 +01:00
TasConsole . setRxBufferSize ( INPUT_BUFFER_SIZE ) ;
2024-05-04 14:14:51 +01:00
TasConsole . begin ( 115200 ) ; // always start CDC to test plugged cable
# if SOC_USB_SERIAL_JTAG_SUPPORTED // Not S2
2024-04-10 10:31:18 +01:00
for ( uint32_t i = 0 ; i < 5 ; i + + ) { // wait up to 250 ms - maybe a shorter time is enough
2024-04-30 16:58:30 +01:00
is_connected_to_USB = HWCDCSerial . isPlugged ( ) ;
2023-10-24 15:32:39 +01:00
if ( is_connected_to_USB ) { break ; }
2024-04-10 10:31:18 +01:00
delay ( 50 ) ;
2023-10-24 15:32:39 +01:00
}
2023-10-24 15:41:36 +01:00
# else
is_connected_to_USB = true ; // S2
2023-10-24 15:32:39 +01:00
# endif // SOC_USB_SERIAL_JTAG_SUPPORTED
if ( is_connected_to_USB ) {
2024-04-30 16:58:30 +01:00
// TasConsole is already running
2023-10-24 15:32:39 +01:00
# if !ARDUINO_USB_MODE
USB . begin ( ) ; // This needs a serial console with DTR/DSR support
# endif // No ARDUINO_USB_MODE
TasConsole . println ( ) ;
AddLog ( LOG_LEVEL_INFO , PSTR ( " CMD: Using USB CDC " ) ) ;
} else {
2024-09-19 13:47:18 +01:00
# if SOC_USB_SERIAL_JTAG_SUPPORTED // Not S2
2024-04-30 16:58:30 +01:00
HWCDCSerial . ~ HWCDC ( ) ; // not needed, deinit CDC
2024-09-19 13:47:18 +01:00
# endif // SOC_USB_SERIAL_JTAG_SUPPORTED
2023-10-24 15:32:39 +01:00
// Init command serial console preparing for AddLog use
Serial . begin ( TasmotaGlobal . baudrate ) ;
Serial . println ( ) ;
2024-04-30 16:58:30 +01:00
TasConsole = Serial ; // Fallback
2023-10-24 15:32:39 +01:00
tasconsole_serial = true ;
AddLog ( LOG_LEVEL_INFO , PSTR ( " CMD: Fall back to serial port, no SOF packet detected on USB port " ) ) ;
}
# else // No USE_USB_CDC_CONSOLE
// Init command serial console preparing for AddLog use
Serial . begin ( TasmotaGlobal . baudrate ) ;
Serial . println ( ) ;
// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars
TasConsole = Serial ;
# endif // USE_USB_CDC_CONSOLE
# else // No ESP32C3, S2 or S3
// Init command serial console preparing for AddLog use
Serial . begin ( TasmotaGlobal . baudrate ) ;
Serial . println ( ) ;
// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars
TasConsole = Serial ;
# endif // ESP32C3, S2 or S3
2022-05-06 13:57:03 +01:00
# else // No ESP32
2023-10-24 15:32:39 +01:00
// Init command serial console preparing for AddLog use
Serial . begin ( TasmotaGlobal . baudrate ) ;
Serial . println ( ) ;
// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars
2022-05-06 13:57:03 +01:00
TasConsole = Serial ;
# endif // ESP32
// Ready for AddLog use
2021-06-13 09:43:10 +01:00
// AddLog(LOG_LEVEL_INFO, PSTR("ADR: Settings %p, Log %p"), Settings, TasmotaGlobal.log_buffer);
2021-09-01 22:06:39 +01:00
# ifdef ESP32
2023-10-04 11:47:58 +01:00
AddLog ( LOG_LEVEL_INFO , PSTR ( " HDW: %s %s " ) , GetDeviceHardwareRevision ( ) . c_str ( ) ,
2021-09-01 21:48:02 +01:00
FoundPSRAM ( ) ? ( CanUsePSRAM ( ) ? " (PSRAM) " : " (PSRAM disabled) " ) : " " ) ;
2022-12-10 12:44:16 +00:00
// AddLog(LOG_LEVEL_DEBUG, PSTR("HDW: FoundPSRAM=%i CanUsePSRAM=%i"), FoundPSRAM(), CanUsePSRAM());
2024-04-15 14:12:17 +01:00
# if !defined(HAS_PSRAM_FIX)
2021-09-01 21:48:02 +01:00
if ( FoundPSRAM ( ) & & ! CanUsePSRAM ( ) ) {
2021-07-18 18:43:33 +01:00
AddLog ( LOG_LEVEL_INFO , PSTR ( " HDW: PSRAM is disabled, requires specific compilation on this hardware (see doc) " ) ) ;
}
2024-04-15 14:12:17 +01:00
# endif // HAS_PSRAM_FIX
# else // ESP8266
2021-09-01 22:06:39 +01:00
AddLog ( LOG_LEVEL_INFO , PSTR ( " HDW: %s " ) , GetDeviceHardware ( ) . c_str ( ) ) ;
2024-04-15 14:12:17 +01:00
# endif // ESP32
2021-04-21 10:55:52 +01:00
2021-01-08 14:00:40 +00:00
# ifdef USE_UFILESYS
UfsInit ( ) ; // xdrv_50_filesystem.ino
2024-04-15 14:12:17 +01:00
# endif // USE_UFILESYS
2021-01-08 14:00:40 +00:00
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
2021-06-11 17:14:12 +01:00
TasmotaGlobal . seriallog_level = Settings - > seriallog_level ;
TasmotaGlobal . syslog_level = Settings - > syslog_level ;
2020-12-07 16:03:22 +00:00
2021-06-11 17:14:12 +01:00
TasmotaGlobal . module_changed = ( Settings - > module ! = Settings - > last_module ) ;
2020-12-07 14:33:09 +00:00
if ( TasmotaGlobal . module_changed ) {
2021-06-11 17:14:12 +01:00
Settings - > baudrate = APP_BAUDRATE / 300 ;
Settings - > serial_config = TS_SERIAL_8N1 ;
2020-12-07 14:33:09 +00:00
}
2022-11-02 10:24:24 +00:00
SetSerialInitBegin ( ) ; // Reset serial interface if current baudrate and/or config is different from requested settings
2020-12-07 14:33:09 +00:00
2020-12-07 16:03:22 +00: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
}
2021-04-22 17:10:26 +01:00
if ( ResetReason ( ) ! = REASON_DEEP_SLEEP_AWAKE ) {
# ifdef ESP8266
2021-06-11 17:14:12 +01:00
Settings - > flag4 . network_wifi = 1 ; // Make sure we're in control
2024-04-15 14:12:17 +01:00
# endif // ESP8266
2021-04-22 17:10:26 +01:00
# ifdef ESP32
2021-06-11 17:14:12 +01:00
if ( ! Settings - > flag4 . network_ethernet ) {
Settings - > flag4 . network_wifi = 1 ; // Make sure we're in control
2021-04-22 17:10:26 +01:00
}
2024-04-15 14:12:17 +01:00
# endif // ESP32
2021-04-22 17:10:26 +01:00
}
2021-06-11 17:14:12 +01:00
TasmotaGlobal . stop_flash_rotate = Settings - > flag . stop_flash_rotate ; // SetOption12 - Switch between dynamic or fixed slot flash save location
TasmotaGlobal . save_data_counter = Settings - > save_data ;
TasmotaGlobal . sleep = Settings - > sleep ;
2018-11-16 08:36:41 +00:00
# ifndef USE_EMULATION
2021-06-11 17:14:12 +01:00
Settings - > flag2 . emulation = 0 ;
2024-04-15 14:12:17 +01:00
# else // No USE_EMULATION
2019-05-20 14:09:42 +01:00
# ifndef USE_EMULATION_WEMO
2021-06-11 17:14:12 +01:00
if ( EMUL_WEMO = = Settings - > flag2 . emulation ) { Settings - > flag2 . emulation = 0 ; }
2024-04-15 14:12:17 +01:00
# endif // USE_EMULATION_WEMO
2019-05-20 14:09:42 +01:00
# ifndef USE_EMULATION_HUE
2021-06-11 17:14:12 +01:00
if ( EMUL_HUE = = Settings - > flag2 . emulation ) { Settings - > flag2 . emulation = 0 ; }
2024-04-15 14:12:17 +01:00
# endif // USE_EMULATION_HUE
2018-11-16 08:36:41 +00:00
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
2022-11-12 14:57:46 +00:00
// AddLog(LOG_LEVEL_INFO, PSTR("DBG: TasmotaGlobal size %d, data %100_H"), sizeof(TasmotaGlobal), (uint8_t*)&TasmotaGlobal);
2020-10-28 16:32:07 +00:00
2021-06-11 17:14:12 +01: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)
2021-06-11 17:14:12 +01:00
if ( RtcReboot . fast_reboot_count > Settings - > param [ P_BOOT_LOOP_OFFSET ] ) { // Restart twice
Settings - > flag3 . user_esp8285_enable = 0 ; // SetOption51 - Enable ESP8285 user GPIO's - Disable ESP8285 Generic GPIOs interfering with flash SPI
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 + + ) {
2021-06-11 17:14:12 +01:00
if ( bitRead ( Settings - > rule_stop , i ) ) {
bitWrite ( Settings - > rule_enabled , i , 0 ) ; // Disable rules causing boot loop
2019-01-30 13:34:31 +00:00
}
2018-08-30 13:27:33 +01:00
}
2022-10-27 16:52:44 +01:00
Settings - > flag4 . network_wifi = 1 ; // Enable wifi if disabled
2018-08-30 13:27:33 +01:00
}
2021-06-11 17:14:12 +01:00
if ( RtcReboot . fast_reboot_count > Settings - > param [ P_BOOT_LOOP_OFFSET ] + 2 ) { // Restarted 4 times
Settings - > rule_enabled = 0 ; // Disable all rules
2023-05-21 11:25:11 +01:00
Settings - > flag3 . shutter_mode = 0 ; // disable shutter support
2021-02-15 15:51:13 +00:00
TasmotaGlobal . no_autoexec = true ;
2018-08-30 13:47:48 +01:00
}
2021-06-11 17:14:12 +01:00
if ( RtcReboot . fast_reboot_count > Settings - > param [ P_BOOT_LOOP_OFFSET ] + 3 ) { // Restarted 5 times
for ( uint32_t i = 0 ; i < nitems ( Settings - > my_gp . io ) ; i + + ) {
Settings - > my_gp . io [ i ] = GPIO_NONE ; // Reset user defined GPIO disabling sensors
2019-01-30 13:34:31 +00:00
}
}
2021-06-11 17:14:12 +01:00
if ( RtcReboot . fast_reboot_count > Settings - > param [ P_BOOT_LOOP_OFFSET ] + 4 ) { // Restarted 6 times
Settings - > module = Settings - > fallback_module ; // Reset module to fallback module
// Settings->last_module = Settings->fallback_module;
2019-01-30 13:34:31 +00:00
}
2021-01-23 15:26:23 +00:00
AddLog ( LOG_LEVEL_INFO , PSTR ( " FRC: " D_LOG_SOME_SETTINGS_RESET " (%d) " ) , RtcReboot . fast_reboot_count ) ;
2018-08-28 09:26:33 +01:00
}
}
2021-05-23 15:50:17 +01:00
memcpy_P ( TasmotaGlobal . version , VERSION_MARKER , 1 ) ; // Dummy for compiler saving VERSION_MARKER
2023-10-04 12:52:08 +01:00
snprintf_P ( TasmotaGlobal . version , sizeof ( TasmotaGlobal . version ) , PSTR ( " %d.%d.%d " ) , TASMOTA_VERSION > > 24 & 0xff , TASMOTA_VERSION > > 16 & 0xff , TASMOTA_VERSION > > 8 & 0xff ) ; // Release version 6.3.0
if ( TASMOTA_VERSION & 0xff ) { // Development or patched version 6.3.0.10
snprintf_P ( TasmotaGlobal . version , sizeof ( TasmotaGlobal . version ) , PSTR ( " %s.%d " ) , TasmotaGlobal . version , TASMOTA_VERSION & 0xff ) ;
2020-12-07 14:33:09 +00:00
}
2021-12-31 17:23:35 +00:00
2020-12-07 14:33:09 +00:00
// Thehackbox inserts "release" or "commit number" before compiling using sed -i -e 's/PSTR("(%s)")/PSTR("(85cff52-%s)")/g' tasmota.ino
2024-02-29 12:03:41 +00:00
// Github inserts "release" or "commit number" before compiling using sed -i -e 's/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT 85cff52-/g' tasmota_version.h
snprintf_P ( TasmotaGlobal . image_name , sizeof ( TasmotaGlobal . image_name ) , PSTR ( " ( " STR ( TASMOTA_SHA_SHORT ) " %s) " ) , PSTR ( CODE_IMAGE_STR ) ) ; // Results in (85cff52-tasmota) or (release-tasmota)
2020-12-07 14:33:09 +00:00
2020-10-30 11:29:48 +00:00
Format ( TasmotaGlobal . mqtt_client , SettingsText ( SET_MQTT_CLIENT ) , sizeof ( TasmotaGlobal . mqtt_client ) ) ;
Format ( TasmotaGlobal . mqtt_topic , SettingsText ( SET_MQTT_TOPIC ) , sizeof ( TasmotaGlobal . mqtt_topic ) ) ;
2020-11-04 10:20:17 +00:00
if ( strchr ( SettingsText ( SET_HOSTNAME ) , ' % ' ) ! = nullptr ) {
2019-12-16 14:13:57 +00:00
SettingsUpdateText ( SET_HOSTNAME , WIFI_HOSTNAME ) ;
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . hostname , sizeof ( TasmotaGlobal . hostname ) - 1 , SettingsText ( SET_HOSTNAME ) , TasmotaGlobal . mqtt_topic , ESP_getChipId ( ) & 0x1FFF ) ;
2017-01-28 13:41:01 +00:00
} else {
2020-10-30 11:29:48 +00:00
snprintf_P ( TasmotaGlobal . hostname , sizeof ( TasmotaGlobal . hostname ) - 1 , SettingsText ( SET_HOSTNAME ) ) ;
2017-01-28 13:41:01 +00:00
}
2021-07-21 10:41:31 +01:00
char * s = TasmotaGlobal . hostname ;
while ( * s ) {
2021-07-26 14:10:47 +01:00
if ( ! ( isalnum ( * s ) | | ( ' . ' = = * s ) ) ) { * s = ' - ' ; } // Valid hostname chars are A..Z, a..z, 0..9, . and -
if ( ( s = = TasmotaGlobal . hostname ) & & ( ' - ' = = * s ) ) { * s = ' x ' ; } // First char cannot be a dash so replace by an x
2021-07-21 10:41:31 +01:00
s + + ;
}
snprintf_P ( TasmotaGlobal . mqtt_topic , sizeof ( TasmotaGlobal . mqtt_topic ) , ResolveToken ( TasmotaGlobal . mqtt_topic ) . c_str ( ) ) ;
2018-09-05 14:38:48 +01:00
2021-03-15 14:51:31 +00:00
RtcInit ( ) ;
2023-03-11 14:52:02 +00:00
GpioInit ( ) ; // FUNC_SETUP_RING1 -> FUNC_SETUP_RING2 -> FUNC_MODULE_INIT -> FUNC_LED_LINK
2023-01-27 14:53:40 +00:00
ButtonInit ( ) ; // FUNC_ADD_BUTTON
SwitchInit ( ) ; // FUNC_ADD_SWITCH
2021-04-06 14:23:07 +01:00
# ifdef ROTARY_V1
RotaryInit ( ) ;
# endif // ROTARY_V1
2021-05-25 17:53:10 +01:00
# ifdef USE_BERRY
2022-02-14 13:53:42 +00:00
if ( ! TasmotaGlobal . no_autoexec ) {
2023-01-27 14:53:40 +00:00
BerryInit ( ) ; // Load preinit.be
2022-02-14 13:53:42 +00:00
}
2024-04-15 14:12:17 +01:00
# endif // USE_BERRY
2021-04-06 14:23:07 +01:00
2023-01-27 14:53:40 +00:00
XdrvXsnsCall ( FUNC_PRE_INIT ) ; // FUNC_PRE_INIT
2018-09-05 14:38:48 +01:00
2021-11-03 10:58:05 +00:00
TasmotaGlobal . init_state = INIT_GPIOS ;
2023-01-27 14:53:40 +00:00
SetPowerOnState ( ) ; // FUNC_SET_POWER -> FUNC_SET_DEVICE_POWER
2017-10-18 17:22:34 +01:00
WifiConnect ( ) ;
2017-01-28 13:41:01 +00:00
2021-07-19 18:24:53 +01:00
AddLog ( LOG_LEVEL_INFO , PSTR ( D_PROJECT " %s - %s " D_VERSION " %s%s- " ARDUINO_CORE_RELEASE " (%s) " ) ,
2021-01-18 20:48:04 +00:00
PSTR ( PROJECT ) , SettingsText ( SET_DEVICENAME ) , TasmotaGlobal . version , TasmotaGlobal . image_name , GetBuildDateAndTime ( ) . c_str ( ) ) ;
2019-02-08 13:55:45 +00:00
# ifdef FIRMWARE_MINIMAL
2021-01-23 15:26:23 +00:00
AddLog ( 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
2023-04-27 15:35:47 +01:00
# ifdef ESP8266
2018-03-21 16:58:39 +00:00
# ifdef USE_ARDUINO_OTA
ArduinoOTAInit ( ) ;
# endif // USE_ARDUINO_OTA
2023-04-27 15:35:47 +01:00
# endif // ESP8266
2018-03-21 16:58:39 +00:00
2023-01-27 14:53:40 +00:00
XdrvXsnsCall ( FUNC_INIT ) ; // FUNC_INIT
2020-06-16 09:36:16 +01:00
# ifdef USE_SCRIPT
2021-06-11 17:14:12 +01:00
if ( bitRead ( Settings - > rule_enabled , 0 ) ) Run_Scripter ( " >BS " , 3 , 0 ) ;
2024-04-15 14:12:17 +01:00
# endif // USE_SCRIPT
2020-06-14 11:36:44 +01:00
2020-10-29 12:58:50 +00:00
TasmotaGlobal . rules_flag . system_init = 1 ;
2017-01-28 13:41:01 +00:00
}
2020-05-11 15:45:22 +01:00
void BacklogLoop ( void ) {
2020-11-27 13:43:45 +00:00
if ( TimeReached ( TasmotaGlobal . backlog_timer ) ) {
2020-10-30 11:29:48 +00:00
if ( ! BACKLOG_EMPTY & & ! TasmotaGlobal . backlog_mutex ) {
TasmotaGlobal . backlog_mutex = true ;
2020-10-15 11:32:40 +01:00
bool nodelay = false ;
do {
2024-01-21 21:07:49 +00:00
char * cmd = * backlog . head ( ) ;
backlog . removeHead ( ) ;
/*
// This adds 32 bytes
char * cmd = * backlog . removeHead ( ) ;
*/
2024-01-20 16:18:03 +00:00
if ( ! strncasecmp_P ( cmd , PSTR ( D_CMND_NODELAY ) , strlen ( D_CMND_NODELAY ) ) ) {
2024-01-20 21:45:24 +00:00
free ( cmd ) ;
2024-01-20 16:18:03 +00:00
nodelay = true ;
} else {
2024-07-08 14:53:15 +01:00
TasmotaGlobal . no_mqtt_response = TasmotaGlobal . backlog_no_mqtt_response ;
2024-01-20 16:18:03 +00:00
ExecuteCommand ( cmd , SRC_BACKLOG ) ;
2024-01-20 21:45:24 +00:00
free ( cmd ) ;
2024-01-20 16:18:03 +00:00
if ( nodelay | | TasmotaGlobal . backlog_nodelay ) {
TasmotaGlobal . backlog_timer = millis ( ) ; // Reset backlog_timer which has been set by ExecuteCommand (CommandHandler)
}
break ;
}
} while ( ! BACKLOG_EMPTY ) ;
2020-10-30 11:29:48 +00:00
TasmotaGlobal . backlog_mutex = false ;
2019-10-04 13:46:31 +01:00
}
2021-04-09 13:00:09 +01:00
if ( BACKLOG_EMPTY ) {
2021-04-07 16:55:33 +01:00
TasmotaGlobal . backlog_nodelay = false ;
}
2019-10-04 13:46:31 +01:00
}
}
2020-05-11 15:45:22 +01:00
void SleepDelay ( uint32_t mseconds ) {
2021-04-09 13:00:09 +01:00
if ( ! TasmotaGlobal . backlog_nodelay & & mseconds ) {
2021-01-03 15:30:45 +00:00
uint32_t wait = millis ( ) + mseconds ;
2023-01-04 14:29:27 +00:00
while ( ! TimeReached ( wait ) & & ! Serial . available ( ) ) { // We need to service serial buffer ASAP as otherwise we get uart buffer overrun
XdrvXsnsCall ( FUNC_SLEEP_LOOP ) ; // Main purpose is reacting ASAP on serial data availability or interrupt handling (ADE7880)
delay ( 1 ) ;
2020-05-11 15:45:22 +01:00
}
} else {
delay ( 0 ) ;
}
}
2021-01-10 16:46:30 +00:00
void Scheduler ( void ) {
2022-11-11 08:57:00 +00:00
XdrvXsnsCall ( FUNC_LOOP ) ;
2018-02-27 13:59:46 +00:00
2021-01-10 16:46:30 +00:00
// check LEAmDNS.h
// MDNS.update() needs to be called in main loop
# ifdef ESP8266 // Not needed with esp32 mdns
# ifdef USE_DISCOVERY
# ifdef USE_WEBSERVER
# ifdef WEBSERVER_ADVERTISE
MdnsUpdate ( ) ;
# endif // WEBSERVER_ADVERTISE
# endif // USE_WEBSERVER
# endif // USE_DISCOVERY
# endif // ESP8266
2017-10-18 17:22:34 +01:00
OsWatchLoop ( ) ;
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
2021-01-03 14:28:52 +00:00
static uint32_t state_50msecond = 0 ; // State 50msecond timer
2018-08-26 14:42:35 +01:00
if ( TimeReached ( state_50msecond ) ) {
SetNextTimeInterval ( state_50msecond , 50 ) ;
2024-01-15 22:58:33 +00:00
LoopTimedCmnd ( ) ;
2020-07-01 09:22:20 +01:00
# ifdef ROTARY_V1
RotaryHandler ( ) ;
2020-07-01 09:24:46 +01:00
# endif // ROTARY_V1
2022-11-11 08:57:00 +00:00
XdrvXsnsCall ( FUNC_EVERY_50_MSECOND ) ;
2018-08-26 14:42:35 +01:00
}
2020-10-28 11:40:52 +00:00
2021-01-03 14:28:52 +00:00
static uint32_t state_100msecond = 0 ; // State 100msecond timer
2018-08-26 14:42:35 +01:00
if ( TimeReached ( state_100msecond ) ) {
SetNextTimeInterval ( state_100msecond , 100 ) ;
Every100mSeconds ( ) ;
2022-11-11 08:57:00 +00:00
XdrvXsnsCall ( FUNC_EVERY_100_MSECOND ) ;
2018-08-26 14:42:35 +01:00
}
2020-10-28 11:40:52 +00:00
2021-01-03 14:28:52 +00:00
static uint32_t state_250msecond = 0 ; // State 250msecond timer
2018-08-26 14:42:35 +01:00
if ( TimeReached ( state_250msecond ) ) {
SetNextTimeInterval ( state_250msecond , 250 ) ;
Every250mSeconds ( ) ;
2022-11-11 08:57:00 +00:00
XdrvXsnsCall ( FUNC_EVERY_250_MSECOND ) ;
2019-10-18 11:47:22 +01:00
}
2020-10-28 11:40:52 +00:00
2021-01-03 14:28:52 +00:00
static uint32_t state_second = 0 ; // State second timer
2019-10-18 11:47:22 +01:00
if ( TimeReached ( state_second ) ) {
SetNextTimeInterval ( state_second , 1000 ) ;
PerformEverySecond ( ) ;
2024-01-29 16:16:38 +00:00
XdrvCall ( FUNC_ACTIVE ) ;
2022-11-11 08:57:00 +00:00
XdrvXsnsCall ( FUNC_EVERY_SECOND ) ;
2018-08-26 14:42:35 +01:00
}
2018-02-27 13:59:46 +00:00
2020-10-30 11:29:48 +00:00
if ( ! TasmotaGlobal . serial_local ) { SerialInput ( ) ; }
2022-05-06 13:57:03 +01:00
# ifdef ESP32
if ( ! tasconsole_serial ) { TasConsoleInput ( ) ; }
# endif // ESP32
2017-01-28 13:41:01 +00:00
2023-04-27 15:35:47 +01:00
# ifdef ESP8266
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
2023-04-27 15:35:47 +01:00
# endif // ESP8266
2023-12-19 11:29:39 +00:00
2023-12-19 11:45:13 +00:00
# ifndef SYSLOG_UPDATE_SECOND
2023-12-19 11:29:39 +00:00
SyslogAsync ( false ) ;
2023-12-19 11:45:13 +00:00
# endif // SYSLOG_UPDATE_SECOND
2021-01-10 16:46:30 +00:00
}
void loop ( void ) {
uint32_t my_sleep = millis ( ) ;
Scheduler ( ) ;
2018-03-21 16:58:39 +00:00
2018-11-18 14:02:52 +00:00
uint32_t my_activity = millis ( ) - my_sleep ;
2018-12-01 17:53:42 +00:00
2022-03-07 10:37:48 +00:00
if ( Settings - > flag3 . sleep_normal ) { // SetOption60 - Enable normal sleep instead of dynamic sleep
2020-05-11 15:45:22 +01:00
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
2021-01-03 14:28:52 +00:00
SleepDelay ( TasmotaGlobal . sleep ) ; // https://github.com/esp8266/Arduino/issues/2021
2018-11-22 11:25:18 +00:00
} else {
2020-10-29 15:16:34 +00:00
if ( my_activity < ( uint32_t ) TasmotaGlobal . sleep ) {
SleepDelay ( ( uint32_t ) TasmotaGlobal . sleep - my_activity ) ; // Provide time for background tasks like wifi
2018-12-01 16:47:25 +00:00
} else {
2020-10-30 11:29:48 +00:00
if ( TasmotaGlobal . global_state . network_down ) {
2021-10-17 20:25:55 +01:00
SleepDelay ( my_activity / 2 ) ; // If wifi down and my_activity > setoption36 then force loop delay to 1/2 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-10-29 15:16:34 +00:00
uint32_t loop_delay = TasmotaGlobal . sleep ;
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 ;
2020-10-28 16:32:07 +00:00
TasmotaGlobal . loop_load_avg = TasmotaGlobal . loop_load_avg - ( TasmotaGlobal . 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
}