1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-14 17:22:20 +01:00

mark_loop_done

This commit is contained in:
J. Nick Koston
2025-06-14 21:58:18 -05:00
parent a1e4143600
commit 4f29039b41
12 changed files with 72 additions and 14 deletions

View File

@@ -17,7 +17,11 @@ void Anova::setup() {
this->current_request_ = 0;
}
void Anova::loop() {}
void Anova::loop() {
// This component uses polling via update() and BLE callbacks
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void Anova::control(const ClimateCall &call) {
if (call.get_mode().has_value()) {

View File

@@ -480,7 +480,11 @@ void BedJetHub::set_clock(uint8_t hour, uint8_t minute) {
/* Internal */
void BedJetHub::loop() {}
void BedJetHub::loop() {
// This component uses polling via update() and BLE callbacks
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void BedJetHub::update() { this->dispatch_status_(); }
void BedJetHub::dump_config() {

View File

@@ -83,7 +83,11 @@ void BedJetClimate::reset_state_() {
this->publish_state();
}
void BedJetClimate::loop() {}
void BedJetClimate::loop() {
// This component is controlled via the parent BedJetHub
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void BedJetClimate::control(const ClimateCall &call) {
ESP_LOGD(TAG, "Received BedJetClimate::control");

View File

@@ -11,7 +11,11 @@ namespace ble_client {
static const char *const TAG = "ble_rssi_sensor";
void BLEClientRSSISensor::loop() {}
void BLEClientRSSISensor::loop() {
// This component uses polling via update() and BLE GAP callbacks
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void BLEClientRSSISensor::dump_config() {
LOG_SENSOR("", "BLE Client RSSI Sensor", this);

View File

@@ -11,7 +11,11 @@ namespace ble_client {
static const char *const TAG = "ble_sensor";
void BLESensor::loop() {}
void BLESensor::loop() {
// This component uses polling via update() and BLE callbacks
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void BLESensor::dump_config() {
LOG_SENSOR("", "BLE Sensor", this);

View File

@@ -14,7 +14,11 @@ static const char *const TAG = "ble_text_sensor";
static const std::string EMPTY = "";
void BLETextSensor::loop() {}
void BLETextSensor::loop() {
// This component uses polling via update() and BLE callbacks
// Empty loop not needed, mark as done to save CPU cycles
this->mark_loop_done();
}
void BLETextSensor::dump_config() {
LOG_TEXT_SENSOR("", "BLE Text Sensor", this);

View File

@@ -168,6 +168,8 @@ void ESP32ImprovComponent::loop() {
case improv::STATE_PROVISIONED: {
this->incoming_data_.clear();
this->set_status_indicator_state_(false);
// Provisioning complete, no further loop execution needed
this->mark_loop_done();
break;
}
}

View File

@@ -42,6 +42,8 @@ void SafeModeComponent::loop() {
ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter");
this->clean_rtc();
this->boot_successful_ = true;
// Mark loop as done since we no longer need to check
this->mark_loop_done();
}
}

View File

@@ -67,6 +67,9 @@ void SNTPComponent::loop() {
time.minute, time.second);
this->time_sync_callback_.call();
this->has_time_ = true;
// Time is now synchronized, no need to check anymore
this->mark_loop_done();
}
} // namespace sntp

View File

@@ -29,17 +29,18 @@ const float LATE = -100.0f;
} // namespace setup_priority
// Component state uses bits 0-1 (4 states)
const uint8_t COMPONENT_STATE_MASK = 0x03;
// Component state uses bits 0-2 (8 states, 5 used)
const uint8_t COMPONENT_STATE_MASK = 0x07;
const uint8_t COMPONENT_STATE_CONSTRUCTION = 0x00;
const uint8_t COMPONENT_STATE_SETUP = 0x01;
const uint8_t COMPONENT_STATE_LOOP = 0x02;
const uint8_t COMPONENT_STATE_FAILED = 0x03;
// Status LED uses bits 2-3
const uint8_t STATUS_LED_MASK = 0x0C;
const uint8_t COMPONENT_STATE_LOOP_DONE = 0x04;
// Status LED uses bits 3-4
const uint8_t STATUS_LED_MASK = 0x18;
const uint8_t STATUS_LED_OK = 0x00;
const uint8_t STATUS_LED_WARNING = 0x04; // Bit 2
const uint8_t STATUS_LED_ERROR = 0x08; // Bit 3
const uint8_t STATUS_LED_WARNING = 0x08; // Bit 3
const uint8_t STATUS_LED_ERROR = 0x10; // Bit 4
const uint32_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning
const uint32_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again
@@ -111,6 +112,9 @@ void Component::call() {
case COMPONENT_STATE_FAILED: // NOLINT(bugprone-branch-clone)
// State failed: Do nothing
break;
case COMPONENT_STATE_LOOP_DONE: // NOLINT(bugprone-branch-clone)
// State loop done: Do nothing, component has finished its work
break;
default:
break;
}
@@ -133,6 +137,11 @@ void Component::mark_failed() {
this->component_state_ |= COMPONENT_STATE_FAILED;
this->status_set_error();
}
void Component::mark_loop_done() {
ESP_LOGD(TAG, "Component %s loop marked as done.", this->get_component_source());
this->component_state_ &= ~COMPONENT_STATE_MASK;
this->component_state_ |= COMPONENT_STATE_LOOP_DONE;
}
void Component::reset_to_construction_state() {
if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) {
ESP_LOGI(TAG, "Component %s is being reset to construction state.", this->get_component_source());
@@ -169,6 +178,10 @@ bool Component::is_ready() const {
return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP ||
(this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP;
}
bool Component::should_skip_loop() const {
uint8_t state = this->component_state_ & COMPONENT_STATE_MASK;
return state == COMPONENT_STATE_FAILED || state == COMPONENT_STATE_LOOP_DONE;
}
bool Component::can_proceed() { return true; }
bool Component::status_has_warning() const { return this->component_state_ & STATUS_LED_WARNING; }
bool Component::status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; }

View File

@@ -58,6 +58,7 @@ extern const uint8_t COMPONENT_STATE_CONSTRUCTION;
extern const uint8_t COMPONENT_STATE_SETUP;
extern const uint8_t COMPONENT_STATE_LOOP;
extern const uint8_t COMPONENT_STATE_FAILED;
extern const uint8_t COMPONENT_STATE_LOOP_DONE;
extern const uint8_t STATUS_LED_MASK;
extern const uint8_t STATUS_LED_OK;
extern const uint8_t STATUS_LED_WARNING;
@@ -150,10 +151,23 @@ class Component {
this->mark_failed();
}
/** Mark this component's loop as done. The loop will no longer be called.
*
* This is useful for components that only need to run for a certain period of time
* and then no longer need their loop() method called, saving CPU cycles.
*/
void mark_loop_done();
bool is_failed() const;
bool is_ready() const;
/** Check if this component should skip its loop execution.
*
* @return True if the component is in FAILED or LOOP_DONE state
*/
bool should_skip_loop() const;
virtual bool can_proceed();
bool status_has_warning() const;

View File

@@ -211,8 +211,8 @@ void HOT Scheduler::call() {
// Not reached timeout yet, done for this call
break;
}
// Don't run on failed components
if (item->component != nullptr && item->component->is_failed()) {
// Don't run on failed or loop-done components
if (item->component != nullptr && item->component->should_skip_loop()) {
LockGuard guard{this->lock_};
this->pop_raw_();
continue;