ESPHome  2024.11.0
application.cpp
Go to the documentation of this file.
2 #include "esphome/core/log.h"
3 #include "esphome/core/version.h"
4 #include "esphome/core/hal.h"
5 
6 #ifdef USE_STATUS_LED
8 #endif
9 
10 namespace esphome {
11 
12 static 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  component->call();
39  this->scheduler.process_to_add();
40  this->feed_wdt();
41  if (component->can_proceed())
42  continue;
43 
44  std::stable_sort(this->components_.begin(), this->components_.begin() + i + 1,
45  [](Component *a, Component *b) { return a->get_loop_priority() > b->get_loop_priority(); });
46 
47  do {
48  uint32_t new_app_state = STATUS_LED_WARNING;
49  this->scheduler.call();
50  this->feed_wdt();
51  for (uint32_t j = 0; j <= i; j++) {
52  this->components_[j]->call();
53  new_app_state |= this->components_[j]->get_component_state();
54  this->app_state_ |= new_app_state;
55  this->feed_wdt();
56  }
57  this->app_state_ = new_app_state;
58  yield();
59  } while (!component->can_proceed());
60  }
61 
62  ESP_LOGI(TAG, "setup() finished successfully!");
63  this->schedule_dump_config();
65 }
67  uint32_t new_app_state = 0;
68 
69  this->scheduler.call();
70  this->feed_wdt();
71  for (Component *component : this->looping_components_) {
72  {
73  WarnIfComponentBlockingGuard guard{component};
74  component->call();
75  }
76  new_app_state |= component->get_component_state();
77  this->app_state_ |= new_app_state;
78  this->feed_wdt();
79  }
80  this->app_state_ = new_app_state;
81 
82  const uint32_t now = millis();
83 
84  auto elapsed = now - this->last_loop_;
86  yield();
87  } else {
88  uint32_t delay_time = this->loop_interval_ - elapsed;
89  uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
90  // next_schedule is max 0.5*delay_time
91  // otherwise interval=0 schedules result in constant looping with almost no sleep
92  next_schedule = std::max(next_schedule, delay_time / 2);
93  delay_time = std::min(next_schedule, delay_time);
94  delay(delay_time);
95  }
96  this->last_loop_ = now;
97 
98  if (this->dump_config_at_ < this->components_.size()) {
99  if (this->dump_config_at_ == 0) {
100  ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_);
101 #ifdef ESPHOME_PROJECT_NAME
102  ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
103 #endif
104  }
105 
106  this->components_[this->dump_config_at_]->call_dump_config();
107  this->dump_config_at_++;
108  }
109 }
110 
111 void IRAM_ATTR HOT Application::feed_wdt() {
112  static uint32_t last_feed = 0;
113  uint32_t now = micros();
114  if (now - last_feed > 3000) {
115  arch_feed_wdt();
116  last_feed = now;
117 #ifdef USE_STATUS_LED
118  if (status_led::global_status_led != nullptr) {
120  }
121 #endif
122  }
123 }
125  ESP_LOGI(TAG, "Forcing a reboot...");
126  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
127  (*it)->on_shutdown();
128  }
129  arch_restart();
130 }
132  ESP_LOGI(TAG, "Rebooting safely...");
134  arch_restart();
135 }
136 
138  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
139  (*it)->on_safe_shutdown();
140  }
141  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
142  (*it)->on_shutdown();
143  }
144 }
145 
147  for (auto *obj : this->components_) {
148  if (obj->has_overridden_loop())
149  this->looping_components_.push_back(obj);
150  }
151 }
152 
153 Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
154 
155 } // namespace esphome
static bool is_high_frequency()
Check whether the loop is running continuously.
Definition: helpers.cpp:665
void IRAM_ATTR HOT arch_feed_wdt()
Definition: core.cpp:53
float get_actual_setup_priority() const
Definition: component.cpp:187
void setup()
Set up all the registered components. Call this at the end of your setup() function.
Definition: application.cpp:28
uint32_t IRAM_ATTR HOT micros()
Definition: core.cpp:27
optional< uint32_t > next_schedule_in()
Definition: scheduler.cpp:137
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:25
const char *const TAG
Definition: spi.cpp:8
void loop()
Make a loop iteration. Call this in your loop() function.
Definition: application.cpp:66
void calculate_looping_components_()
Application App
Global storage of Application pointer - only one Application can exist.
virtual bool can_proceed()
Definition: component.cpp:148
std::vector< Component * > components_
Definition: application.h:473
void arch_restart()
Definition: core.cpp:29
std::vector< Component * > looping_components_
Definition: application.h:474
const uint32_t STATUS_LED_WARNING
Definition: component.cpp:39
StatusLED * global_status_led
Definition: status_led.cpp:10
const char * compilation_time_
Definition: application.h:544
void IRAM_ATTR HOT yield()
Definition: core.cpp:24
void register_component_(Component *comp)
Definition: application.cpp:14
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
value_type value_or(U const &v) const
Definition: optional.h:93
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26