[safe_mode] Allow user-defined interval for successful boot (#6882)

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
NMartin354 2024-06-11 19:38:20 -05:00 committed by GitHub
parent 562700bd2c
commit 7b60543afd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 9 deletions

View file

@ -16,6 +16,7 @@ from esphome import automation
CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"]
CONF_BOOT_IS_GOOD_AFTER = "boot_is_good_after"
CONF_ON_SAFE_MODE = "on_safe_mode" CONF_ON_SAFE_MODE = "on_safe_mode"
safe_mode_ns = cg.esphome_ns.namespace("safe_mode") safe_mode_ns = cg.esphome_ns.namespace("safe_mode")
@ -34,6 +35,9 @@ CONFIG_SCHEMA = cv.All(
cv.Schema( cv.Schema(
{ {
cv.GenerateID(): cv.declare_id(SafeModeComponent), cv.GenerateID(): cv.declare_id(SafeModeComponent),
cv.Optional(
CONF_BOOT_IS_GOOD_AFTER, default="1min"
): cv.positive_time_period_milliseconds,
cv.Optional(CONF_DISABLED, default=False): cv.boolean, cv.Optional(CONF_DISABLED, default=False): cv.boolean,
cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int,
cv.Optional( cv.Optional(
@ -63,7 +67,9 @@ async def to_code(config):
await automation.build_automation(trigger, [], conf) await automation.build_automation(trigger, [], conf)
condition = var.should_enter_safe_mode( condition = var.should_enter_safe_mode(
config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] config[CONF_NUM_ATTEMPTS],
config[CONF_REBOOT_TIMEOUT],
config[CONF_BOOT_IS_GOOD_AFTER],
) )
cg.add(RawExpression(f"if ({condition}) return")) cg.add(RawExpression(f"if ({condition}) return"))
CORE.data[CONF_SAFE_MODE] = {} CORE.data[CONF_SAFE_MODE] = {}

View file

@ -16,6 +16,8 @@ static const char *const TAG = "safe_mode";
void SafeModeComponent::dump_config() { void SafeModeComponent::dump_config() {
ESP_LOGCONFIG(TAG, "Safe Mode:"); ESP_LOGCONFIG(TAG, "Safe Mode:");
ESP_LOGCONFIG(TAG, " Boot considered successful after %" PRIu32 " seconds",
this->safe_mode_boot_is_good_after_ / 1000); // because milliseconds
ESP_LOGCONFIG(TAG, " Invoke after %u boot attempts", this->safe_mode_num_attempts_); ESP_LOGCONFIG(TAG, " Invoke after %u boot attempts", this->safe_mode_num_attempts_);
ESP_LOGCONFIG(TAG, " Remain in safe mode for %" PRIu32 " seconds", ESP_LOGCONFIG(TAG, " Remain in safe mode for %" PRIu32 " seconds",
this->safe_mode_enable_time_ / 1000); // because milliseconds this->safe_mode_enable_time_ / 1000); // because milliseconds
@ -34,7 +36,7 @@ void SafeModeComponent::dump_config() {
float SafeModeComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } float SafeModeComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
void SafeModeComponent::loop() { void SafeModeComponent::loop() {
if (!this->boot_successful_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_enable_time_) { if (!this->boot_successful_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_boot_is_good_after_) {
// successful boot, reset counter // successful boot, reset counter
ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter");
this->clean_rtc(); this->clean_rtc();
@ -60,9 +62,11 @@ bool SafeModeComponent::get_safe_mode_pending() {
return this->read_rtc_() == SafeModeComponent::ENTER_SAFE_MODE_MAGIC; return this->read_rtc_() == SafeModeComponent::ENTER_SAFE_MODE_MAGIC;
} }
bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time) { bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time,
uint32_t boot_is_good_after) {
this->safe_mode_start_time_ = millis(); this->safe_mode_start_time_ = millis();
this->safe_mode_enable_time_ = enable_time; this->safe_mode_enable_time_ = enable_time;
this->safe_mode_boot_is_good_after_ = boot_is_good_after;
this->safe_mode_num_attempts_ = num_attempts; this->safe_mode_num_attempts_ = num_attempts;
this->rtc_ = global_preferences->make_preference<uint32_t>(233825507UL, false); this->rtc_ = global_preferences->make_preference<uint32_t>(233825507UL, false);
this->safe_mode_rtc_value_ = this->read_rtc_(); this->safe_mode_rtc_value_ = this->read_rtc_();

View file

@ -11,7 +11,7 @@ namespace safe_mode {
/// SafeModeComponent provides a safe way to recover from repeated boot failures /// SafeModeComponent provides a safe way to recover from repeated boot failures
class SafeModeComponent : public Component { class SafeModeComponent : public Component {
public: public:
bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time); bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time, uint32_t boot_is_good_after);
/// Set to true if the next startup will enter safe mode /// Set to true if the next startup will enter safe mode
void set_safe_mode_pending(const bool &pending); void set_safe_mode_pending(const bool &pending);
@ -33,11 +33,12 @@ class SafeModeComponent : public Component {
void write_rtc_(uint32_t val); void write_rtc_(uint32_t val);
uint32_t read_rtc_(); uint32_t read_rtc_();
bool boot_successful_{false}; ///< set to true after boot is considered successful bool boot_successful_{false}; ///< set to true after boot is considered successful
uint32_t safe_mode_start_time_; ///< stores when safe mode was enabled uint32_t safe_mode_boot_is_good_after_{60000}; ///< The amount of time after which the boot is considered successful
uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should remain active for uint32_t safe_mode_enable_time_{60000}; ///< The time safe mode should remain active for
uint32_t safe_mode_rtc_value_; uint32_t safe_mode_rtc_value_{0};
uint8_t safe_mode_num_attempts_; uint32_t safe_mode_start_time_{0}; ///< stores when safe mode was enabled
uint8_t safe_mode_num_attempts_{0};
ESPPreferenceObject rtc_; ESPPreferenceObject rtc_;
CallbackManager<void()> safe_mode_callback_{}; CallbackManager<void()> safe_mode_callback_{};

View file

@ -3,6 +3,7 @@ wifi:
password: password1 password: password1
safe_mode: safe_mode:
boot_is_good_after: 2min
num_attempts: 3 num_attempts: 3
reboot_timeout: 2min reboot_timeout: 2min
on_safe_mode: on_safe_mode: