ESPHome  1.15.1
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/esphal.h"
5 
6 #ifdef USE_STATUS_LED
8 #endif
9 
10 namespace esphome {
11 
12 static const char *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 already registered! (%p)", 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  if (component->can_proceed())
41  continue;
42 
43  std::stable_sort(this->components_.begin(), this->components_.begin() + i + 1,
44  [](Component *a, Component *b) { return a->get_loop_priority() > b->get_loop_priority(); });
45 
46  do {
47  uint32_t new_app_state = STATUS_LED_WARNING;
48  this->scheduler.call();
49  for (uint32_t j = 0; j <= i; j++) {
50  this->components_[j]->call();
51  new_app_state |= this->components_[j]->get_component_state();
52  this->app_state_ |= new_app_state;
53  }
54  this->app_state_ = new_app_state;
55  yield();
56  } while (!component->can_proceed());
57  }
58 
59  ESP_LOGI(TAG, "setup() finished successfully!");
60  this->schedule_dump_config();
62 
63  // Dummy function to link some symbols into the binary.
65 }
67  uint32_t new_app_state = 0;
68  const uint32_t start = millis();
69 
70  this->scheduler.call();
71  for (Component *component : this->looping_components_) {
72  component->call();
73  new_app_state |= component->get_component_state();
74  this->app_state_ |= new_app_state;
75  this->feed_wdt();
76  }
77  this->app_state_ = new_app_state;
78 
79  const uint32_t end = millis();
80  if (end - start > 200) {
81  ESP_LOGV(TAG, "A component took a long time in a loop() cycle (%.2f s).", (end - start) / 1e3f);
82  ESP_LOGV(TAG, "Components should block for at most 20-30ms in loop().");
83  }
84 
85  const uint32_t now = millis();
86 
88  yield();
89  } else {
90  uint32_t delay_time = this->loop_interval_;
91  if (now - this->last_loop_ < this->loop_interval_)
92  delay_time = this->loop_interval_ - (now - this->last_loop_);
93 
94  uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
95  // next_schedule is max 0.5*delay_time
96  // otherwise interval=0 schedules result in constant looping with almost no sleep
97  next_schedule = std::max(next_schedule, delay_time / 2);
98  delay_time = std::min(next_schedule, delay_time);
99  delay(delay_time);
100  }
101  this->last_loop_ = now;
102 
103  if (this->dump_config_at_ >= 0 && this->dump_config_at_ < this->components_.size()) {
104  if (this->dump_config_at_ == 0) {
105  ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_.c_str());
106  }
107 
108  this->components_[this->dump_config_at_]->dump_config();
109  this->dump_config_at_++;
110  }
111 }
112 
113 void ICACHE_RAM_ATTR HOT Application::feed_wdt() {
114  static uint32_t LAST_FEED = 0;
115  uint32_t now = millis();
116  if (now - LAST_FEED > 3) {
117 #ifdef ARDUINO_ARCH_ESP8266
118  ESP.wdtFeed();
119 #endif
120 #ifdef ARDUINO_ARCH_ESP32
121  yield();
122 #endif
123  LAST_FEED = now;
124 #ifdef USE_STATUS_LED
125  if (status_led::global_status_led != nullptr) {
127  }
128 #endif
129  }
130 }
132  ESP_LOGI(TAG, "Forcing a reboot...");
133  for (auto *comp : this->components_)
134  comp->on_shutdown();
135  ESP.restart();
136  // restart() doesn't always end execution
137  while (true) {
138  yield();
139  }
140 }
142  ESP_LOGI(TAG, "Rebooting safely...");
143  for (auto *comp : this->components_)
144  comp->on_safe_shutdown();
145  for (auto *comp : this->components_)
146  comp->on_shutdown();
147  ESP.restart();
148  // restart() doesn't always end execution
149  while (true) {
150  yield();
151  }
152 }
153 
155  for (auto *obj : this->components_) {
156  if (obj->has_overridden_loop())
157  this->looping_components_.push_back(obj);
158  }
159 }
160 
162 
163 } // namespace esphome
std::string compilation_time_
Definition: application.h:243
const char * TAG
Definition: tm1637.cpp:8
float get_actual_setup_priority() const
Definition: component.cpp:135
void setup()
Set up all the registered components. Call this at the end of your setup() function.
Definition: application.cpp:28
optional< uint32_t > next_schedule_in()
Definition: scheduler.cpp:74
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:113
std::vector< Component * > components_
Definition: application.h:214
void force_link_symbols()
This function can be used by the HAL to force-link specific symbols into the generated binary without...
Definition: esphal.cpp:274
std::vector< Component * > looping_components_
Definition: application.h:215
const uint32_t STATUS_LED_WARNING
Definition: component.cpp:32
StatusLED * global_status_led
Definition: status_led.cpp:10
void register_component_(Component *comp)
Definition: application.cpp:14
Definition: a4988.cpp:4
value_type value_or(U const &v) const
Definition: optional.h:91