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