diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index fcded02ba5..5bcc676247 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -1,6 +1,7 @@ #include "debug_component.h" #include +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index f887d52864..a55cc7bf44 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -34,6 +34,7 @@ class DebugComponent : public PollingComponent { #endif void set_loop_time_sensor(sensor::Sensor *loop_time_sensor) { loop_time_sensor_ = loop_time_sensor; } #ifdef USE_ESP32 + void on_shutdown() override; void set_psram_sensor(sensor::Sensor *psram_sensor) { this->psram_sensor_ = psram_sensor; } #endif // USE_ESP32 void set_cpu_frequency_sensor(sensor::Sensor *cpu_frequency_sensor) { diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 662e60501d..999cb927b3 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -1,6 +1,7 @@ #include "debug_component.h" #ifdef USE_ESP32 +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" #include @@ -10,12 +11,12 @@ #include #include +#include + #ifdef USE_ARDUINO #include #endif -#include - namespace esphome { namespace debug { @@ -42,16 +43,39 @@ static const char *const RESET_REASONS[] = { "CPU lock up", }; +static const char *const REBOOT_KEY = "reboot_source"; +static const size_t REBOOT_MAX_LEN = 24; + +// on shutdown, store the source of the reboot request +void DebugComponent::on_shutdown() { + auto *component = App.get_current_component(); + char buffer[REBOOT_MAX_LEN]{}; + auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name())); + if (component != nullptr) { + strncpy(buffer, component->get_component_source(), REBOOT_MAX_LEN - 1); + } + ESP_LOGD(TAG, "Storing reboot source: %s", buffer); + pref.save(&buffer); + global_preferences->sync(); +} + std::string DebugComponent::get_reset_reason_() { std::string reset_reason; unsigned reason = esp_reset_reason(); if (reason < sizeof(RESET_REASONS) / sizeof(RESET_REASONS[0])) { reset_reason = RESET_REASONS[reason]; + if (reason == ESP_RST_SW) { + auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name())); + char buffer[REBOOT_MAX_LEN]{}; + if (pref.load(&buffer)) { + reset_reason = "Reboot request from " + std::string(buffer); + } + } } else { reset_reason = "unknown source"; } ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str()); - return "Reset by " + reset_reason; + return reset_reason; } static const char *const WAKEUP_CAUSES[] = { diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index a4550bcd9e..3f5a283fd8 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -70,6 +70,7 @@ void Application::loop() { this->feed_wdt(); for (Component *component : this->looping_components_) { { + this->set_current_component(component); WarnIfComponentBlockingGuard guard{component}; component->call(); } diff --git a/esphome/core/application.h b/esphome/core/application.h index 462beb1f25..e64e2b7655 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -97,6 +97,9 @@ class Application { this->compilation_time_ = compilation_time; } + void set_current_component(Component *component) { this->current_component_ = component; } + Component *get_current_component() { return this->current_component_; } + #ifdef USE_BINARY_SENSOR void register_binary_sensor(binary_sensor::BinarySensor *binary_sensor) { this->binary_sensors_.push_back(binary_sensor); @@ -547,6 +550,7 @@ class Application { uint32_t loop_interval_{16}; size_t dump_config_at_{SIZE_MAX}; uint32_t app_state_{0}; + Component *current_component_{nullptr}; }; /// Global storage of Application pointer - only one Application can exist. diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 7e83b3b705..b4f617d405 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -1,4 +1,6 @@ #include "scheduler.h" + +#include "application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" @@ -215,6 +217,7 @@ void HOT Scheduler::call() { this->pop_raw_(); continue; } + App.set_current_component(item->component); #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")",