ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
component.h
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4#include <cstdint>
5#include <functional>
6#include <string>
7
9#include "esphome/core/hal.h"
11#include "esphome/core/log.h"
14
15// Forward declarations for friend access from codegen-generated setup()
16void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h
17void original_setup(); // NOLINT(readability-redundant-declaration)
18
19namespace esphome {
20
21// Forward declaration for LogString
22struct LogString;
23
24#ifdef USE_RUNTIME_STATS
25namespace runtime_stats {
26class RuntimeStatsCollector;
27} // namespace runtime_stats
28#endif
29
34namespace setup_priority {
35
37inline constexpr float POWER = 1200.0f;
39inline constexpr float BUS = 1000.0f;
41inline constexpr float IO = 900.0f;
43inline constexpr float HARDWARE = 800.0f;
45inline constexpr float DATA = 600.0f;
47inline constexpr float PROCESSOR = 400.0f;
48inline constexpr float BLUETOOTH = 350.0f;
49inline constexpr float AFTER_BLUETOOTH = 300.0f;
50inline constexpr float WIFI = 250.0f;
51inline constexpr float ETHERNET = 250.0f;
53inline constexpr float BEFORE_CONNECTION = 220.0f;
55inline constexpr float AFTER_WIFI = 200.0f;
57inline constexpr float AFTER_CONNECTION = 100.0f;
59inline constexpr float LATE = -100.0f;
60
61} // namespace setup_priority
62
63inline constexpr uint32_t SCHEDULER_DONT_RUN = 4294967295UL;
64
69 POLLING_UPDATE = 0, // PollingComponent interval
70 STATUS_WARNING = 1, // status_momentary_warning() without a name
71 STATUS_ERROR = 2, // status_momentary_error() without a name
72};
73
74// Forward declaration
75class PollingComponent;
76
77// Function declaration for LOG_UPDATE_INTERVAL
78void log_update_interval(const char *tag, PollingComponent *component);
79
80#define LOG_UPDATE_INTERVAL(this) log_update_interval(TAG, this)
81
82// Component state uses bits 0-2 (8 states, 5 used)
83inline constexpr uint8_t COMPONENT_STATE_MASK = 0x07;
84inline constexpr uint8_t COMPONENT_STATE_CONSTRUCTION = 0x00;
85inline constexpr uint8_t COMPONENT_STATE_SETUP = 0x01;
86inline constexpr uint8_t COMPONENT_STATE_LOOP = 0x02;
87inline constexpr uint8_t COMPONENT_STATE_FAILED = 0x03;
88inline constexpr uint8_t COMPONENT_STATE_LOOP_DONE = 0x04;
89// Status LED uses bits 3-4
90inline constexpr uint8_t STATUS_LED_MASK = 0x18;
91inline constexpr uint8_t STATUS_LED_OK = 0x00;
92inline constexpr uint8_t STATUS_LED_WARNING = 0x08;
93inline constexpr uint8_t STATUS_LED_ERROR = 0x10;
94// Component loop override flag uses bit 5 (set at registration time)
95inline constexpr uint8_t COMPONENT_HAS_LOOP = 0x20;
96// Bit 6 on Application::app_state_ (ONLY) — set at the end of
97// Application::setup(). Component::status_clear_*_slow_path_() uses this to
98// decide whether to propagate clears to App.app_state_. Never set on a
99// Component's component_state_.
100inline constexpr uint8_t APP_STATE_SETUP_COMPLETE = 0x40;
101
102inline constexpr uint8_t WARN_IF_BLOCKING_OVER_CS = 5U; // 50ms in centiseconds (1cs = 10ms)
103
106const LogString *component_source_lookup(uint8_t index);
107
108#ifdef USE_RUNTIME_STATS
112 // Period stats (reset each logging interval)
116 // Total stats (persistent until reboot, uint64_t to avoid overflow)
118 uint64_t total_time_us{0};
120
121 // Cumulative sum of every record_time() duration since boot, across all
122 // components. Used by Application::loop() to snapshot time spent inside
123 // LoopBlockingGuard (including guards constructed by the
124 // scheduler at scheduler.cpp) so main-loop overhead accounting can
125 // subtract scheduled-callback time from the before_loop_tasks_ wall time.
126 static uint64_t global_recorded_us; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
127
128 void record_time(uint32_t duration_us) {
129 this->period_count++;
130 this->period_time_us += duration_us;
131 if (duration_us > this->period_max_time_us)
132 this->period_max_time_us = duration_us;
133 this->total_count++;
134 this->total_time_us += duration_us;
135 if (duration_us > this->total_max_time_us)
136 this->total_max_time_us = duration_us;
137 global_recorded_us += duration_us;
138 }
140 this->period_count = 0;
141 this->period_time_us = 0;
142 this->period_max_time_us = 0;
143 }
144};
145#endif
146
148 public:
154 virtual void setup();
155
161 virtual void loop();
162
163 virtual void dump_config();
164
171 virtual float get_setup_priority() const;
172
173 float get_actual_setup_priority() const;
174
175 void set_setup_priority(float priority);
176
177 void call();
178
179 virtual void on_shutdown() {}
180 virtual void on_safe_shutdown() {}
181
186 virtual bool teardown() { return true; }
187
193 virtual void on_powerdown() {}
194
195 uint8_t get_component_state() const { return this->component_state_; }
196
202
207 bool is_in_loop_state() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP; }
208
215 bool is_idle() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE; }
216
223 void mark_failed();
224
225 void mark_failed(const LogString *message) {
226 this->status_set_error(message);
227 this->mark_failed();
228 }
229
238 void disable_loop();
239
248 void enable_loop() {
249 if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE)
251 }
252
273
274 bool is_failed() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; }
275
276 bool is_ready() const;
277
278 virtual bool can_proceed();
279
281
282 bool status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; }
283
284 void status_set_warning(); // Set warning flag without message
285 void status_set_warning(const char *message);
286 void status_set_warning(const LogString *message);
287
290 bool status_comm_result(bool ok);
291 bool status_comm_result(bool ok, const LogString *message);
292
293 void status_set_error(); // Set error flag without message
294 void status_set_error(const LogString *message);
295
297 if ((this->component_state_ & STATUS_LED_WARNING) == 0)
298 return;
300 }
301
303 if ((this->component_state_ & STATUS_LED_ERROR) == 0)
304 return;
306 }
307
308 // Remove before 2027.5.0
309 ESPDEPRECATED("Use status_momentary_warning() without a name. Removed in 2027.5.0", "2026.11.0")
310 void status_momentary_warning(const char *name, uint32_t length = 5000);
311
315 void status_momentary_warning(const LogString *message, uint32_t length = 5000);
316
317 // Remove before 2027.5.0
318 ESPDEPRECATED("Use status_momentary_error() without a name. Removed in 2027.5.0", "2026.11.0")
319 void status_momentary_error(const char *name, uint32_t length = 5000);
320
324 void status_momentary_error(const LogString *message, uint32_t length = 5000);
325
326 bool has_overridden_loop() const { return (this->component_state_ & COMPONENT_HAS_LOOP) != 0; }
327
332 inline const LogString *get_component_log_str() const ESPHOME_ALWAYS_INLINE {
334 }
335
336 bool should_warn_of_blocking(uint32_t blocking_time, uint32_t &threshold_ms_out);
337
338 protected:
339 friend class Application;
340 friend void ::setup();
341 friend void ::original_setup();
342
348 void set_component_source_(uint8_t index) { this->component_source_index_ = index; }
349
350 virtual void call_setup();
351 void call_dump_config_();
352
354
356 inline void set_component_state_(uint8_t state) {
357 this->component_state_ &= ~COMPONENT_STATE_MASK;
358 this->component_state_ |= state;
359 }
360
365 bool set_status_flag_(uint8_t flag);
367 bool set_error_flag_(const LogString *message);
368
397 void set_interval(const char *name, uint32_t interval, std::function<void()> &&f); // NOLINT
398
405 void set_interval(uint32_t id, uint32_t interval, std::function<void()> &&f); // NOLINT
406
407 void set_interval(InternalSchedulerID id, uint32_t interval, std::function<void()> &&f); // NOLINT
408
409 void set_interval(uint32_t interval, std::function<void()> &&f); // NOLINT
410
416 bool cancel_interval(const char *name); // NOLINT
417 bool cancel_interval(uint32_t id); // NOLINT
418 bool cancel_interval(InternalSchedulerID id); // NOLINT
419
442 void set_timeout(const char *name, uint32_t timeout, std::function<void()> &&f); // NOLINT
443
450 void set_timeout(uint32_t id, uint32_t timeout, std::function<void()> &&f); // NOLINT
451
452 void set_timeout(InternalSchedulerID id, uint32_t timeout, std::function<void()> &&f); // NOLINT
453
454 void set_timeout(uint32_t timeout, std::function<void()> &&f); // NOLINT
455
461 bool cancel_timeout(const char *name); // NOLINT
462 bool cancel_timeout(uint32_t id); // NOLINT
463 bool cancel_timeout(InternalSchedulerID id); // NOLINT
464
480 void defer(const char *name, std::function<void()> &&f); // NOLINT
481
483 void defer(std::function<void()> &&f); // NOLINT
484
486 void defer(uint32_t id, std::function<void()> &&f); // NOLINT
487
489 bool cancel_defer(const char *name); // NOLINT
490 bool cancel_defer(uint32_t id); // NOLINT
491
494
495 // Ordered for optimal packing on 32-bit systems (8 bytes total with vtable)
504 uint8_t component_state_{0x00};
505 volatile bool pending_enable_loop_{false};
506#ifdef USE_RUNTIME_STATS
508 friend class LoopBlockingGuard;
510#endif
511};
512
520 public:
522
527 explicit PollingComponent(uint32_t update_interval);
528
533 void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
534
535 // ========== OVERRIDE METHODS ==========
536 // (You'll only need this when creating your own custom sensor)
537 virtual void update() = 0;
538
539 // ========== INTERNAL METHODS ==========
540 // (In most use cases you won't need these)
541 void call_setup() override;
542
544 virtual uint32_t get_update_interval() const;
545
546 // Start the poller, used for component.suspend
547 void start_poller();
548
549 // Stop the poller, used for component.suspend
550 void stop_poller();
551
552 protected:
554};
555
556// LoopBlockingGuard lives in application.h because it reads its state from App.
557
558// Function to clear setup priority overrides after all components are set up
559// Only has an implementation when USE_SETUP_PRIORITY_OVERRIDE is defined
561
562} // namespace esphome
void mark_failed()
Mark this component as failed.
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
bool has_overridden_loop() const
Definition component.h:326
void mark_failed(const LogString *message)
Definition component.h:225
virtual void on_powerdown()
Called after teardown is complete to power down hardware.
Definition component.h:193
bool set_status_flag_(uint8_t flag)
Helper to set a status LED flag on both this component and the app.
ComponentRuntimeStats runtime_stats_
Definition component.h:509
bool is_failed() const
Definition component.h:274
uint8_t get_component_state() const
Definition component.h:195
void enable_loop_slow_path_()
volatile bool pending_enable_loop_
ISR-safe flag for enable_loop_soon_any_context.
Definition component.h:505
virtual bool can_proceed()
virtual void on_safe_shutdown()
Definition component.h:180
bool cancel_interval(const char *name)
Cancel an interval function.
Definition component.cpp:92
void status_clear_error()
Definition component.h:302
void set_component_source_(uint8_t index)
Set where this component was loaded from for some debug messages.
Definition component.h:348
bool status_comm_result(bool ok)
Clears the warning when ok, else sets it with message (default "Communication failed"); returns ok.
bool is_in_loop_state() const
Check if this component has completed setup and is in the loop state.
Definition component.h:207
void status_momentary_warning(uint32_t length=5000)
Set warning status flag and clear it after length ms.
virtual bool teardown()
Called during teardown to allow component to gracefully finish operations.
Definition component.h:186
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:504
bool should_warn_of_blocking(uint32_t blocking_time, uint32_t &threshold_ms_out)
bool cancel_timeout(const char *name)
Cancel a timeout function.
bool is_ready() const
virtual void dump_config()
void enable_loop()
Enable this component's loop.
Definition component.h:248
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:332
uint8_t component_source_index_
Index into component source PROGMEM lookup table (0 = not set)
Definition component.h:496
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:356
bool status_has_warning() const
Definition component.h:280
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
void defer(const char *name, std::function< void()> &&f)
Defer a callback to the next loop() call with a const char* name.
bool status_has_error() const
Definition component.h:282
void status_clear_error_slow_path_()
void disable_loop()
Disable this component's loop.
virtual void on_shutdown()
Definition component.h:179
ESPDEPRECATED("Use status_momentary_warning() without a name. Removed in 2027.5.0", "2026.11.0") void status_momentary_warning(const char *name
void set_interval(const char *name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a const char* name.
Definition component.cpp:88
void status_momentary_error(uint32_t length=5000)
Set error status flag and clear it after length ms.
virtual void loop()
This method will be called repeatedly.
Definition component.cpp:86
void reset_to_construction_state()
Reset this component back to the construction state to allow setup to run again.
bool set_error_flag_(const LogString *message)
Set the error flag and log it; true when it was not set before.
uint8_t warn_if_blocking_over_
Warn threshold in centiseconds (max 2550ms)
Definition component.h:497
void set_setup_priority(float priority)
bool cancel_defer(const char *name)
Cancel a defer callback using the specified name, name must not be empty.
void status_clear_warning()
Definition component.h:296
virtual void call_setup()
bool is_idle() const
Check if this component is idle.
Definition component.h:215
This class simplifies creating components that periodically check a state.
Definition component.h:519
virtual uint32_t get_update_interval() const
Get the update interval in ms of this sensor.
void call_setup() override
void set_update_interval(uint32_t update_interval)
Manually set the update interval in ms for this polling object.
Definition component.h:533
virtual void update()=0
const Component * component
Definition component.cpp:34
const LogString * message
Definition component.cpp:35
void original_setup()
void setup()
uint8_t priority
bool state
Definition fan.h:2
constexpr float BEFORE_CONNECTION
For components that should be initialized after WiFi and before API is connected.
Definition component.h:53
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.h:43
constexpr float WIFI
Definition component.h:50
constexpr float ETHERNET
Definition component.h:51
constexpr float AFTER_BLUETOOTH
Definition component.h:49
constexpr float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.h:55
constexpr float LATE
For components that should be initialized at the very end of the setup process.
Definition component.h:59
constexpr float DATA
For components that import data from directly connected sensors like DHT.
Definition component.h:45
constexpr float PROCESSOR
For components that use data from sensors like displays.
Definition component.h:47
constexpr float POWER
For power supply components that must be on before buses like i2c can work.
Definition component.h:37
constexpr float BLUETOOTH
Definition component.h:48
constexpr float BUS
For communication buses like i2c/spi.
Definition component.h:39
constexpr float IO
For components that represent GPIO pins like PCF8573.
Definition component.h:41
constexpr float AFTER_CONNECTION
For components that should be initialized after a data connection (API/MQTT) is connected.
Definition component.h:57
constexpr uint8_t COMPONENT_STATE_FAILED
Definition component.h:87
constexpr uint8_t WARN_IF_BLOCKING_OVER_CS
Definition component.h:102
constexpr uint8_t COMPONENT_HAS_LOOP
Definition component.h:95
InternalSchedulerID
Type-safe scheduler IDs for core base classes.
Definition component.h:68
constexpr uint8_t STATUS_LED_MASK
Definition component.h:90
constexpr uint8_t COMPONENT_STATE_LOOP
Definition component.h:86
constexpr uint8_t APP_STATE_SETUP_COMPLETE
Definition component.h:100
constexpr uint8_t STATUS_LED_WARNING
Definition component.h:92
constexpr uint8_t COMPONENT_STATE_MASK
Definition component.h:83
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:88
constexpr uint8_t COMPONENT_STATE_SETUP
Definition component.h:85
constexpr uint8_t COMPONENT_STATE_CONSTRUCTION
Definition component.h:84
constexpr uint8_t STATUS_LED_OK
Definition component.h:91
constexpr uint8_t STATUS_LED_ERROR
Definition component.h:93
constexpr uint32_t SCHEDULER_DONT_RUN
Definition component.h:63
static void uint32_t
Inline runtime statistics — eliminates std::map lookup on every loop iteration.
Definition component.h:111
static uint64_t global_recorded_us
Definition component.h:126
void record_time(uint32_t duration_us)
Definition component.h:128