diff --git a/docs/source/Reference/SystemVariable.rst b/docs/source/Reference/SystemVariable.rst index 54c9d7bd8..1a88a7cb9 100644 --- a/docs/source/Reference/SystemVariable.rst +++ b/docs/source/Reference/SystemVariable.rst @@ -28,6 +28,19 @@ More uses of these system variables can be seen in the rules section and formula - ESP_Easy - Name as configured through the webgui. - + * - ``%bootcause%`` + - 0 + - (re)boot cause as integer value, to be used in rules. + + * ``0`` = manual reboot (reset btn) + * ``1`` = cold boot + * ``2`` = deep sleep + * ``3`` = soft restart + * ``10`` = ext Watchdog + * ``11`` = SW Watchdog + * ``12`` = Exception + * ``20`` = Power unstable + - Yes * - ``%systime%`` - 01:23:54 - Current time if NTP is enabled (hh:mm:ss, hh:mm prior to v2.0). @@ -50,7 +63,13 @@ More uses of these system variables can be seen in the rules section and formula - * - ``%sunrise%`` - 5:04 - - Time of sunrise on current day, when NTP is active and coordinates set. If you want to postpone or trigger something earlier but still using the sunset/sunrise time as reference you can use this syntax: '''%sunrise+10m%''' or '''%sunset-1h%'''. Where the offset must be a integer with the prefix "m" for minutes or "h" for hours. Minus or plus is used to tell if the offset is prior or later than the sunset/sunrise. Any other letter positioned between the number and '%' is regarded as "seconds" notation. + - Time of sunrise on current day, when NTP is active and coordinates set. + If you want to postpone or trigger something earlier but still using the sunset/sunrise time as reference you can use this syntax: + + * ``%sunrise+10m%`` + * ``%sunset-1h%`` + + Where the offset must be a integer with the postfix "m" for minutes or "h" for hours. Minus or plus is used to tell if the offset is prior or later than the sunset/sunrise. Any other letter positioned between the number and '%' is regarded as "seconds" notation. - * - ``%sunset%`` - 22:03 @@ -98,7 +117,9 @@ More uses of these system variables can be seen in the rules section and formula - * - ``%unixtime%`` - 1521731277 - - Unix time (seconds since epoch, 1970-01-01 00:00:00)
Example: 1521731277 = 2018-03-22 15:07:57 + - Unix time (seconds since epoch, 1970-01-01 00:00:00) + + Example: 1521731277 = 2018-03-22 15:07:57 - Yes * - ``%uptime%`` - 3244 @@ -134,7 +155,9 @@ More uses of these system variables can be seen in the rules section and formula - Yes * - ``%vcc%`` - 5.2 - - VCC value, this is only available in the VCC versions of FW. If the variable output is "-1.0" it means that the VCC is not activated or that a reading has not been completed (could be due to incorrect cabling, interval set to "0", etc. etc.). + - VCC value, this is only available in the VCC builds of FW (with "VCC" in the file name). + + If the variable output is "-1.0" it means that the VCC is not activated or that a reading has not been completed (could be due to incorrect cabling, interval set to "0", etc. etc.). - Yes * - ``%mac%`` - 00:14:22:01:23:45 diff --git a/src/ESPEasy.ino b/src/ESPEasy.ino index aaf35e851..4a2feb4ad 100644 --- a/src/ESPEasy.ino +++ b/src/ESPEasy.ino @@ -264,6 +264,11 @@ void setup() log += FreeMem(); addLog(LOG_LEVEL_INFO, log); + readBootCause(); + + log = F("INIT : "); + log += getLastBootCauseString(); + #ifdef ESP8266 // Our ESP32 code does not yet support RTC, so separate this in code for ESP8266 and ESP32 if (readFromRTC()) @@ -273,17 +278,14 @@ void setup() lastMixedSchedulerId_beforereboot = RTC.lastMixedSchedulerId; readUserVarFromRTC(); - if (RTC.deepSleepState == 1) + if (RTC.deepSleepState != 1) { - log = F("INIT : Rebooted from deepsleep #"); - lastBootCause = BOOT_CAUSE_DEEP_SLEEP; - } - else { node_time.restoreLastKnownUnixTime(RTC.lastSysTime, RTC.deepSleepState); - log = F("INIT : Warm boot #"); } + log += F(" #"); log += RTC.bootCounter; + #ifndef BUILD_NO_DEBUG log += F(" Last Action before Reboot: "); log += ESPEasy_Scheduler::decodeSchedulerId(lastMixedSchedulerId_beforereboot); @@ -303,19 +305,6 @@ void setup() } #endif // ESP8266 - #ifdef ESP32 - if (rtc_get_reset_reason( (RESET_REASON) 0) == DEEPSLEEP_RESET) { - log = F("INIT : Rebooted from deepsleep #"); - lastBootCause = BOOT_CAUSE_DEEP_SLEEP; - } else { - // cold boot situation - if (lastBootCause == BOOT_CAUSE_MANUAL_REBOOT) // only set this if not set earlier during boot stage. - lastBootCause = BOOT_CAUSE_COLD_BOOT; - log = F("INIT : Cold Boot"); - } - - #endif // ESP32 - log += F(" - Restart Reason: "); log += getResetReasonString(); diff --git a/src/src/Globals/Statistics.h b/src/src/Globals/Statistics.h index 695d27c7b..dfbf30a6e 100644 --- a/src/src/Globals/Statistics.h +++ b/src/src/Globals/Statistics.h @@ -7,10 +7,15 @@ class String; + #define BOOT_CAUSE_MANUAL_REBOOT 0 #define BOOT_CAUSE_COLD_BOOT 1 #define BOOT_CAUSE_DEEP_SLEEP 2 +#define BOOT_CAUSE_SOFT_RESTART 3 #define BOOT_CAUSE_EXT_WD 10 +#define BOOT_CAUSE_SW_WATCHDOG 11 +#define BOOT_CAUSE_EXCEPTION 12 +#define BOOT_CAUSE_POWER_UNSTABLE 20 #ifndef BUILD_NO_RAM_TRACKER extern uint32_t lowestRAM; diff --git a/src/src/Helpers/Hardware.cpp b/src/src/Helpers/Hardware.cpp index 330d35711..e55c12a5b 100644 --- a/src/src/Helpers/Hardware.cpp +++ b/src/src/Helpers/Hardware.cpp @@ -526,6 +526,61 @@ uint8_t getChipRevision() { return rev; } +#ifdef ESP8266 +void readBootCause() { + lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; + const rst_info * resetInfo = ESP.getResetInfoPtr(); + if (resetInfo != nullptr) { + switch(resetInfo->reason) { + // normal startup by power on + case REASON_DEFAULT_RST: lastBootCause = BOOT_CAUSE_COLD_BOOT; break; + // hardware watch dog reset + case REASON_WDT_RST: lastBootCause = BOOT_CAUSE_EXT_WD; break; + // exception reset, GPIO status won’t change + case REASON_EXCEPTION_RST: lastBootCause = BOOT_CAUSE_EXCEPTION; break; + // software watch dog reset, GPIO status won’t change + case REASON_SOFT_WDT_RST: lastBootCause = BOOT_CAUSE_SW_WATCHDOG; break; + // software restart ,system_restart , GPIO status won’t change + case REASON_SOFT_RESTART: lastBootCause = BOOT_CAUSE_SOFT_RESTART; break; + // wake up from deep-sleep + case REASON_DEEP_SLEEP_AWAKE: lastBootCause = BOOT_CAUSE_DEEP_SLEEP; break; + // external system reset + case REASON_EXT_SYS_RST: lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; break; + default: + break; + } + + } + +} +#endif + +#ifdef ESP32 +void readBootCause() { + lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; + switch (rtc_get_reset_reason(0)) { + case NO_MEAN: break; + case POWERON_RESET: lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; break; + case SW_RESET: lastBootCause = BOOT_CAUSE_SOFT_RESTART; break; + case OWDT_RESET: lastBootCause = BOOT_CAUSE_SW_WATCHDOG; break; + case DEEPSLEEP_RESET: lastBootCause = BOOT_CAUSE_DEEP_SLEEP; break; + case SDIO_RESET: lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; break; + case TG0WDT_SYS_RESET: + case TG1WDT_SYS_RESET: + case RTCWDT_SYS_RESET: lastBootCause = BOOT_CAUSE_EXT_WD; break; + case INTRUSION_RESET: + case TGWDT_CPU_RESET: + case SW_CPU_RESET: lastBootCause = BOOT_CAUSE_SOFT_RESTART; break; // Both call to ESP.reset() and on exception crash + case RTCWDT_CPU_RESET: lastBootCause = BOOT_CAUSE_EXT_WD; break; + case EXT_CPU_RESET: lastBootCause = BOOT_CAUSE_MANUAL_REBOOT; break; // reset button or cold boot, only for core 1 + case RTCWDT_BROWN_OUT_RESET: lastBootCause = BOOT_CAUSE_POWER_UNSTABLE; break; + case RTCWDT_RTC_RESET: lastBootCause = BOOT_CAUSE_COLD_BOOT; break; + } +} +#endif + + + /********************************************************************************************\ Hardware specific configurations \*********************************************************************************************/ diff --git a/src/src/Helpers/Hardware.h b/src/src/Helpers/Hardware.h index ca76b2a4f..314218676 100644 --- a/src/src/Helpers/Hardware.h +++ b/src/src/Helpers/Hardware.h @@ -77,6 +77,12 @@ String getChipModel(); uint8_t getChipRevision(); +/********************************************************************************************\ + Boot information + \*********************************************************************************************/ +void readBootCause(); + + /********************************************************************************************\ Hardware specific configurations \*********************************************************************************************/ diff --git a/src/src/Helpers/StringGenerator_System.cpp b/src/src/Helpers/StringGenerator_System.cpp index 1ea7ac3c4..0f8e8bf74 100644 --- a/src/src/Helpers/StringGenerator_System.cpp +++ b/src/src/Helpers/StringGenerator_System.cpp @@ -39,13 +39,14 @@ String getMQTT_state() { String getLastBootCauseString() { switch (lastBootCause) { - case BOOT_CAUSE_MANUAL_REBOOT: return F("Manual reboot"); - case BOOT_CAUSE_DEEP_SLEEP: // nobody should ever see this, since it should sleep again right away. - return F("Deep sleep"); - case BOOT_CAUSE_COLD_BOOT: - return F("Cold boot"); - case BOOT_CAUSE_EXT_WD: - return F("External Watchdog"); + case BOOT_CAUSE_MANUAL_REBOOT: return F("Manual Reboot"); + case BOOT_CAUSE_DEEP_SLEEP: return F("Deep Sleep"); + case BOOT_CAUSE_COLD_BOOT: return F("Cold Boot"); + case BOOT_CAUSE_EXT_WD: return F("External Watchdog"); + case BOOT_CAUSE_SOFT_RESTART: return F("Soft Reboot"); + case BOOT_CAUSE_SW_WATCHDOG: return F("SW Watchdog"); + case BOOT_CAUSE_EXCEPTION: return F("Exception"); + case BOOT_CAUSE_POWER_UNSTABLE: return F("PWR Unstable"); // ESP32 only } return getUnknownString(); } diff --git a/src/src/Helpers/SystemVariables.cpp b/src/src/Helpers/SystemVariables.cpp index ec7c13a28..55fa5e189 100644 --- a/src/src/Helpers/SystemVariables.cpp +++ b/src/src/Helpers/SystemVariables.cpp @@ -19,6 +19,7 @@ #include "../Globals/NetworkState.h" #include "../Globals/RuntimeData.h" #include "../Globals/Settings.h" +#include "../Globals/Statistics.h" #include "../Helpers/CompiletimeDefines.h" #include "../Helpers/Hardware.h" @@ -87,6 +88,7 @@ void SystemVariables::parseSystemVariables(String& s, boolean useURLencode) switch (enumval) { + case BOOT_CAUSE: value = String(lastBootCause); break; // Integer value to be used in rules case BSSID: value = String((WiFiEventData.WiFiDisconnected()) ? F("00:00:00:00:00:00") : WiFi.BSSIDstr()); break; case CR: value = "\r"; break; case IP: value = getValue(LabelType::IP_ADDRESS); break; @@ -258,6 +260,7 @@ SystemVariables::Enum SystemVariables::nextReplacementEnum(const String& str, Sy String SystemVariables::toString(SystemVariables::Enum enumval) { switch (enumval) { + case Enum::BOOT_CAUSE: return F("%bootcause%"); case Enum::BSSID: return F("%bssid%"); case Enum::CR: return F("%CR%"); case Enum::IP4: return F("%ip4%"); diff --git a/src/src/Helpers/SystemVariables.h b/src/src/Helpers/SystemVariables.h index 9fdfa4a0f..deebfa09f 100644 --- a/src/src/Helpers/SystemVariables.h +++ b/src/src/Helpers/SystemVariables.h @@ -11,6 +11,7 @@ public: enum Enum { // For optmization, keep enums sorted alfabetically + BOOT_CAUSE, BSSID, CR, IP, diff --git a/src/src/WebServer/SysVarPage.cpp b/src/src/WebServer/SysVarPage.cpp index d76eaa804..467c2f9b2 100644 --- a/src/src/WebServer/SysVarPage.cpp +++ b/src/src/WebServer/SysVarPage.cpp @@ -80,6 +80,7 @@ void handle_sysvars() { addSysVar_enum_html(SystemVariables::SYSHEAP); addSysVar_enum_html(SystemVariables::SYSSTACK); addSysVar_enum_html(SystemVariables::SYSNAME); + addSysVar_enum_html(SystemVariables::BOOT_CAUSE); #if FEATURE_ADC_VCC addSysVar_enum_html(SystemVariables::VCC); #endif // if FEATURE_ADC_VCC