ESPHome 2025.5.0
Loading...
Searching...
No Matches
component.cpp
Go to the documentation of this file.
2
3#include <cinttypes>
4#include <utility>
6#include "esphome/core/hal.h"
8#include "esphome/core/log.h"
9
10namespace esphome {
11
12static const char *const TAG = "component";
13
14namespace setup_priority {
15
16const float BUS = 1000.0f;
17const float IO = 900.0f;
18const float HARDWARE = 800.0f;
19const float DATA = 600.0f;
20const float PROCESSOR = 400.0;
21const float BLUETOOTH = 350.0f;
22const float AFTER_BLUETOOTH = 300.0f;
23const float WIFI = 250.0f;
24const float ETHERNET = 250.0f;
25const float BEFORE_CONNECTION = 220.0f;
26const float AFTER_WIFI = 200.0f;
27const float AFTER_CONNECTION = 100.0f;
28const float LATE = -100.0f;
29
30} // namespace setup_priority
31
32const uint32_t COMPONENT_STATE_MASK = 0xFF;
33const uint32_t COMPONENT_STATE_CONSTRUCTION = 0x00;
34const uint32_t COMPONENT_STATE_SETUP = 0x01;
35const uint32_t COMPONENT_STATE_LOOP = 0x02;
36const uint32_t COMPONENT_STATE_FAILED = 0x03;
37const uint32_t STATUS_LED_MASK = 0xFF00;
38const uint32_t STATUS_LED_OK = 0x0000;
39const uint32_t STATUS_LED_WARNING = 0x0100;
40const uint32_t STATUS_LED_ERROR = 0x0200;
41
42const uint32_t WARN_IF_BLOCKING_OVER_MS = 50U;
43const uint32_t WARN_IF_BLOCKING_INCREMENT_MS = 10U;
44
45uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
46
47float Component::get_loop_priority() const { return 0.0f; }
48
50
52
54
55void Component::set_interval(const std::string &name, uint32_t interval, std::function<void()> &&f) { // NOLINT
56 App.scheduler.set_interval(this, name, interval, std::move(f));
57}
58
59bool Component::cancel_interval(const std::string &name) { // NOLINT
60 return App.scheduler.cancel_interval(this, name);
61}
62
63void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts,
64 std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT
65 App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
66}
67
68bool Component::cancel_retry(const std::string &name) { // NOLINT
69 return App.scheduler.cancel_retry(this, name);
70}
71
72void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) { // NOLINT
73 App.scheduler.set_timeout(this, name, timeout, std::move(f));
74}
75
76bool Component::cancel_timeout(const std::string &name) { // NOLINT
77 return App.scheduler.cancel_timeout(this, name);
78}
79
80void Component::call_loop() { this->loop(); }
81void Component::call_setup() { this->setup(); }
83 this->dump_config();
84 if (this->is_failed()) {
85 ESP_LOGE(TAG, " Component %s is marked FAILED: %s", this->get_component_source(), this->error_message_.c_str());
86 }
87}
88
89uint32_t Component::get_component_state() const { return this->component_state_; }
92 switch (state) {
94 // State Construction: Call setup and set state to setup
95 this->component_state_ &= ~COMPONENT_STATE_MASK;
97 this->call_setup();
98 break;
100 // State setup: Call first loop and set state to loop
101 this->component_state_ &= ~COMPONENT_STATE_MASK;
103 this->call_loop();
104 break;
106 // State loop: Call loop
107 this->call_loop();
108 break;
109 case COMPONENT_STATE_FAILED: // NOLINT(bugprone-branch-clone)
110 // State failed: Do nothing
111 break;
112 default:
113 break;
114 }
115}
117 if (this->component_source_ == nullptr)
118 return "<unknown>";
119 return this->component_source_;
120}
121bool Component::should_warn_of_blocking(uint32_t blocking_time) {
122 if (blocking_time > this->warn_if_blocking_over_) {
124 return true;
125 }
126 return false;
127}
129 ESP_LOGE(TAG, "Component %s was marked as failed.", this->get_component_source());
130 this->component_state_ &= ~COMPONENT_STATE_MASK;
132 this->status_set_error();
133}
134void Component::defer(std::function<void()> &&f) { // NOLINT
135 App.scheduler.set_timeout(this, "", 0, std::move(f));
136}
137bool Component::cancel_defer(const std::string &name) { // NOLINT
138 return App.scheduler.cancel_timeout(this, name);
139}
140void Component::defer(const std::string &name, std::function<void()> &&f) { // NOLINT
141 App.scheduler.set_timeout(this, name, 0, std::move(f));
142}
143void Component::set_timeout(uint32_t timeout, std::function<void()> &&f) { // NOLINT
144 App.scheduler.set_timeout(this, "", timeout, std::move(f));
145}
146void Component::set_interval(uint32_t interval, std::function<void()> &&f) { // NOLINT
147 App.scheduler.set_interval(this, "", interval, std::move(f));
148}
149void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f,
150 float backoff_increase_factor) { // NOLINT
151 App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor);
152}
153bool Component::is_failed() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; }
155 return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP ||
156 (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP;
157}
158bool Component::can_proceed() { return true; }
161void Component::status_set_warning(const char *message) {
162 // Don't spam the log. This risks missing different warning messages though.
163 if ((this->component_state_ & STATUS_LED_WARNING) != 0)
164 return;
167 ESP_LOGW(TAG, "Component %s set Warning flag: %s", this->get_component_source(), message);
168}
169void Component::status_set_error(const char *message) {
170 if ((this->component_state_ & STATUS_LED_ERROR) != 0)
171 return;
174 ESP_LOGE(TAG, "Component %s set Error flag: %s", this->get_component_source(), message);
175 if (strcmp(message, "unspecified") != 0)
176 this->error_message_ = message;
177}
179 if ((this->component_state_ & STATUS_LED_WARNING) == 0)
180 return;
181 this->component_state_ &= ~STATUS_LED_WARNING;
182 ESP_LOGW(TAG, "Component %s cleared Warning flag", this->get_component_source());
183}
185 if ((this->component_state_ & STATUS_LED_ERROR) == 0)
186 return;
187 this->component_state_ &= ~STATUS_LED_ERROR;
188 ESP_LOGE(TAG, "Component %s cleared Error flag", this->get_component_source());
189}
190void Component::status_momentary_warning(const std::string &name, uint32_t length) {
191 this->status_set_warning();
192 this->set_timeout(name, length, [this]() { this->status_clear_warning(); });
193}
194void Component::status_momentary_error(const std::string &name, uint32_t length) {
195 this->status_set_error();
196 this->set_timeout(name, length, [this]() { this->status_clear_error(); });
197}
200 if (std::isnan(this->setup_priority_override_))
201 return this->get_setup_priority();
202 return this->setup_priority_override_;
203}
205
207#if defined(USE_HOST) || defined(CLANG_TIDY)
208 bool loop_overridden = true;
209 bool call_loop_overridden = true;
210#else
211#pragma GCC diagnostic push
212#pragma GCC diagnostic ignored "-Wpmf-conversions"
213 bool loop_overridden = (void *) (this->*(&Component::loop)) != (void *) (&Component::loop);
214 bool call_loop_overridden = (void *) (this->*(&Component::call_loop)) != (void *) (&Component::call_loop);
215#pragma GCC diagnostic pop
216#endif
217 return loop_overridden || call_loop_overridden;
218}
219
220PollingComponent::PollingComponent(uint32_t update_interval) : update_interval_(update_interval) {}
221
223 // Let the polling component subclass setup their HW.
224 this->setup();
225
226 // init the poller
227 this->start_poller();
228}
229
231 // Register interval.
232 this->set_interval("update", this->get_update_interval(), [this]() { this->update(); });
233}
234
236 // Clear the interval to suspend component
237 this->cancel_interval("update");
238}
239
241void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
242
244 : started_(start_time), component_(component) {}
246 uint32_t curr_time = millis();
247
248 uint32_t blocking_time = curr_time - this->started_;
249 bool should_warn;
250 if (this->component_ != nullptr) {
251 should_warn = this->component_->should_warn_of_blocking(blocking_time);
252 } else {
253 should_warn = blocking_time > WARN_IF_BLOCKING_OVER_MS;
254 }
255 if (should_warn) {
256 const char *src = component_ == nullptr ? "<null>" : component_->get_component_source();
257 ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, blocking_time);
258 ESP_LOGW(TAG, "Components should block for at most 30 ms.");
259 }
260
261 return curr_time;
262}
263
265
266} // namespace esphome
virtual void mark_failed()
Mark this component as failed.
virtual void call_dump_config()
Definition component.cpp:82
virtual float get_setup_priority() const
priority of setup().
Definition component.cpp:49
virtual void setup()
Where the component's initialization should happen.
Definition component.cpp:51
float get_actual_setup_priority() const
bool has_overridden_loop() const
uint32_t warn_if_blocking_over_
Definition component.h:291
bool is_failed() const
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
Definition component.cpp:55
bool should_warn_of_blocking(uint32_t blocking_time)
virtual bool can_proceed()
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
Definition component.cpp:76
virtual float get_loop_priority() const
priority of loop().
Definition component.cpp:47
void status_momentary_error(const std::string &name, uint32_t length=5000)
const char * get_component_source() const
Get the integration where this component was declared as a string.
bool cancel_retry(const std::string &name)
Cancel a retry function.
Definition component.cpp:68
void status_momentary_warning(const std::string &name, uint32_t length=5000)
bool is_ready() const
virtual void dump_config()
bool status_has_warning() const
bool status_has_error() const
bool cancel_interval(const std::string &name)
Cancel an interval function.
Definition component.cpp:59
void status_set_warning(const char *message="unspecified")
bool cancel_defer(const std::string &name)
Cancel a defer callback using the specified name, name must not be empty.
virtual void loop()
This method will be called repeatedly.
Definition component.cpp:53
void status_set_error(const char *message="unspecified")
uint32_t get_component_state() const
Definition component.cpp:89
uint32_t component_state_
State of this component.
Definition component.h:288
const char * component_source_
Definition component.h:290
void set_setup_priority(float priority)
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
virtual void call_loop()
Definition component.cpp:80
float setup_priority_override_
Definition component.h:289
void status_clear_warning()
virtual void call_setup()
Definition component.cpp:81
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.cpp:72
std::string error_message_
Definition component.h:292
void set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function< RetryResult(uint8_t)> &&f, float backoff_increase_factor=1.0f)
Set an retry function with a unique name.
Definition component.cpp:63
virtual uint32_t get_update_interval() const
Get the update interval in ms of this sensor.
void call_setup() override
virtual void set_update_interval(uint32_t update_interval)
Manually set the update interval in ms for this polling object.
virtual void update()=0
bool cancel_retry(Component *component, const std::string &name)
void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function< RetryResult(uint8_t)> func, float backoff_increase_factor=1.0f)
bool cancel_timeout(Component *component, const std::string &name)
Definition scheduler.cpp:47
bool cancel_interval(Component *component, const std::string &name)
Definition scheduler.cpp:79
void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function< void()> func)
Definition scheduler.cpp:25
void set_interval(Component *component, const std::string &name, uint32_t interval, std::function< void()> func)
Definition scheduler.cpp:50
WarnIfComponentBlockingGuard(Component *component, uint32_t start_time)
uint8_t priority
bool state
Definition fan.h:0
const float BUS
For communication buses like i2c/spi.
Definition component.cpp:16
const float AFTER_CONNECTION
For components that should be initialized after a data connection (API/MQTT) is connected.
Definition component.cpp:27
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:19
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.cpp:18
const float BEFORE_CONNECTION
For components that should be initialized after WiFi and before API is connected.
Definition component.cpp:25
const float IO
For components that represent GPIO pins like PCF8573.
Definition component.cpp:17
const float LATE
For components that should be initialized at the very end of the setup process.
Definition component.cpp:28
const float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition component.cpp:26
const float PROCESSOR
For components that use data from sensors like displays.
Definition component.cpp:20
const float AFTER_BLUETOOTH
Definition component.cpp:22
const char *const TAG
Definition spi.cpp:8
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
const uint32_t STATUS_LED_OK
Definition component.cpp:38
const uint32_t COMPONENT_STATE_FAILED
Definition component.cpp:36
const uint32_t WARN_IF_BLOCKING_INCREMENT_MS
How long the blocking time must be larger to warn again.
Definition component.cpp:43
const uint32_t COMPONENT_STATE_MASK
Definition component.cpp:32
const uint32_t COMPONENT_STATE_LOOP
Definition component.cpp:35
uint32_t global_state
Definition component.cpp:45
const uint32_t COMPONENT_STATE_SETUP
Definition component.cpp:34
const uint32_t STATUS_LED_ERROR
Definition component.cpp:40
const uint32_t COMPONENT_STATE_CONSTRUCTION
Definition component.cpp:33
const uint32_t STATUS_LED_MASK
Definition component.cpp:37
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
Application App
Global storage of Application pointer - only one Application can exist.
const uint32_t STATUS_LED_WARNING
Definition component.cpp:39
const uint32_t WARN_IF_BLOCKING_OVER_MS
Initial blocking time allowed without warning.
Definition component.cpp:42
uint16_t length
Definition tt21100.cpp:0