mirror of
https://github.com/esphome/esphome.git
synced 2025-08-06 18:37:47 +00:00
deep_sleep: Replace polling loop with event-driven state machine
This commit is contained in:
parent
4e9e48e2e7
commit
7c2d2ef5a3
@ -36,26 +36,27 @@ void DeepSleepComponent::dump_config() {
|
|||||||
this->dump_config_platform_();
|
this->dump_config_platform_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeepSleepComponent::loop() {
|
|
||||||
if (this->next_enter_deep_sleep_)
|
|
||||||
this->begin_sleep();
|
|
||||||
}
|
|
||||||
|
|
||||||
float DeepSleepComponent::get_loop_priority() const {
|
|
||||||
return -100.0f; // run after everything else is ready
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
|
void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; }
|
||||||
|
|
||||||
void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
|
void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; }
|
||||||
|
|
||||||
void DeepSleepComponent::begin_sleep(bool manual) {
|
void DeepSleepComponent::begin_sleep(bool manual) {
|
||||||
if (this->prevent_ && !manual) {
|
if (this->sleep_state_ == SLEEP_STATE_ENTERING_SLEEP) {
|
||||||
this->next_enter_deep_sleep_ = true;
|
// Already entering sleep, avoid re-entrance
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->prevent_ && !manual) {
|
||||||
|
// Sleep was prevented
|
||||||
|
this->sleep_state_ = SLEEP_STATE_BLOCKED_BY_PREVENT;
|
||||||
|
ESP_LOGD(TAG, "Deep sleep blocked by prevent flag");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sleep_state_ = SLEEP_STATE_ENTERING_SLEEP;
|
||||||
|
|
||||||
if (!this->prepare_to_sleep_()) {
|
if (!this->prepare_to_sleep_()) {
|
||||||
|
// prepare_to_sleep_ will set appropriate blocked state
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +77,17 @@ float DeepSleepComponent::get_setup_priority() const { return setup_priority::LA
|
|||||||
|
|
||||||
void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; }
|
void DeepSleepComponent::prevent_deep_sleep() { this->prevent_ = true; }
|
||||||
|
|
||||||
void DeepSleepComponent::allow_deep_sleep() { this->prevent_ = false; }
|
void DeepSleepComponent::allow_deep_sleep() {
|
||||||
|
this->prevent_ = false;
|
||||||
|
// If sleep was blocked by prevent flag, try to sleep now
|
||||||
|
if (this->sleep_state_ == SLEEP_STATE_BLOCKED_BY_PREVENT) {
|
||||||
|
ESP_LOGD(TAG, "Deep sleep allowed, executing deferred sleep");
|
||||||
|
this->sleep_state_ = SLEEP_STATE_IDLE;
|
||||||
|
// Schedule sleep for next loop iteration to avoid potential issues
|
||||||
|
// with calling begin_sleep during another component's execution
|
||||||
|
this->defer([this]() { this->begin_sleep(false); }); // false = automatic sleep (respects prevent flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace deep_sleep
|
} // namespace deep_sleep
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
@ -93,8 +93,6 @@ class DeepSleepComponent : public Component {
|
|||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void loop() override;
|
|
||||||
float get_loop_priority() const override;
|
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
/// Helper to enter deep sleep mode
|
/// Helper to enter deep sleep mode
|
||||||
@ -124,9 +122,16 @@ class DeepSleepComponent : public Component {
|
|||||||
optional<bool> touch_wakeup_;
|
optional<bool> touch_wakeup_;
|
||||||
optional<WakeupCauseToRunDuration> wakeup_cause_to_run_duration_;
|
optional<WakeupCauseToRunDuration> wakeup_cause_to_run_duration_;
|
||||||
#endif
|
#endif
|
||||||
|
enum SleepState : uint8_t {
|
||||||
|
SLEEP_STATE_IDLE,
|
||||||
|
SLEEP_STATE_BLOCKED_BY_PREVENT,
|
||||||
|
SLEEP_STATE_BLOCKED_BY_WAKEUP_PIN,
|
||||||
|
SLEEP_STATE_ENTERING_SLEEP,
|
||||||
|
};
|
||||||
|
|
||||||
optional<uint32_t> run_duration_;
|
optional<uint32_t> run_duration_;
|
||||||
bool next_enter_deep_sleep_{false};
|
|
||||||
bool prevent_{false};
|
bool prevent_{false};
|
||||||
|
SleepState sleep_state_{SLEEP_STATE_IDLE};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool global_has_deep_sleep; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
extern bool global_has_deep_sleep; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
@ -59,13 +59,27 @@ bool DeepSleepComponent::prepare_to_sleep_() {
|
|||||||
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr &&
|
if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_KEEP_AWAKE && this->wakeup_pin_ != nullptr &&
|
||||||
this->wakeup_pin_->digital_read()) {
|
this->wakeup_pin_->digital_read()) {
|
||||||
// Defer deep sleep until inactive
|
// Defer deep sleep until inactive
|
||||||
if (!this->next_enter_deep_sleep_) {
|
if (this->sleep_state_ != SLEEP_STATE_BLOCKED_BY_WAKEUP_PIN) {
|
||||||
|
this->sleep_state_ = SLEEP_STATE_BLOCKED_BY_WAKEUP_PIN;
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
ESP_LOGW(TAG, "Waiting for wakeup pin state change");
|
ESP_LOGW(TAG, "Waiting for wakeup pin state change");
|
||||||
|
// Set up monitoring - check pin state every 100ms
|
||||||
|
this->set_interval("wakeup_pin_check", 100, [this]() {
|
||||||
|
if (!this->wakeup_pin_->digital_read()) {
|
||||||
|
ESP_LOGD(TAG, "Wakeup pin inactive, can now enter deep sleep");
|
||||||
|
this->cancel_interval("wakeup_pin_check");
|
||||||
|
this->sleep_state_ = SLEEP_STATE_IDLE;
|
||||||
|
this->begin_sleep(false); // false = automatic sleep (respects prevent flag)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this->next_enter_deep_sleep_ = true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// If we were monitoring and now can sleep, clean up
|
||||||
|
if (this->sleep_state_ == SLEEP_STATE_BLOCKED_BY_WAKEUP_PIN) {
|
||||||
|
this->cancel_interval("wakeup_pin_check");
|
||||||
|
this->sleep_state_ = SLEEP_STATE_ENTERING_SLEEP;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user