ESPHome  2023.11.6
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 
85  yield();
86  } else {
87  uint32_t delay_time = this->loop_interval_;
88  if (now - this->last_loop_ < this->loop_interval_)
89  delay_time = this->loop_interval_ - (now - this->last_loop_);
90 
91  uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
92  // next_schedule is max 0.5*delay_time
93  // otherwise interval=0 schedules result in constant looping with almost no sleep
94  next_schedule = std::max(next_schedule, delay_time / 2);
95  delay_time = std::min(next_schedule, delay_time);
96  delay(delay_time);
97  }
98  this->last_loop_ = now;
99 
100  if (this->dump_config_at_ < this->components_.size()) {
101  if (this->dump_config_at_ == 0) {
102  ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_);
103 #ifdef ESPHOME_PROJECT_NAME
104  ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
105 #endif
106  }
107 
108  this->components_[this->dump_config_at_]->call_dump_config();
109  this->dump_config_at_++;
110  }
111 }
112 
113 void IRAM_ATTR HOT Application::feed_wdt() {
114  static uint32_t last_feed = 0;
115  uint32_t now = micros();
116  if (now - last_feed > 3000) {
117  arch_feed_wdt();
118  last_feed = now;
119 #ifdef USE_STATUS_LED
120  if (status_led::global_status_led != nullptr) {
122  }
123 #endif
124  }
125 }
127  ESP_LOGI(TAG, "Forcing a reboot...");
128  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
129  (*it)->on_shutdown();
130  }
131  arch_restart();
132 }
134  ESP_LOGI(TAG, "Rebooting safely...");
136  arch_restart();
137 }
138 
140  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
141  (*it)->on_safe_shutdown();
142  }
143  for (auto it = this->components_.rbegin(); it != this->components_.rend(); ++it) {
144  (*it)->on_shutdown();
145  }
146 }
147 
149  for (auto *obj : this->components_) {
150  if (obj->has_overridden_loop())
151  this->looping_components_.push_back(obj);
152  }
153 }
154 
155 Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
156 
157 } // namespace esphome
static bool is_high_frequency()
Check whether the loop is running continuously.
Definition: helpers.cpp:548
void IRAM_ATTR HOT arch_feed_wdt()
Definition: core.cpp:53
float get_actual_setup_priority() const
Definition: component.cpp:164
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:142
std::vector< Component * > components_
Definition: application.h:352
void arch_restart()
Definition: core.cpp:29
std::vector< Component * > looping_components_
Definition: application.h:353
const uint32_t STATUS_LED_WARNING
Definition: component.cpp:38
StatusLED * global_status_led
Definition: status_led.cpp:10
const char * compilation_time_
Definition: application.h:405
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