ESPHome 2025.9.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 {
12namespace 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 strcasecmp(reset_reason.c_str(), "power On") == 0 || strcasecmp(reset_reason.c_str(), "external system") == 0;
24#endif
25#ifdef USE_LIBRETINY
26 auto reason = lt_get_reboot_reason();
27 return reason == REBOOT_REASON_POWER || reason == REBOOT_REASON_HARDWARE;
28#endif
29}
30
32 uint8_t count = 0;
33 this->flash_.load(&count);
34 ESP_LOGCONFIG(TAG, "Factory Reset by Reset:");
35 ESP_LOGCONFIG(TAG,
36 " Max interval between resets %" PRIu32 " seconds\n"
37 " Current count: %u\n"
38 " Factory reset after %u resets",
39 this->max_interval_ / 1000, count, this->required_count_);
40}
41
42void FactoryResetComponent::save_(uint8_t count) {
43 this->flash_.save(&count);
45 this->defer([count, this] { this->increment_callback_.call(count, this->required_count_); });
46}
47
49 this->flash_ = global_preferences->make_preference<uint8_t>(POWER_CYCLES_KEY, true);
50 if (was_power_cycled()) {
51 uint8_t count = 0;
52 this->flash_.load(&count);
53 // this is a power on reset or external system reset
54 count++;
55 if (count == this->required_count_) {
56 ESP_LOGW(TAG, "Reset count reached, factory resetting");
58 // delay to allow log to be sent
59 delay(100); // NOLINT
60 App.safe_reboot(); // should not return
61 }
62 this->save_(count);
63 ESP_LOGD(TAG, "Power on reset detected, incremented count to %u", count);
64 this->set_timeout(this->max_interval_, [this]() {
65 ESP_LOGD(TAG, "No reset in the last %" PRIu32 " seconds, resetting count", this->max_interval_ / 1000);
66 this->save_(0); // reset count
67 });
68 } else {
69 this->save_(0); // reset count if not a power cycle
70 }
71}
72
73} // namespace factory_reset
74} // namespace esphome
75
76#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_
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
ESPPreferences * global_preferences
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29
Application App
Global storage of Application pointer - only one Application can exist.