[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"]
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] = {}

View file

@ -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_();

View file

@ -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_{};

View file

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