ESPHome  2021.11.3
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 
9 namespace esphome {
10 
11 static const char *const TAG = "component";
12 
13 namespace setup_priority {
14 
15 const float BUS = 1000.0f;
16 const float IO = 900.0f;
17 const float HARDWARE = 800.0f;
18 const float DATA = 600.0f;
19 const float PROCESSOR = 400.0;
20 const float BLUETOOTH = 350.0f;
21 const float AFTER_BLUETOOTH = 300.0f;
22 const float WIFI = 250.0f;
23 const float BEFORE_CONNECTION = 220.0f;
24 const float AFTER_WIFI = 200.0f;
25 const float AFTER_CONNECTION = 100.0f;
26 const float LATE = -100.0f;
27 
28 } // namespace setup_priority
29 
30 const uint32_t COMPONENT_STATE_MASK = 0xFF;
31 const uint32_t COMPONENT_STATE_CONSTRUCTION = 0x00;
32 const uint32_t COMPONENT_STATE_SETUP = 0x01;
33 const uint32_t COMPONENT_STATE_LOOP = 0x02;
34 const uint32_t COMPONENT_STATE_FAILED = 0x03;
35 const uint32_t STATUS_LED_MASK = 0xFF00;
36 const uint32_t STATUS_LED_OK = 0x0000;
37 const uint32_t STATUS_LED_WARNING = 0x0100;
38 const uint32_t STATUS_LED_ERROR = 0x0200;
39 
40 uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
41 
42 float Component::get_loop_priority() const { return 0.0f; }
43 
45 
47 
48 void Component::loop() {}
49 
50 void Component::set_interval(const std::string &name, uint32_t interval, std::function<void()> &&f) { // NOLINT
51  App.scheduler.set_interval(this, name, interval, std::move(f));
52 }
53 
54 bool Component::cancel_interval(const std::string &name) { // NOLINT
55  return App.scheduler.cancel_interval(this, name);
56 }
57 
58 void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) { // NOLINT
59  return App.scheduler.set_timeout(this, name, timeout, std::move(f));
60 }
61 
62 bool Component::cancel_timeout(const std::string &name) { // NOLINT
63  return App.scheduler.cancel_timeout(this, name);
64 }
65 
66 void Component::call_loop() { this->loop(); }
67 void Component::call_setup() { this->setup(); }
68 void Component::call_dump_config() { this->dump_config(); }
69 
70 uint32_t Component::get_component_state() const { return this->component_state_; }
72  uint32_t state = this->component_state_ & COMPONENT_STATE_MASK;
73  switch (state) {
75  // State Construction: Call setup and set state to setup
76  this->component_state_ &= ~COMPONENT_STATE_MASK;
77  this->component_state_ |= COMPONENT_STATE_SETUP;
78  this->call_setup();
79  break;
81  // State setup: Call first loop and set state to loop
82  this->component_state_ &= ~COMPONENT_STATE_MASK;
83  this->component_state_ |= COMPONENT_STATE_LOOP;
84  this->call_loop();
85  break;
87  // State loop: Call loop
88  this->call_loop();
89  break;
91  // State failed: Do nothing
92  break;
93  default:
94  break;
95  }
96 }
97 const char *Component::get_component_source() const {
98  if (this->component_source_ == nullptr)
99  return "<unknown>";
100  return this->component_source_;
101 }
103  ESP_LOGE(TAG, "Component %s was marked as failed.", this->get_component_source());
104  this->component_state_ &= ~COMPONENT_STATE_MASK;
105  this->component_state_ |= COMPONENT_STATE_FAILED;
106  this->status_set_error();
107 }
108 void Component::defer(std::function<void()> &&f) { // NOLINT
109  App.scheduler.set_timeout(this, "", 0, std::move(f));
110 }
111 bool Component::cancel_defer(const std::string &name) { // NOLINT
112  return App.scheduler.cancel_timeout(this, name);
113 }
114 void Component::defer(const std::string &name, std::function<void()> &&f) { // NOLINT
115  App.scheduler.set_timeout(this, name, 0, std::move(f));
116 }
117 void Component::set_timeout(uint32_t timeout, std::function<void()> &&f) { // NOLINT
118  App.scheduler.set_timeout(this, "", timeout, std::move(f));
119 }
120 void Component::set_interval(uint32_t interval, std::function<void()> &&f) { // NOLINT
121  App.scheduler.set_interval(this, "", interval, std::move(f));
122 }
123 bool Component::is_failed() { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; }
124 bool Component::can_proceed() { return true; }
125 bool Component::status_has_warning() { return this->component_state_ & STATUS_LED_WARNING; }
126 bool Component::status_has_error() { return this->component_state_ & STATUS_LED_ERROR; }
128  this->component_state_ |= STATUS_LED_WARNING;
130 }
132  this->component_state_ |= STATUS_LED_ERROR;
134 }
135 void Component::status_clear_warning() { this->component_state_ &= ~STATUS_LED_WARNING; }
136 void Component::status_clear_error() { this->component_state_ &= ~STATUS_LED_ERROR; }
137 void Component::status_momentary_warning(const std::string &name, uint32_t length) {
138  this->status_set_warning();
139  this->set_timeout(name, length, [this]() { this->status_clear_warning(); });
140 }
141 void Component::status_momentary_error(const std::string &name, uint32_t length) {
142  this->status_set_error();
143  this->set_timeout(name, length, [this]() { this->status_clear_error(); });
144 }
147  if (std::isnan(this->setup_priority_override_))
148  return this->get_setup_priority();
149  return this->setup_priority_override_;
150 }
151 void Component::set_setup_priority(float priority) { this->setup_priority_override_ = priority; }
152 
154 #ifdef CLANG_TIDY
155  bool loop_overridden = true;
156  bool call_loop_overridden = true;
157 #else
158 #pragma GCC diagnostic push
159 #pragma GCC diagnostic ignored "-Wpmf-conversions"
160  bool loop_overridden = (void *) (this->*(&Component::loop)) != (void *) (&Component::loop);
161  bool call_loop_overridden = (void *) (this->*(&Component::call_loop)) != (void *) (&Component::call_loop);
162 #pragma GCC diagnostic pop
163 #endif
164  return loop_overridden || call_loop_overridden;
165 }
166 
167 PollingComponent::PollingComponent(uint32_t update_interval) : Component(), update_interval_(update_interval) {}
168 
170  // Let the polling component subclass setup their HW.
171  this->setup();
172 
173  // Register interval.
174  this->set_interval("update", this->get_update_interval(), [this]() { this->update(); });
175 }
176 
177 uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; }
178 void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
179 
181  : started_(millis()), component_(component) {}
183  uint32_t now = millis();
184  if (now - started_ > 50) {
185  const char *src = component_ == nullptr ? "<null>" : component_->get_component_source();
186  ESP_LOGV(TAG, "Component %s took a long time for an operation (%.2f s).", src, (now - started_) / 1e3f);
187  ESP_LOGV(TAG, "Components should block for at most 20-30ms.");
188  ;
189  }
190 }
191 
192 } // namespace esphome
void setup()
const uint32_t COMPONENT_STATE_LOOP
Definition: component.cpp:33
const uint32_t COMPONENT_STATE_FAILED
Definition: component.cpp:34
void loop()
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:18
virtual void loop()
This method will be called repeatedly.
Definition: component.cpp:48
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:50
const float BEFORE_CONNECTION
For components that should be initialized after WiFi and before API is connected. ...
Definition: component.cpp:23
const float AFTER_CONNECTION
For components that should be initialized after a data connection (API/MQTT) is connected.
Definition: component.cpp:25
virtual float get_loop_priority() const
priority of loop().
Definition: component.cpp:42
bool cancel_timeout(const std::string &name)
Cancel a timeout function.
Definition: component.cpp:62
const float AFTER_WIFI
For components that should be initialized after WiFi is connected.
Definition: component.cpp:24
bool cancel_timeout(Component *component, const std::string &name)
Definition: scheduler.cpp:39
void status_momentary_warning(const std::string &name, uint32_t length=5000)
Definition: component.cpp:137
float get_actual_setup_priority() const
Definition: component.cpp:146
bool cancel_interval(const std::string &name)
Cancel an interval function.
Definition: component.cpp:54
const uint32_t STATUS_LED_OK
Definition: component.cpp:36
void set_setup_priority(float priority)
Definition: component.cpp:151
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
Definition: component.cpp:114
const float LATE
For components that should be initialized at the very end of the setup process.
Definition: component.cpp:26
bool has_overridden_loop() const
Definition: component.cpp:153
bool status_has_warning()
Definition: component.cpp:125
virtual void dump_config()
Definition: component.cpp:145
const float AFTER_BLUETOOTH
Definition: component.cpp:21
virtual void call_dump_config()
Definition: component.cpp:68
void set_interval(Component *component, const std::string &name, uint32_t interval, std::function< void()> &&func)
Definition: scheduler.cpp:42
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:21
void status_momentary_error(const std::string &name, uint32_t length=5000)
Definition: component.cpp:141
uint32_t global_state
Definition: component.cpp:40
virtual void call_setup()
Definition: component.cpp:67
uint32_t get_component_state() const
Definition: component.cpp:70
const float BUS
For communication buses like i2c/spi.
Definition: component.cpp:15
virtual void setup()
Where the component&#39;s initialization should happen.
Definition: component.cpp:46
const uint32_t COMPONENT_STATE_SETUP
Definition: component.cpp:32
virtual float get_setup_priority() const
priority of setup().
Definition: component.cpp:44
void status_clear_warning()
Definition: component.cpp:135
const uint32_t COMPONENT_STATE_CONSTRUCTION
Definition: component.cpp:31
bool cancel_defer(const std::string &name)
Cancel a defer callback using the specified name, name must not be empty.
Definition: component.cpp:111
void set_timeout(uint32_t timeout, std::function< void()> &&f)
Definition: component.cpp:117
virtual void update()=0
const float PROCESSOR
For components that use data from sensors like displays.
Definition: component.cpp:19
const char * get_component_source() const
Get the integration where this component was declared as a string.
Definition: component.cpp:97
Application App
Global storage of Application pointer - only one Application can exist.
virtual bool can_proceed()
Definition: component.cpp:124
void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function< void()> &&func)
Definition: scheduler.cpp:16
WarnIfComponentBlockingGuard(Component *component)
Definition: component.cpp:180
void status_set_warning()
Definition: component.cpp:127
const uint32_t COMPONENT_STATE_MASK
Definition: component.cpp:30
virtual uint32_t get_update_interval() const
Get the update interval in ms of this sensor.
Definition: component.cpp:177
const uint32_t STATUS_LED_WARNING
Definition: component.cpp:37
uint8_t priority
void status_clear_error()
Definition: component.cpp:136
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:17
void call_setup() override
Definition: component.cpp:169
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:102
bool cancel_interval(Component *component, const std::string &name)
Definition: scheduler.cpp:72
const float IO
For components that represent GPIO pins like PCF8573.
Definition: component.cpp:16
const uint32_t STATUS_LED_ERROR
Definition: component.cpp:38
Library based on https://github.com/miguelbalboa/rfid and adapted to ESPHome by . ...
Definition: a4988.cpp:4
virtual void call_loop()
Definition: component.cpp:66
const uint32_t STATUS_LED_MASK
Definition: component.cpp:35
virtual void set_update_interval(uint32_t update_interval)
Manually set the update interval in ms for this polling object.
Definition: component.cpp:178