diff --git a/code/espurna/button.cpp b/code/espurna/button.cpp index ef420e65..197a85f1 100644 --- a/code/espurna/button.cpp +++ b/code/espurna/button.cpp @@ -549,13 +549,11 @@ void buttonEvent(unsigned char id, button_event_t event) { break; case ButtonAction::Reset: - deferredReset(100, CUSTOM_RESET_HARDWARE); + deferredReset(100, CustomResetReason::Button); break; case ButtonAction::FactoryReset: - DEBUG_MSG_P(PSTR("\n\nFACTORY RESET\n\n")); - resetSettings(); - deferredReset(100, CUSTOM_RESET_FACTORY); + factoryReset(); break; case ButtonAction::Wps: diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index ed8d1039..bf9da812 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -252,23 +252,6 @@ #define LIGHT_EFFECT_FADE 3 #define LIGHT_EFFECT_SMOOTH 4 -//------------------------------------------------------------------------------ -// RESET -//------------------------------------------------------------------------------ - -#define CUSTOM_RESET_HARDWARE 1 // Reset from hardware button -#define CUSTOM_RESET_WEB 2 // Reset from web interface -#define CUSTOM_RESET_TERMINAL 3 // Reset from terminal -#define CUSTOM_RESET_MQTT 4 // Reset via MQTT -#define CUSTOM_RESET_RPC 5 // Reset via RPC (HTTP) -#define CUSTOM_RESET_OTA 6 // Reset after successful OTA update -#define CUSTOM_RESET_HTTP 7 // Reset via HTTP GET -#define CUSTOM_RESET_NOFUSS 8 // Reset after successful NOFUSS update -#define CUSTOM_RESET_UPGRADE 9 // Reset after update from web interface -#define CUSTOM_RESET_FACTORY 10 // Factory reset from terminal - -#define CUSTOM_RESET_MAX 10 - //------------------------------------------------------------------------------ // ENVIRONMENTAL //------------------------------------------------------------------------------ diff --git a/code/espurna/curtain_kingart.cpp b/code/espurna/curtain_kingart.cpp index c9d13fb7..6cbc89ab 100644 --- a/code/espurna/curtain_kingart.cpp +++ b/code/espurna/curtain_kingart.cpp @@ -343,7 +343,7 @@ void _KACurtainResult() { if (buffer.indexOf("enterESPTOUCH") > 0) { wifiStartAP(); } else if (buffer.indexOf("exitESPTOUCH") > 0) { - deferredReset(100, CUSTOM_RESET_HARDWARE); + deferredReset(100, CustomResetReason::Hardware); } else { //In any other case, update as it could be a move action curtainUpdateUI(); } diff --git a/code/espurna/nofuss.cpp b/code/espurna/nofuss.cpp index 69b6e572..cf5b33d8 100644 --- a/code/espurna/nofuss.cpp +++ b/code/espurna/nofuss.cpp @@ -168,7 +168,7 @@ void nofussSetup() { #endif // TODO: NoFUSS will reset the board after this callback returns. // Maybe this should be optional - customResetReason(CUSTOM_RESET_NOFUSS); + customResetReason(CustomResetReason::Ota); nice_delay(100); } diff --git a/code/espurna/ota.cpp b/code/espurna/ota.cpp index 2a94ff5f..c230e2bd 100644 --- a/code/espurna/ota.cpp +++ b/code/espurna/ota.cpp @@ -23,7 +23,7 @@ void otaPrintError() { } } -bool otaFinalize(size_t size, int reason, bool evenIfRemaining) { +bool otaFinalize(size_t size, CustomResetReason reason, bool evenIfRemaining) { if (Update.isRunning() && Update.end(evenIfRemaining)) { DEBUG_MSG_P(PSTR("[OTA] Success: %7u bytes\n"), size); deferredReset(500, reason); @@ -106,7 +106,7 @@ void otaSetup() { if ((0xA55A == rtcmem[64]) && (0xA55A == rtcmem[68])) { DEBUG_MSG_P(PSTR("[OTA] Detected TASMOTA OTA, resetting the device...\n")); rtcmem[64] = rtcmem[68] = 0; - customResetReason(CUSTOM_RESET_TERMINAL); + customResetReason(CustomResetReason::Factory); resetSettings(); eraseSDKConfig(); *((int*) 0) = 0; diff --git a/code/espurna/ota.h b/code/espurna/ota.h index fe6e7aa2..8ba71d8d 100644 --- a/code/espurna/ota.h +++ b/code/espurna/ota.h @@ -40,7 +40,7 @@ void otaClientSetup(); void otaSetup(); void otaPrintError(); -bool otaFinalize(size_t size, int reason, bool evenIfRemaining = false); +bool otaFinalize(size_t size, CustomResetReason reason, bool evenIfRemaining = false); // Helper methods from UpdaterClass that need to be called manually for async mode, // because we are not using Stream interface to feed it data. diff --git a/code/espurna/ota_arduinoota.cpp b/code/espurna/ota_arduinoota.cpp index 61a15f97..9e1987fd 100644 --- a/code/espurna/ota_arduinoota.cpp +++ b/code/espurna/ota_arduinoota.cpp @@ -57,7 +57,7 @@ void _arduinoOtaOnEnd() { #endif // Note: ArduinoOTA will reset the board after this callback returns. - customResetReason(CUSTOM_RESET_OTA); + customResetReason(CustomResetReason::Ota); nice_delay(100); } diff --git a/code/espurna/ota_asynctcp.cpp b/code/espurna/ota_asynctcp.cpp index 0bc92cdb..832abf25 100644 --- a/code/espurna/ota_asynctcp.cpp +++ b/code/espurna/ota_asynctcp.cpp @@ -70,7 +70,7 @@ void _otaClientDisconnect() { void _otaClientOnDisconnect(void* arg, AsyncClient* client) { DEBUG_MSG_P(PSTR("\n")); - otaFinalize(reinterpret_cast(arg)->size, CUSTOM_RESET_OTA, true); + otaFinalize(reinterpret_cast(arg)->size, CustomResetReason::Ota, true); schedule_function(_otaClientDisconnect); } diff --git a/code/espurna/ota_httpupdate.cpp b/code/espurna/ota_httpupdate.cpp index 7983dc62..c9fa25f5 100644 --- a/code/espurna/ota_httpupdate.cpp +++ b/code/espurna/ota_httpupdate.cpp @@ -139,7 +139,7 @@ void _otaClientRunUpdater(__attribute__((unused)) WiFiClient* client, const Stri break; case HTTP_UPDATE_OK: DEBUG_MSG_P(PSTR("[OTA] Done, restarting...")); - deferredReset(500, CUSTOM_RESET_OTA); // wait a bit more than usual + deferredReset(500, CustomResetReason::Ota); // wait a bit more than usual break; } diff --git a/code/espurna/ota_web.cpp b/code/espurna/ota_web.cpp index 2b2a7737..84db5a96 100644 --- a/code/espurna/ota_web.cpp +++ b/code/espurna/ota_web.cpp @@ -128,7 +128,7 @@ void _onUpgradeFile(AsyncWebServerRequest *request, String filename, size_t inde } if (final) { - otaFinalize(index + len, CUSTOM_RESET_UPGRADE, true); + otaFinalize(index + len, CustomResetReason::Ota, true); } else { otaProgress(index + len); } diff --git a/code/espurna/rpc.cpp b/code/espurna/rpc.cpp index 970027b5..77f8f91d 100644 --- a/code/espurna/rpc.cpp +++ b/code/espurna/rpc.cpp @@ -21,7 +21,7 @@ bool rpcHandleAction(const String& action) { if (action.equals("reboot")) { result = true; schedule_function([]() { - deferredReset(100, CUSTOM_RESET_RPC); + deferredReset(100, CustomResetReason::Rpc); }); } else if (action.equals("heartbeat")) { result = true; diff --git a/code/espurna/rpnrules.cpp b/code/espurna/rpnrules.cpp index f7bba481..ac6af30f 100644 --- a/code/espurna/rpnrules.cpp +++ b/code/espurna/rpnrules.cpp @@ -807,7 +807,7 @@ void _rpnInit() { rpn_operator_set(_rpn_ctxt, "reset", 0, [](rpn_context & ctxt) -> rpn_error { static bool once = ([]() { - deferredReset(100, CUSTOM_RESET_TERMINAL); + deferredReset(100, CustomResetReason::Rule); return true; })(); return once diff --git a/code/espurna/settings.cpp b/code/espurna/settings.cpp index d4cdc69c..32e9afd6 100644 --- a/code/espurna/settings.cpp +++ b/code/espurna/settings.cpp @@ -541,22 +541,22 @@ void settingsSetup() { terminalOK(ctx); }); - terminalRegisterCommand(F("RELOAD"), [](const terminal::CommandContext&) { + terminalRegisterCommand(F("RELOAD"), [](const terminal::CommandContext& ctx) { espurnaReload(); - terminalOK(); + terminalOK(ctx); }); - terminalRegisterCommand(F("FACTORY.RESET"), [](const terminal::CommandContext&) { - resetSettings(); - terminalOK(); + terminalRegisterCommand(F("FACTORY.RESET"), [](const terminal::CommandContext& ctx) { + factoryReset(); + terminalOK(ctx); }); - #if not SETTINGS_AUTOSAVE - terminalRegisterCommand(F("SAVE"), [](const terminal::CommandContext&) { - eepromCommit(); - terminalOK(); - }); - #endif +#if not SETTINGS_AUTOSAVE + terminalRegisterCommand(F("SAVE"), [](const terminal::CommandContext& ctx) { + eepromCommit(); + terminalOK(ctx); + }); +#endif } diff --git a/code/espurna/system.cpp b/code/espurna/system.cpp index 48c823c0..05a9c9a3 100644 --- a/code/espurna/system.cpp +++ b/code/espurna/system.cpp @@ -50,16 +50,16 @@ void systemStabilityCounter(uint8_t count) { Rtcmem->sys = data.value; } -uint8_t _systemResetReason() { +CustomResetReason _systemRtcmemResetReason() { system_rtcmem_t data; data.value = Rtcmem->sys; - return data.packed.reset_reason; + return static_cast(data.packed.reset_reason); } -void _systemResetReason(uint8_t reason) { +void _systemRtcmemResetReason(CustomResetReason reason) { system_rtcmem_t data; data.value = Rtcmem->sys; - data.packed.reset_reason = reason; + data.packed.reset_reason = static_cast(reason); Rtcmem->sys = data.value; } @@ -116,39 +116,90 @@ void systemCheckLoop() { // ----------------------------------------------------------------------------- // Reset // ----------------------------------------------------------------------------- + Ticker _defer_reset; -uint8_t _reset_reason = 0; +auto _reset_reason = CustomResetReason::None; + +String customResetReasonToPayload(CustomResetReason reason) { + const __FlashStringHelper* ptr { nullptr }; + switch (reason) { + case CustomResetReason::None: + ptr = F("None"); + break; + case CustomResetReason::Button: + ptr = F("Hardware button"); + break; + case CustomResetReason::Factory: + ptr = F("Factory reset"); + break; + case CustomResetReason::Hardware: + ptr = F("Reboot from a Hardware request"); + break; + case CustomResetReason::Mqtt: + ptr = F("Reboot from MQTT"); + break; + case CustomResetReason::Ota: + ptr = F("Reboot after a successful OTA update"); + break; + case CustomResetReason::Rpc: + ptr = F("Reboot from a RPC action"); + break; + case CustomResetReason::Rule: + ptr = F("Reboot from an automation rule"); + break; + case CustomResetReason::Scheduler: + ptr = F("Reboot from a scheduler action"); + break; + case CustomResetReason::Terminal: + ptr = F("Reboot from a terminal command"); + break; + case CustomResetReason::Web: + ptr = F("Reboot from web interface"); + break; + } + + return String(ptr); +} // system_get_rst_info() result is cached by the Core init for internal use uint32_t systemResetReason() { return resetInfo.reason; } -void customResetReason(unsigned char reason) { +void customResetReason(CustomResetReason reason) { _reset_reason = reason; - _systemResetReason(reason); + _systemRtcmemResetReason(reason); } -unsigned char customResetReason() { - static unsigned char status = 255; - if (status == 255) { - if (rtcmemStatus()) status = _systemResetReason(); - if (status > 0) customResetReason(0); - if (status > CUSTOM_RESET_MAX) status = 0; +CustomResetReason customResetReason() { + bool once { true }; + static auto reason = CustomResetReason::None; + if (once) { + once = false; + if (rtcmemStatus()) { + reason = _systemRtcmemResetReason(); + } + customResetReason(CustomResetReason::None); } - return status; + return reason; } void reset() { ESP.restart(); } -void deferredReset(unsigned long delay, unsigned char reason) { +void deferredReset(unsigned long delay, CustomResetReason reason) { _defer_reset.once_ms(delay, customResetReason, reason); } +void factoryReset() { + DEBUG_MSG_P(PSTR("\n\nFACTORY RESET\n\n")); + resetSettings(); + deferredReset(100, CustomResetReason::Factory); +} + bool checkNeedsReset() { - return _reset_reason > 0; + return _reset_reason != CustomResetReason::None; } // ----------------------------------------------------------------------------- diff --git a/code/espurna/system.h b/code/espurna/system.h index fe2649bf..0ad55eb3 100644 --- a/code/espurna/system.h +++ b/code/espurna/system.h @@ -11,10 +11,26 @@ Copyright (C) 2019 by Xose Pérez #include "espurna.h" extern "C" { - #include "user_interface.h" - extern struct rst_info resetInfo; +#include "user_interface.h" +extern struct rst_info resetInfo; } +enum class CustomResetReason : uint8_t { + None, + Button, + Factory, + Hardware, + Mqtt, + Ota, + Rpc, + Rule, + Scheduler, + Terminal, + Web +}; + +void factoryReset(); + uint32_t systemResetReason(); uint8_t systemStabilityCounter(); void systemStabilityCounter(uint8_t count); @@ -22,11 +38,11 @@ void systemStabilityCounter(uint8_t count); void systemCheck(bool stable); bool systemCheck(); -uint32_t systemResetReason(); -unsigned char customResetReason(); -void customResetReason(unsigned char reason); +void customResetReason(CustomResetReason reason); +CustomResetReason customResetReason(); +String customResetReasonToPayload(CustomResetReason reason); -void deferredReset(unsigned long delay, unsigned char reason); +void deferredReset(unsigned long delay, CustomResetReason reason); bool checkNeedsReset(); unsigned long systemLoadAverage(); diff --git a/code/espurna/terminal.cpp b/code/espurna/terminal.cpp index 000a411b..05b8053c 100644 --- a/code/espurna/terminal.cpp +++ b/code/espurna/terminal.cpp @@ -288,7 +288,7 @@ void _terminalInitCommands() { terminalRegisterCommand(F("ERASE.CONFIG"), [](const terminal::CommandContext&) { terminalOK(); - customResetReason(CUSTOM_RESET_TERMINAL); + customResetReason(CustomResetReason::Terminal); eraseSDKConfig(); *((int*) 0) = 0; // see https://github.com/esp8266/Arduino/issues/1494 }); @@ -358,13 +358,13 @@ void _terminalInitCommands() { terminalRegisterCommand(F("RESET"), [](const terminal::CommandContext&) { terminalOK(); - deferredReset(100, CUSTOM_RESET_TERMINAL); + deferredReset(100, CustomResetReason::Terminal); }); terminalRegisterCommand(F("RESET.SAFE"), [](const terminal::CommandContext&) { systemStabilityCounter(SYSTEM_CHECK_MAX); terminalOK(); - deferredReset(100, CUSTOM_RESET_TERMINAL); + deferredReset(100, CustomResetReason::Terminal); }); terminalRegisterCommand(F("UPTIME"), [](const terminal::CommandContext&) { diff --git a/code/espurna/utils.cpp b/code/espurna/utils.cpp index e047faf6..ac9f2695 100644 --- a/code/espurna/utils.cpp +++ b/code/espurna/utils.cpp @@ -24,23 +24,6 @@ Copyright (C) 2017-2019 by Xose Pérez // Reset reasons //-------------------------------------------------------------------------------- -PROGMEM const char custom_reset_hardware[] = "Hardware button"; -PROGMEM const char custom_reset_web[] = "Reboot from web interface"; -PROGMEM const char custom_reset_terminal[] = "Reboot from terminal"; -PROGMEM const char custom_reset_mqtt[] = "Reboot from MQTT"; -PROGMEM const char custom_reset_rpc[] = "Reboot from RPC"; -PROGMEM const char custom_reset_ota[] = "Reboot after successful OTA update"; -PROGMEM const char custom_reset_http[] = "Reboot from HTTP"; -PROGMEM const char custom_reset_nofuss[] = "Reboot after successful NoFUSS update"; -PROGMEM const char custom_reset_upgrade[] = "Reboot after successful web update"; -PROGMEM const char custom_reset_factory[] = "Factory reset"; -PROGMEM const char* const custom_reset_string[] = { - custom_reset_hardware, custom_reset_web, custom_reset_terminal, - custom_reset_mqtt, custom_reset_rpc, custom_reset_ota, - custom_reset_http, custom_reset_nofuss, custom_reset_upgrade, - custom_reset_factory -}; - void setDefaultHostname() { if (strlen(HOSTNAME) > 0) { setSetting("hostname", F(HOSTNAME)); @@ -540,13 +523,10 @@ const char* _info_wifi_sleep_mode(WiFiSleepType_t type) { void info(bool first) { - - // Avoid printing on early boot when buffering is enabled - #if DEBUG_SUPPORT - - #if DEBUG_LOG_BUFFER_SUPPORT - if (first && debugLogBuffer()) return; - #endif +#if DEBUG_SUPPORT +#if DEBUG_LOG_BUFFER_SUPPORT + if (first && debugLogBuffer()) return; +#endif DEBUG_MSG_P(PSTR("\n\n---8<-------\n\n")); @@ -618,14 +598,13 @@ void info(bool first) { DEBUG_MSG_P(PSTR("[MAIN] Boot version: %d\n"), ESP.getBootVersion()); DEBUG_MSG_P(PSTR("[MAIN] Boot mode: %d\n"), ESP.getBootMode()); - unsigned char reason = customResetReason(); - if (reason > 0) { - char buffer[32]; - strcpy_P(buffer, custom_reset_string[reason-1]); - DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), buffer); + + auto reason = customResetReason(); + if (CustomResetReason::None != reason) { + DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), customResetReasonToPayload(reason).c_str()); } else { - DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), (char *) ESP.getResetReason().c_str()); - DEBUG_MSG_P(PSTR("[MAIN] Last reset info: %s\n"), (char *) ESP.getResetInfo().c_str()); + DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), ESP.getResetReason().c_str()); + DEBUG_MSG_P(PSTR("[MAIN] Last reset info: %s\n"), ESP.getResetInfo().c_str()); } DEBUG_MSG_P(PSTR("\n")); @@ -634,9 +613,9 @@ void info(bool first) { DEBUG_MSG_P(PSTR("[MAIN] Board: %s\n"), getBoardName().c_str()); DEBUG_MSG_P(PSTR("[MAIN] Support: %s\n"), getEspurnaModules().c_str()); DEBUG_MSG_P(PSTR("[MAIN] OTA: %s\n"), getEspurnaOTAModules().c_str()); - #if SENSOR_SUPPORT - DEBUG_MSG_P(PSTR("[MAIN] Sensors: %s\n"), getEspurnaSensors().c_str()); - #endif // SENSOR_SUPPORT +#if SENSOR_SUPPORT + DEBUG_MSG_P(PSTR("[MAIN] Sensors: %s\n"), getEspurnaSensors().c_str()); +#endif DEBUG_MSG_P(PSTR("[MAIN] WebUI image: %s\n"), getEspurnaWebUI().c_str()); DEBUG_MSG_P(PSTR("\n")); @@ -660,19 +639,18 @@ void info(bool first) { // ------------------------------------------------------------------------- - #if SYSTEM_CHECK_ENABLED - if (!systemCheck()) { - DEBUG_MSG_P(PSTR("\n")); - DEBUG_MSG_P(PSTR("[MAIN] Device is in SAFE MODE\n")); - } - #endif +#if SYSTEM_CHECK_ENABLED + if (!systemCheck()) { + DEBUG_MSG_P(PSTR("\n")); + DEBUG_MSG_P(PSTR("[MAIN] Device is in SAFE MODE\n")); + } +#endif // ------------------------------------------------------------------------- DEBUG_MSG_P(PSTR("\n\n---8<-------\n\n")); - #endif // DEBUG_SUPPORT == 1 - +#endif // DEBUG_SUPPORT == 1 } // ----------------------------------------------------------------------------- diff --git a/code/espurna/web.cpp b/code/espurna/web.cpp index 5a1f4db6..7b4e4133 100644 --- a/code/espurna/web.cpp +++ b/code/espurna/web.cpp @@ -220,13 +220,12 @@ constexpr const size_t WEB_CONFIG_BUFFER_MAX = 4096; // ----------------------------------------------------------------------------- void _onReset(AsyncWebServerRequest *request) { - webLog(request); if (!webAuthenticate(request)) { return request->requestAuthentication(getSetting("hostname").c_str()); } - deferredReset(100, CUSTOM_RESET_HTTP); + deferredReset(100, CustomResetReason::Web); request->send(200); } diff --git a/code/espurna/ws.cpp b/code/espurna/ws.cpp index b1855171..e1b4b147 100644 --- a/code/espurna/ws.cpp +++ b/code/espurna/ws.cpp @@ -338,7 +338,7 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) { DEBUG_MSG_P(PSTR("[WEBSOCKET] Requested action: %s\n"), action); if (strcmp(action, "reboot") == 0) { - deferredReset(100, CUSTOM_RESET_WEB); + deferredReset(100, CustomResetReason::Web); return; } @@ -352,9 +352,7 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) { } if (strcmp(action, "factory_reset") == 0) { - DEBUG_MSG_P(PSTR("\n\nFACTORY RESET\n\n")); - resetSettings(); - deferredReset(100, CUSTOM_RESET_FACTORY); + factoryReset(); return; }