ESPHome 2026.1.0-dev
Loading...
Searching...
No Matches
factory_reset.cpp
Go to the documentation of this file.
1#include "factory_reset.h"
2
4#include "esphome/core/hal.h"
5#include "esphome/core/log.h"
6
7#include <cinttypes>
8
9#if !defined(USE_RP2040) && !defined(USE_HOST)
10
11namespace esphome::factory_reset {
12
13static const char *const TAG = "factory_reset";
14static const uint32_t POWER_CYCLES_KEY = 0xFA5C0DE;
15
16static bool was_power_cycled() {
17#ifdef USE_ESP32
18 return esp_reset_reason() == ESP_RST_POWERON;
19#endif
20#ifdef USE_ESP8266
21 auto reset_reason = EspClass::getResetReason();
22 return strcasecmp(reset_reason.c_str(), "power On") == 0 || strcasecmp(reset_reason.c_str(), "external system") == 0;
23#endif
24#ifdef USE_LIBRETINY
25 auto reason = lt_get_reboot_reason();
26 return reason == REBOOT_REASON_POWER || reason == REBOOT_REASON_HARDWARE;
27#endif
28}
29
31 uint8_t count = 0;
32 this->flash_.load(&count);
33 ESP_LOGCONFIG(TAG, "Factory Reset by Reset:");
34 ESP_LOGCONFIG(TAG,
35 " Max interval between resets: %u seconds\n"
36 " Current count: %u\n"
37 " Factory reset after %u resets",
38 this->max_interval_, count, this->required_count_);
39}
40
41void FactoryResetComponent::save_(uint8_t count) {
42 this->flash_.save(&count);
44 this->defer([count, this] { this->increment_callback_.call(count, this->required_count_); });
45}
46
48 this->flash_ = global_preferences->make_preference<uint8_t>(POWER_CYCLES_KEY, true);
49 if (was_power_cycled()) {
50 uint8_t count = 0;
51 this->flash_.load(&count);
52 // this is a power on reset or external system reset
53 count++;
54 if (count == this->required_count_) {
55 ESP_LOGW(TAG, "Reset count reached, factory resetting");
57 // delay to allow log to be sent
58 delay(100); // NOLINT
59 App.safe_reboot(); // should not return
60 }
61 this->save_(count);
62 ESP_LOGD(TAG, "Power on reset detected, incremented count to %u", count);
63 this->set_timeout(static_cast<uint32_t>(this->max_interval_) * 1000, [this]() {
64 ESP_LOGD(TAG, "No reset in the last %u seconds, resetting count", this->max_interval_);
65 this->save_(0); // reset count
66 });
67 } else {
68 this->save_(0); // reset count if not a power cycle
69 }
70}
71
72} // namespace esphome::factory_reset
73
74#endif // !defined(USE_RP2040) && !defined(USE_HOST)
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
bool save(const T *src)
Definition preferences.h:21
virtual bool sync()=0
Commit pending writes to flash.
virtual bool reset()=0
Forget all unsaved changes and re-initialize the permanent preferences storage.
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
CallbackManager< void(uint8_t, uint8_t)> increment_callback_
ESPPreferences * global_preferences
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:26
Application App
Global storage of Application pointer - only one Application can exist.