ESPHome 2026.6.2
Loading...
Searching...
No Matches
component.cpp
Go to the documentation of this file.
2
3#include <cinttypes>
4#include <limits>
5#include <memory>
6#include <utility>
7#include <vector>
9#include "esphome/core/hal.h"
11#include "esphome/core/log.h"
12
13namespace esphome {
14
15static const char *const TAG = "component";
16
17// Global vectors for component data that doesn't belong in every instance.
18// Using vector instead of unordered_map for both because:
19// - Much lower memory overhead (8 bytes per entry vs 20+ for unordered_map)
20// - Linear search is fine for small n (typically < 5 entries)
21// - These are rarely accessed (setup only or error cases only)
22
23// Component error messages - only stores messages for failed components
24// Lazy allocated since most configs have zero failures
25// Note: We don't clear this vector because:
26// 1. Components are never destroyed in ESPHome
27// 2. Failed components remain failed (no recovery mechanism)
28// 3. Memory usage is minimal (only failures with custom messages are stored)
29
30// Using namespace-scope static to avoid guard variables (saves 16 bytes total)
31// This is safe because ESPHome is single-threaded during initialization
32namespace {
33struct ComponentErrorMessage {
34 const Component *component;
35 const LogString *message;
36};
37
38#ifdef USE_SETUP_PRIORITY_OVERRIDE
39struct ComponentPriorityOverride {
40 const Component *component;
41 float priority;
42};
43
44// Setup priority overrides - freed after setup completes
45// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead
46// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
47std::vector<ComponentPriorityOverride> *setup_priority_overrides = nullptr;
48#endif
49
50// Error messages for failed components
51// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead
52// This is never freed as error messages persist for the lifetime of the device
53// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
54std::vector<ComponentErrorMessage> *component_error_messages = nullptr;
55
56// Helper to store error messages
57void store_component_error_message(const Component *component, const LogString *message) {
58 // Lazy allocate the error messages vector if needed
59 if (!component_error_messages) {
60 component_error_messages = new std::vector<ComponentErrorMessage>();
61 }
62 // Check if this component already has an error message
63 for (auto &entry : *component_error_messages) {
64 if (entry.component == component) {
65 entry.message = message;
66 return;
67 }
68 }
69 // Add new error message
70 component_error_messages->emplace_back(ComponentErrorMessage{component, message});
71}
72} // namespace
73
74// setup_priority, component state, and status LED constants are now
75// constexpr in component.h
76
77static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS =
78 10U;
79// Threshold in ms (computed from centiseconds constant in component.h)
80static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast<uint32_t>(WARN_IF_BLOCKING_OVER_CS) * 10U;
81
83
85
87
88void Component::set_interval(const std::string &name, uint32_t interval, std::function<void()> &&f) { // NOLINT
89#pragma GCC diagnostic push
90#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
91 App.scheduler.set_interval(this, name, interval, std::move(f));
92#pragma GCC diagnostic pop
93}
94
95void Component::set_interval(const char *name, uint32_t interval, std::function<void()> &&f) { // NOLINT
96 App.scheduler.set_interval(this, name, interval, std::move(f));
97}
98
99bool Component::cancel_interval(const std::string &name) { // NOLINT
100#pragma GCC diagnostic push
101#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
102 return App.scheduler.cancel_interval(this, name);
103#pragma GCC diagnostic pop
104}
105
106bool Component::cancel_interval(const char *name) { // NOLINT
107 return App.scheduler.cancel_interval(this, name);
108}
109
110void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts,
111 std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT
112#pragma GCC diagnostic push
113#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
114 App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
115#pragma GCC diagnostic pop
116}
117
118void Component::set_retry(const char *name, uint32_t initial_wait_time, uint8_t max_attempts,
119 std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT
120#pragma GCC diagnostic push
121#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
122 App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
123#pragma GCC diagnostic pop
124}
125
126bool Component::cancel_retry(const std::string &name) { // NOLINT
127#pragma GCC diagnostic push
128#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
129 return App.scheduler.cancel_retry(this, name);
130#pragma GCC diagnostic pop
131}
132
133bool Component::cancel_retry(const char *name) { // NOLINT
134#pragma GCC diagnostic push
135#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
136 return App.scheduler.cancel_retry(this, name);
137#pragma GCC diagnostic pop
138}
139
140void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) { // NOLINT
141#pragma GCC diagnostic push
142#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
143 App.scheduler.set_timeout(this, name, timeout, std::move(f));
144#pragma GCC diagnostic pop
145}
146
147void Component::set_timeout(const char *name, uint32_t timeout, std::function<void()> &&f) { // NOLINT
148 App.scheduler.set_timeout(this, name, timeout, std::move(f));
149}
150
151bool Component::cancel_timeout(const std::string &name) { // NOLINT
152#pragma GCC diagnostic push
153#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
154 return App.scheduler.cancel_timeout(this, name);
155#pragma GCC diagnostic pop
156}
157
158bool Component::cancel_timeout(const char *name) { // NOLINT
159 return App.scheduler.cancel_timeout(this, name);
160}
161
162// uint32_t (numeric ID) overloads - zero heap allocation
163void Component::set_timeout(uint32_t id, uint32_t timeout, std::function<void()> &&f) { // NOLINT
164 App.scheduler.set_timeout(this, id, timeout, std::move(f));
165}
166
167bool Component::cancel_timeout(uint32_t id) { return App.scheduler.cancel_timeout(this, id); }
168
169void Component::set_timeout(InternalSchedulerID id, uint32_t timeout, std::function<void()> &&f) { // NOLINT
170 App.scheduler.set_timeout(this, id, timeout, std::move(f));
171}
172
173bool Component::cancel_timeout(InternalSchedulerID id) { return App.scheduler.cancel_timeout(this, id); }
174
175void Component::set_interval(uint32_t id, uint32_t interval, std::function<void()> &&f) { // NOLINT
176 App.scheduler.set_interval(this, id, interval, std::move(f));
177}
178
179bool Component::cancel_interval(uint32_t id) { return App.scheduler.cancel_interval(this, id); }
180
181void Component::set_interval(InternalSchedulerID id, uint32_t interval, std::function<void()> &&f) { // NOLINT
182 App.scheduler.set_interval(this, id, interval, std::move(f));
183}
184
185bool Component::cancel_interval(InternalSchedulerID id) { return App.scheduler.cancel_interval(this, id); }
186
187void Component::set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts,
188 std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT
189#pragma GCC diagnostic push
190#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
191 App.scheduler.set_retry(this, id, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
192#pragma GCC diagnostic pop
193}
194
195bool Component::cancel_retry(uint32_t id) {
196#pragma GCC diagnostic push
197#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
198 return App.scheduler.cancel_retry(this, id);
199#pragma GCC diagnostic pop
200}
201
202void Component::call_setup() { this->setup(); }
204 this->dump_config();
205 if (this->is_failed()) {
206 // Look up error message from global vector
207 const LogString *error_msg = nullptr;
208 if (component_error_messages) {
209 for (const auto &entry : *component_error_messages) {
210 if (entry.component == this) {
211 error_msg = entry.message;
212 break;
213 }
214 }
215 }
216 ESP_LOGE(TAG, " %s is marked FAILED: %s", LOG_STR_ARG(this->get_component_log_str()),
217 error_msg ? LOG_STR_ARG(error_msg) : LOG_STR_LITERAL("unspecified"));
218 }
219}
220
223 switch (state) {
225 // State Construction: Call setup and set state to setup
227 ESP_LOGV(TAG, "Setup %s", LOG_STR_ARG(this->get_component_log_str()));
228#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
229 uint32_t start_time = millis();
230#endif
231 this->call_setup();
232#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
233 uint32_t setup_time = millis() - start_time;
234 // Only log at CONFIG level if setup took longer than the blocking threshold
235 // to avoid spamming the log and blocking the event loop
236 if (setup_time >= WARN_IF_BLOCKING_OVER_MS) {
237 ESP_LOGCONFIG(TAG, "Setup %s took %ums", LOG_STR_ARG(this->get_component_log_str()), (unsigned) setup_time);
238 } else {
239 ESP_LOGV(TAG, "Setup %s took %ums", LOG_STR_ARG(this->get_component_log_str()), (unsigned) setup_time);
240 }
241#endif
242 break;
243 }
245 // State setup: Call first loop and set state to loop
247 this->loop();
248 break;
250 // State loop: Call loop
251 this->loop();
252 break;
254 // State failed: Do nothing
256 // State loop done: Do nothing, component has finished its work
257 default:
258 break;
259 }
260}
261bool Component::should_warn_of_blocking(uint32_t blocking_time, uint32_t &threshold_ms_out) {
262 // Convert centisecond threshold to milliseconds for comparison
263 uint32_t threshold_ms = static_cast<uint32_t>(this->warn_if_blocking_over_) * 10U;
264 // Report the threshold that was exceeded (before any ratcheting below) so the warning is accurate.
265 threshold_ms_out = threshold_ms;
266 if (blocking_time > threshold_ms) {
267 // Set new threshold: blocking_time + increment, converted back to centiseconds
268 uint32_t new_threshold_ms = blocking_time + WARN_IF_BLOCKING_INCREMENT_MS;
269 uint32_t new_cs = new_threshold_ms / 10U;
270 // Saturate at uint8_t max (255 = 2550ms)
271 this->warn_if_blocking_over_ = static_cast<uint8_t>(new_cs > 255U ? 255U : new_cs);
272 return true;
273 }
274 return false;
275}
277 ESP_LOGE(TAG, "%s was marked as failed", LOG_STR_ARG(this->get_component_log_str()));
279 this->status_set_error();
280 // Also remove from loop since failed components shouldn't loop
282}
285 ESP_LOGVV(TAG, "%s loop disabled", LOG_STR_ARG(this->get_component_log_str()));
288 }
289}
291 ESP_LOGVV(TAG, "%s loop enabled", LOG_STR_ARG(this->get_component_log_str()));
294}
296 // This method is thread and ISR-safe because:
297 // 1. Only performs simple assignments to volatile variables (atomic on all platforms)
298 // 2. No read-modify-write operations that could be interrupted
299 // 3. No memory allocation or object construction; on ESP32 the only call (wake_loop_any_context) is ISR-safe
300 // 4. IRAM_ATTR ensures code is in IRAM, not flash (required for ISR execution)
301 // 5. Components are never destroyed, so no use-after-free concerns
302 // 6. App is guaranteed to be initialized before any ISR could fire
303 // 7. Multiple ISR/thread calls are safe - just sets the same flags to true
304 // 8. Race condition with main loop is handled by clearing flag before processing
305 this->pending_enable_loop_ = true;
307 // Wake the main loop from sleep. Without this, the main loop would not
308 // wake until the select/delay timeout expires (~16ms).
310}
313 ESP_LOGI(TAG, "%s is being reset to construction state", LOG_STR_ARG(this->get_component_log_str()));
315 // Clear error status when resetting
316 this->status_clear_error();
317 }
318}
319void Component::defer(std::function<void()> &&f) { // NOLINT
320 App.scheduler.set_timeout(this, static_cast<const char *>(nullptr), 0, std::move(f));
321}
322bool Component::cancel_defer(const std::string &name) { // NOLINT
323#pragma GCC diagnostic push
324#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
325 return App.scheduler.cancel_timeout(this, name);
326#pragma GCC diagnostic pop
327}
328bool Component::cancel_defer(const char *name) { // NOLINT
329 return App.scheduler.cancel_timeout(this, name);
330}
331void Component::defer(const std::string &name, std::function<void()> &&f) { // NOLINT
332#pragma GCC diagnostic push
333#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
334 App.scheduler.set_timeout(this, name, 0, std::move(f));
335#pragma GCC diagnostic pop
336}
337void Component::defer(const char *name, std::function<void()> &&f) { // NOLINT
338 App.scheduler.set_timeout(this, name, 0, std::move(f));
339}
340void Component::defer(uint32_t id, std::function<void()> &&f) { // NOLINT
341 App.scheduler.set_timeout(this, id, 0, std::move(f));
342}
343bool Component::cancel_defer(uint32_t id) { return App.scheduler.cancel_timeout(this, id); }
344void Component::set_timeout(uint32_t timeout, std::function<void()> &&f) { // NOLINT
345 App.scheduler.set_timeout(this, static_cast<const char *>(nullptr), timeout, std::move(f));
346}
347void Component::set_interval(uint32_t interval, std::function<void()> &&f) { // NOLINT
348 App.scheduler.set_interval(this, static_cast<const char *>(nullptr), interval, std::move(f));
349}
350void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f,
351 float backoff_increase_factor) { // NOLINT
352#pragma GCC diagnostic push
353#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
354 App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
355#pragma GCC diagnostic pop
356}
358 // Bitmask check: valid states are SETUP(1), LOOP(2), LOOP_DONE(4)
359 // (1 << state) & 0b10110 checks membership in one instruction
360 return ((1u << (this->component_state_ & COMPONENT_STATE_MASK)) &
361 ((1u << COMPONENT_STATE_SETUP) | (1u << COMPONENT_STATE_LOOP) | (1u << COMPONENT_STATE_LOOP_DONE))) != 0;
362}
363bool Component::can_proceed() { return true; }
364bool Component::set_status_flag_(uint8_t flag) {
365 if ((this->component_state_ & flag) != 0)
366 return false;
367 this->component_state_ |= flag;
368 App.app_state_ |= flag;
369 return true;
370}
371
372void Component::status_set_warning() { this->status_set_warning((const LogString *) nullptr); }
375 return;
376 ESP_LOGW(TAG, "%s set Warning flag: %s", LOG_STR_ARG(this->get_component_log_str()),
377 message ? message : LOG_STR_LITERAL("unspecified"));
378}
381 return;
382 ESP_LOGW(TAG, "%s set Warning flag: %s", LOG_STR_ARG(this->get_component_log_str()),
383 message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified"));
384}
385void Component::status_set_error() { this->status_set_error((const LogString *) nullptr); }
386void Component::status_set_error(const LogString *message) {
388 return;
389 ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()),
390 message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified"));
391 if (message != nullptr) {
392 store_component_error_message(this, message);
393 }
394}
396 this->component_state_ &= ~STATUS_LED_WARNING;
397 // Clear the app-wide STATUS_LED_WARNING bit only if setup has finished
398 // AND no other component still has it set. During setup the forced
399 // STATUS_LED_WARNING (from the slow-setup busy-wait) must not be wiped
400 // by a transient component clear — Application::setup() reconciles
401 // the warning bit once at the end before setting APP_STATE_SETUP_COMPLETE.
402 // The set path is unchanged (set_status_flag_ still writes directly).
404 App.app_state_ &= ~STATUS_LED_WARNING;
405 ESP_LOGW(TAG, "%s cleared Warning flag", LOG_STR_ARG(this->get_component_log_str()));
406}
408 this->component_state_ &= ~STATUS_LED_ERROR;
409 // STATUS_LED_ERROR is never artificially forced — it only ever lands
410 // in app_state_ via a real set_status_flag_ call. So the walk-and-clear
411 // path is always safe, including during setup.
413 App.app_state_ &= ~STATUS_LED_ERROR;
414 ESP_LOGE(TAG, "%s cleared Error flag", LOG_STR_ARG(this->get_component_log_str()));
415}
417 this->status_set_warning();
418 this->set_timeout(name, length, [this]() { this->status_clear_warning(); });
419}
421 this->status_set_error();
422 this->set_timeout(name, length, [this]() { this->status_clear_error(); });
423}
425
426// Function implementation of LOG_UPDATE_INTERVAL macro to reduce code size
428 uint32_t update_interval = component->get_update_interval();
429 if (update_interval == SCHEDULER_DONT_RUN) {
430 ESP_LOGCONFIG(tag, " Update Interval: never");
431 } else if (update_interval < 100) {
432 ESP_LOGCONFIG(tag, " Update Interval: %.3fs", update_interval / 1000.0f);
433 } else {
434 ESP_LOGCONFIG(tag, " Update Interval: %.1fs", update_interval / 1000.0f);
435 }
436}
438#ifdef USE_SETUP_PRIORITY_OVERRIDE
439 // Check if there's an override in the global vector
440 if (setup_priority_overrides) {
441 // Linear search is fine for small n (typically < 5 overrides)
442 for (const auto &entry : *setup_priority_overrides) {
443 if (entry.component == this) {
444 return entry.priority;
445 }
446 }
447 }
448#endif
449 return this->get_setup_priority();
450}
451#ifdef USE_SETUP_PRIORITY_OVERRIDE
453 // Lazy allocate the vector if needed
454 if (!setup_priority_overrides) {
455 setup_priority_overrides = new std::vector<ComponentPriorityOverride>();
456 }
457
458 // Check if this component already has an override
459 for (auto &entry : *setup_priority_overrides) {
460 if (entry.component == this) {
461 entry.priority = priority;
462 return;
463 }
464 }
465
466 // Add new override
467 setup_priority_overrides->emplace_back(ComponentPriorityOverride{this, priority});
468}
469#endif
470
471PollingComponent::PollingComponent(uint32_t update_interval) : update_interval_(update_interval) {}
472
474 // init the poller before calling setup, allowing setup to cancel it if desired
475 this->start_poller();
476 // Let the polling component subclass setup their HW.
477 this->setup();
478}
479
481 // Register interval.
482 this->set_interval(InternalSchedulerID::POLLING_UPDATE, this->get_update_interval(), [this]() { this->update(); });
483}
484
486 // Clear the interval to suspend component
488}
489
491
492#ifdef USE_RUNTIME_STATS
493uint64_t ComponentRuntimeStats::global_recorded_us = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
494#endif
495
496void __attribute__((noinline, cold)) LoopBlockingGuard::warn_blocking(uint32_t blocking_time) {
497 // Identity is published on App by the caller before the guard is built; read it back here.
499 // Component-less path always warns (the caller already checked the constant threshold).
500 uint32_t threshold_ms = WARN_IF_BLOCKING_OVER_MS;
501 if (component != nullptr && !component->should_warn_of_blocking(blocking_time, threshold_ms)) {
502 return; // Component's (possibly ratcheted) threshold not exceeded yet
503 }
504 // Component name if any, else the published source (owning script), else a generic label.
505 const LogString *name;
506 if (component != nullptr) {
507 name = component->get_component_log_str();
508 } else {
509 name = App.get_current_source();
510 if (name == nullptr)
511 name = LOG_STR("a scheduled task");
512 }
513 ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms), max is %" PRIu32 " ms", LOG_STR_ARG(name),
514 blocking_time, threshold_ms);
515}
516
517#ifdef USE_SETUP_PRIORITY_OVERRIDE
519 // Free the setup priority map completely
520 delete setup_priority_overrides;
521 setup_priority_overrides = nullptr;
522}
523#endif
524
525// Weak default for component_source_lookup - overridden by generated code
526__attribute__((weak)) const LogString *component_source_lookup(uint8_t) { return LOG_STR("<unknown>"); }
527
528} // namespace esphome
Component * get_current_component()
bool any_component_has_status_flag_(uint8_t flag) const
Walk all registered components looking for any whose component_state_ has the given flag set.
void enable_component_loop_(Component *component)
void disable_component_loop_(Component *component)
const LogString * get_current_source()
volatile bool has_pending_enable_loop_requests_
bool is_setup_complete() const
True once Application::setup() has finished walking all components and finalized the initial status f...
void mark_failed()
Mark this component as failed.
void status_momentary_error(const char *name, uint32_t length=5000)
Set error status flag and automatically clear it after a timeout.
virtual float get_setup_priority() const
priority of setup().
Definition component.cpp:82
virtual void setup()
Where the component's initialization should happen.
Definition component.cpp:84
float get_actual_setup_priority() const
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std voi defer)(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call.
Definition component.h:543
bool set_status_flag_(uint8_t flag)
Helper to set a status LED flag on both this component and the app.
bool is_failed() const
Definition component.h:272
void enable_loop_slow_path_()
volatile bool pending_enable_loop_
ISR-safe flag for enable_loop_soon_any_context.
Definition component.h:571
virtual bool can_proceed()
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.h:493
void status_clear_error()
Definition component.h:295
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std voi set_interval)(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
Definition component.h:400
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_defer(const std boo cancel_defer)(const char *name)
Cancel a defer callback using the specified name, name must not be empty.
Definition component.h:555
void enable_loop_soon_any_context()
Thread and ISR-safe version of enable_loop() that can be called from any context.
uint8_t component_state_
State of this component - each bit has a purpose: Bits 0-2: Component state (0x00=CONSTRUCTION,...
Definition component.h:570
bool should_warn_of_blocking(uint32_t blocking_time, uint32_t &threshold_ms_out)
void status_momentary_warning(const char *name, uint32_t length=5000)
Set warning status flag and automatically clear it after a timeout.
bool is_ready() const
virtual void dump_config()
const LogString * get_component_log_str() const ESPHOME_ALWAYS_INLINE
Get the integration where this component was declared as a LogString for logging.
Definition component.h:325
void status_clear_warning_slow_path_()
void set_component_state_(uint8_t state)
Helper to set component state (clears state bits and sets new state)
Definition component.h:349
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t uint8_t std::function< RetryResult(uint8_t)> float backoff_increase_factor
Definition component.h:437
void status_clear_error_slow_path_()
void disable_loop()
Disable this component's loop.
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t initial_wait_time
Definition component.h:436
virtual void loop()
This method will be called repeatedly.
Definition component.cpp:86
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(const std boo cancel_timeout)(const char *name)
Cancel a timeout function.
Definition component.h:515
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t uint8_t max_attempts
Definition component.h:436
void reset_to_construction_state()
Reset this component back to the construction state to allow setup to run again.
uint8_t warn_if_blocking_over_
Warn threshold in centiseconds (max 2550ms)
Definition component.h:563
void set_setup_priority(float priority)
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(const std boo cancel_interval)(const char *name)
Cancel an interval function.
Definition component.h:422
ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", "2026.2.0") void set_retry(const std uint32_t uint8_t std::function< RetryResult(uint8_t)> && f
Definition component.h:437
void status_clear_warning()
Definition component.h:289
virtual void call_setup()
This class simplifies creating components that periodically check a state.
Definition component.h:585
virtual uint32_t get_update_interval() const
Get the update interval in ms of this sensor.
void call_setup() override
virtual void update()=0
struct @65::@66 __attribute__
Wake the main loop task from an ISR. ISR-safe.
Definition main_task.h:32
const Component * component
Definition component.cpp:34
const LogString * message
Definition component.cpp:35
uint8_t priority
bool state
Definition fan.h:2
constexpr float DATA
For components that import data from directly connected sensors like DHT.
Definition component.h:43
const char *const TAG
Definition spi.cpp:7
const char * tag
Definition log.h:74
constexpr uint8_t COMPONENT_STATE_FAILED
Definition component.h:83
constexpr uint8_t WARN_IF_BLOCKING_OVER_CS
Definition component.h:100
InternalSchedulerID
Type-safe scheduler IDs for core base classes.
Definition component.h:66
constexpr uint8_t COMPONENT_STATE_LOOP
Definition component.h:82
constexpr uint8_t STATUS_LED_WARNING
Definition component.h:88
constexpr uint8_t COMPONENT_STATE_MASK
Definition component.h:79
void log_update_interval(const char *tag, PollingComponent *component)
void clear_setup_priority_overrides()
const LogString * component_source_lookup(uint8_t index)
Lookup component source name by index (1-based).
constexpr uint8_t COMPONENT_STATE_LOOP_DONE
Definition component.h:84
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:28
Application App
Global storage of Application pointer - only one Application can exist.
constexpr uint8_t COMPONENT_STATE_SETUP
Definition component.h:81
constexpr uint8_t COMPONENT_STATE_CONSTRUCTION
Definition component.h:80
constexpr uint8_t STATUS_LED_ERROR
Definition component.h:89
constexpr uint32_t SCHEDULER_DONT_RUN
Definition component.h:61
void IRAM_ATTR wake_loop_any_context()
IRAM_ATTR entry point for ISR callers — defined in wake_esp8266.cpp.
static void uint32_t
static uint64_t global_recorded_us
Definition component.h:124
uint16_t length
Definition tt21100.cpp:0