mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	[safe_mode] Allow user-defined interval for successful boot (#6882)
Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
		| @@ -16,6 +16,7 @@ from esphome import automation | ||||
|  | ||||
| CODEOWNERS = ["@paulmonigatti", "@jsuanet", "@kbx81"] | ||||
|  | ||||
| CONF_BOOT_IS_GOOD_AFTER = "boot_is_good_after" | ||||
| CONF_ON_SAFE_MODE = "on_safe_mode" | ||||
|  | ||||
| safe_mode_ns = cg.esphome_ns.namespace("safe_mode") | ||||
| @@ -34,6 +35,9 @@ CONFIG_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             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_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, | ||||
|             cv.Optional( | ||||
| @@ -63,7 +67,9 @@ async def to_code(config): | ||||
|         await automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|     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")) | ||||
|     CORE.data[CONF_SAFE_MODE] = {} | ||||
|   | ||||
| @@ -16,6 +16,8 @@ static const char *const TAG = "safe_mode"; | ||||
|  | ||||
| void SafeModeComponent::dump_config() { | ||||
|   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, "  Remain in safe mode for %" PRIu32 " seconds", | ||||
|                 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; } | ||||
|  | ||||
| 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 | ||||
|     ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); | ||||
|     this->clean_rtc(); | ||||
| @@ -60,9 +62,11 @@ bool SafeModeComponent::get_safe_mode_pending() { | ||||
|   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_enable_time_ = enable_time; | ||||
|   this->safe_mode_boot_is_good_after_ = boot_is_good_after; | ||||
|   this->safe_mode_num_attempts_ = num_attempts; | ||||
|   this->rtc_ = global_preferences->make_preference<uint32_t>(233825507UL, false); | ||||
|   this->safe_mode_rtc_value_ = this->read_rtc_(); | ||||
|   | ||||
| @@ -11,7 +11,7 @@ namespace safe_mode { | ||||
| /// SafeModeComponent provides a safe way to recover from repeated boot failures | ||||
| class SafeModeComponent : public Component { | ||||
|  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 | ||||
|   void set_safe_mode_pending(const bool &pending); | ||||
| @@ -33,11 +33,12 @@ class SafeModeComponent : public Component { | ||||
|   void write_rtc_(uint32_t val); | ||||
|   uint32_t read_rtc_(); | ||||
|  | ||||
|   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_enable_time_{60000};  ///< The time safe mode should remain active for | ||||
|   uint32_t safe_mode_rtc_value_; | ||||
|   uint8_t safe_mode_num_attempts_; | ||||
|   bool boot_successful_{false};                   ///< set to true after boot is considered successful | ||||
|   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_rtc_value_{0}; | ||||
|   uint32_t safe_mode_start_time_{0};  ///< stores when safe mode was enabled | ||||
|   uint8_t safe_mode_num_attempts_{0}; | ||||
|   ESPPreferenceObject rtc_; | ||||
|   CallbackManager<void()> safe_mode_callback_{}; | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ wifi: | ||||
|   password: password1 | ||||
|  | ||||
| safe_mode: | ||||
|   boot_is_good_after: 2min | ||||
|   num_attempts: 3 | ||||
|   reboot_timeout: 2min | ||||
|   on_safe_mode: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user