ESPHome 2026.2.1
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"
7
8#include <cinttypes>
9
10#if !defined(USE_RP2040) && !defined(USE_HOST)
11
12namespace esphome::factory_reset {
13
14static const char *const TAG = "factory_reset";
15static const uint32_t POWER_CYCLES_KEY = 0xFA5C0DE;
16
17static bool was_power_cycled() {
18#ifdef USE_ESP32
19 return esp_reset_reason() == ESP_RST_POWERON;
20#endif
21#ifdef USE_ESP8266
22 auto reset_reason = EspClass::getResetReason();
23 return ESPHOME_strcasecmp_P(reset_reason.c_str(), ESPHOME_PSTR("power On")) == 0 ||
24 ESPHOME_strcasecmp_P(reset_reason.c_str(), ESPHOME_PSTR("external system")) == 0;
25#endif
26#ifdef USE_LIBRETINY
27 auto reason = lt_get_reboot_reason();
28 return reason == REBOOT_REASON_POWER || reason == REBOOT_REASON_HARDWARE;
29#endif
30}
31
33 uint8_t count = 0;
34 this->flash_.load(&count);
35 ESP_LOGCONFIG(TAG,
36 "Factory Reset by Reset:\n"
37 " Max interval between resets: %u seconds\n"
38 " Current count: %u\n"
39 " Factory reset after %u resets",
40 this->max_interval_, count, this->required_count_);
41}
42
43void FactoryResetComponent::save_(uint8_t count) {
44 this->flash_.save(&count);
46 this->defer([count, this] { this->increment_callback_.call(count, this->required_count_); });
47}
48
50 this->flash_ = global_preferences->make_preference<uint8_t>(POWER_CYCLES_KEY, true);
51 if (was_power_cycled()) {
52 uint8_t count = 0;
53 this->flash_.load(&count);
54 // this is a power on reset or external system reset
55 count++;
56 if (count == this->required_count_) {
57 ESP_LOGW(TAG, "Reset count reached, factory resetting");
59 // delay to allow log to be sent
60 delay(100); // NOLINT
61 App.safe_reboot(); // should not return
62 }
63 this->save_(count);
64 ESP_LOGD(TAG, "Power on reset detected, incremented count to %u", count);
65 this->set_timeout(static_cast<uint32_t>(this->max_interval_) * 1000, [this]() {
66 ESP_LOGD(TAG, "No reset in the last %u seconds, resetting count", this->max_interval_);
67 this->save_(0); // reset count
68 });
69 } else {
70 this->save_(0); // reset count if not a power cycle
71 }
72}
73
74} // namespace esphome::factory_reset
75
76#endif // !defined(USE_RP2040) && !defined(USE_HOST)
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std voi defer)(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call.
Definition component.h:479
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.h:429
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.