Merge branch 'deep_sleep_loop' into integration

This commit is contained in:
J. Nick Koston 2025-07-05 15:54:13 -05:00
commit e7a1ef7aa1
No known key found for this signature in database
3 changed files with 47 additions and 17 deletions

View File

@ -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

View File

@ -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)

View File

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