mirror of
https://github.com/esphome/esphome.git
synced 2026-05-23 11:16:52 +08:00
[status_led] Disable loop when idle (#15642)
This commit is contained in:
@@ -7,6 +7,11 @@ namespace status_led {
|
||||
|
||||
static const char *const TAG = "status_led";
|
||||
|
||||
static constexpr uint32_t ERROR_PERIOD_MS = 250;
|
||||
static constexpr uint32_t ERROR_ON_MS = 150;
|
||||
static constexpr uint32_t WARNING_PERIOD_MS = 1500;
|
||||
static constexpr uint32_t WARNING_ON_MS = 250;
|
||||
|
||||
StatusLED *global_status_led = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
StatusLED::StatusLED(GPIOPin *pin) : pin_(pin) { global_status_led = this; }
|
||||
@@ -19,12 +24,18 @@ void StatusLED::dump_config() {
|
||||
LOG_PIN(" Pin: ", this->pin_);
|
||||
}
|
||||
void StatusLED::loop() {
|
||||
if ((App.get_app_state() & STATUS_LED_ERROR) != 0u) {
|
||||
this->pin_->digital_write(millis() % 250u < 150u);
|
||||
} else if ((App.get_app_state() & STATUS_LED_WARNING) != 0u) {
|
||||
this->pin_->digital_write(millis() % 1500u < 250u);
|
||||
const uint32_t app_state = App.get_app_state();
|
||||
// Use millis() rather than App.get_loop_component_start_time() because this loop is also
|
||||
// dispatched from Application::feed_wdt() during long blocking operations, where the cached
|
||||
// per-component timestamp doesn't advance and would freeze the blink pattern.
|
||||
const uint32_t now = millis();
|
||||
if ((app_state & STATUS_LED_ERROR) != 0u) {
|
||||
this->pin_->digital_write(now % ERROR_PERIOD_MS < ERROR_ON_MS);
|
||||
} else if ((app_state & STATUS_LED_WARNING) != 0u) {
|
||||
this->pin_->digital_write(now % WARNING_PERIOD_MS < WARNING_ON_MS);
|
||||
} else {
|
||||
this->pin_->digital_write(false);
|
||||
this->disable_loop();
|
||||
}
|
||||
}
|
||||
float StatusLED::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
@@ -225,7 +225,21 @@ void HOT Application::feed_wdt_slow_(uint32_t time) {
|
||||
this->last_wdt_feed_ = time;
|
||||
#ifdef USE_STATUS_LED
|
||||
if (status_led::global_status_led != nullptr) {
|
||||
status_led::global_status_led->call();
|
||||
auto *sl = status_led::global_status_led;
|
||||
uint8_t sl_state = sl->get_component_state() & COMPONENT_STATE_MASK;
|
||||
if (sl_state == COMPONENT_STATE_LOOP_DONE) {
|
||||
// status_led only transitions to LOOP_DONE from inside its own loop() (after the
|
||||
// first idle-path dispatch), so its pin is already initialized by pre_setup() and
|
||||
// its setup() has already run. Re-dispatch only if an error or warning bit has been
|
||||
// set since; otherwise skip entirely.
|
||||
if ((this->app_state_ & STATUS_LED_MASK) == 0)
|
||||
return;
|
||||
sl->enable_loop();
|
||||
} else if (sl_state != COMPONENT_STATE_LOOP) {
|
||||
// CONSTRUCTION/SETUP/FAILED: not our job — App::setup() drives the lifecycle.
|
||||
return;
|
||||
}
|
||||
sl->loop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user