ESPHome 2025.5.0
Loading...
Searching...
No Matches
application.cpp
Go to the documentation of this file.
2#include "esphome/core/log.h"
4#include "esphome/core/hal.h"
5
6#ifdef USE_STATUS_LED
8#endif
9
10namespace esphome {
11
12static const char *const TAG = "app";
13
15 if (comp == nullptr) {
16 ESP_LOGW(TAG, "Tried to register null component!");
17 return;
18 }
19
20 for (auto *c : this->components_) {
21 if (comp == c) {
22 ESP_LOGW(TAG, "Component %s already registered! (%p)", c->get_component_source(), c);
23 return;
24 }
25 }
26 this->components_.push_back(comp);
27}
29 ESP_LOGI(TAG, "Running through setup()...");
30 ESP_LOGV(TAG, "Sorting components by setup priority...");
31 std::stable_sort(this->components_.begin(), this->components_.end(), [](const Component *a, const Component *b) {
32 return a->get_actual_setup_priority() > b->get_actual_setup_priority();
33 });
34
35 for (uint32_t i = 0; i < this->components_.size(); i++) {
36 Component *component = this->components_[i];
37
38 // Update loop_component_start_time_ before calling each component during setup
40 component->call();
42 this->feed_wdt();
43 if (component->can_proceed())
44 continue;
45
46 std::stable_sort(this->components_.begin(), this->components_.begin() + i + 1,
47 [](Component *a, Component *b) { return a->get_loop_priority() > b->get_loop_priority(); });
48
49 do {
50 uint32_t new_app_state = STATUS_LED_WARNING;
51 this->scheduler.call();
52 this->feed_wdt();
53 for (uint32_t j = 0; j <= i; j++) {
54 // Update loop_component_start_time_ right before calling each component
56 this->components_[j]->call();
57 new_app_state |= this->components_[j]->get_component_state();
58 this->app_state_ |= new_app_state;
59 this->feed_wdt();
60 }
61 this->app_state_ = new_app_state;
62 yield();
63 } while (!component->can_proceed());
64 }
65
66 ESP_LOGI(TAG, "setup() finished successfully!");
69}
71 uint32_t new_app_state = 0;
72
73 this->scheduler.call();
74
75 // Get the initial loop time at the start
76 uint32_t last_op_end_time = millis();
77
78 // Feed WDT with time
79 this->feed_wdt(last_op_end_time);
80
81 for (Component *component : this->looping_components_) {
82 // Update the cached time before each component runs
83 this->loop_component_start_time_ = last_op_end_time;
84
85 {
86 this->set_current_component(component);
87 WarnIfComponentBlockingGuard guard{component, last_op_end_time};
88 component->call();
89 // Use the finish method to get the current time as the end time
90 last_op_end_time = guard.finish();
91 }
92 new_app_state |= component->get_component_state();
93 this->app_state_ |= new_app_state;
94 this->feed_wdt(last_op_end_time);
95 }
96 this->app_state_ = new_app_state;
97
98 // Use the last component's end time instead of calling millis() again
99 auto elapsed = last_op_end_time - this->last_loop_;
101 yield();
102 } else {
103 uint32_t delay_time = this->loop_interval_ - elapsed;
104 uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
105 // next_schedule is max 0.5*delay_time
106 // otherwise interval=0 schedules result in constant looping with almost no sleep
107 next_schedule = std::max(next_schedule, delay_time / 2);
108 delay_time = std::min(next_schedule, delay_time);
109 delay(delay_time);
110 }
111 this->last_loop_ = last_op_end_time;
112
113 if (this->dump_config_at_ < this->components_.size()) {
114 if (this->dump_config_at_ == 0) {
115 ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_);
116#ifdef ESPHOME_PROJECT_NAME
117 ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
118#endif
119 }
120
121 this->components_[this->dump_config_at_]->call_dump_config();
122 this->dump_config_at_++;
123 }
124}
125
126void IRAM_ATTR HOT Application::feed_wdt(uint32_t time) {
127 static uint32_t last_feed = 0;
128 // Use provided time if available, otherwise get current time
129 uint32_t now = time ? time : millis();
130 // Compare in milliseconds (3ms threshold)
131 if (now - last_feed > 3) {
133 last_feed = now;
134#ifdef USE_STATUS_LED
135 if (status_led::global_status_led != nullptr) {
137 }
138#endif
139 }
140}
142 ESP_LOGI(TAG, "Forcing a reboot...");
143 for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
144 (*it)->on_shutdown();
145 }
146 arch_restart();
147}
149 ESP_LOGI(TAG, "Rebooting safely...");
151 arch_restart();
152}
153
155 for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
156 (*it)->on_safe_shutdown();
157 }
158 for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
159 (*it)->on_shutdown();
160 }
161}
162
164 for (auto *obj : this->components_) {
165 if (obj->has_overridden_loop())
166 this->looping_components_.push_back(obj);
167 }
168}
169
170Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
171
172} // namespace esphome
void setup()
Set up all the registered components. Call this at the end of your setup() function.
void set_current_component(Component *component)
std::vector< Component * > components_
uint32_t loop_component_start_time_
const char * compilation_time_
std::vector< Component * > looping_components_
void feed_wdt(uint32_t time=0)
void loop()
Make a loop iteration. Call this in your loop() function.
void calculate_looping_components_()
void register_component_(Component *comp)
virtual bool can_proceed()
static bool is_high_frequency()
Check whether the loop is running continuously.
Definition helpers.cpp:685
optional< uint32_t > next_schedule_in()
value_type value_or(U const &v) const
Definition optional.h:93
const char *const TAG
Definition spi.cpp:8
StatusLED * global_status_led
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
void IRAM_ATTR HOT yield()
Definition core.cpp:26
void IRAM_ATTR HOT arch_feed_wdt()
Definition core.cpp:55
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:28
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
void arch_restart()
Definition core.cpp:31
Application App
Global storage of Application pointer - only one Application can exist.
const uint32_t STATUS_LED_WARNING
Definition component.cpp:39