ESPHome  2021.11.4
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  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  this->feed_wdt();
57  } while (!component->can_proceed());
58  }
59 
60  ESP_LOGI(TAG, "setup() finished successfully!");
61  this->schedule_dump_config();
63 }
65  uint32_t new_app_state = 0;
66 
67  this->scheduler.call();
68  for (Component *component : this->looping_components_) {
69  {
70  WarnIfComponentBlockingGuard guard{component};
71  component->call();
72  }
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 now = millis();
80 
82  yield();
83  } else {
84  uint32_t delay_time = this->loop_interval_;
85  if (now - this->last_loop_ < this->loop_interval_)
86  delay_time = this->loop_interval_ - (now - this->last_loop_);
87 
88  uint32_t next_schedule = this->scheduler.next_schedule_in().value_or(delay_time);
89  // next_schedule is max 0.5*delay_time
90  // otherwise interval=0 schedules result in constant looping with almost no sleep
91  next_schedule = std::max(next_schedule, delay_time / 2);
92  delay_time = std::min(next_schedule, delay_time);
93  delay(delay_time);
94  }
95  this->last_loop_ = now;
96 
97  if (this->dump_config_at_ >= 0 && this->dump_config_at_ < this->components_.size()) {
98  if (this->dump_config_at_ == 0) {
99  ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", this->compilation_time_.c_str());
100 #ifdef ESPHOME_PROJECT_NAME
101  ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION);
102 #endif
103  }
104 
105  this->components_[this->dump_config_at_]->call_dump_config();
106  this->dump_config_at_++;
107  }
108 }
109 
110 void IRAM_ATTR HOT Application::feed_wdt() {
111  static uint32_t last_feed = 0;
112  uint32_t now = micros();
113  if (now - last_feed > 3000) {
114  arch_feed_wdt();
115  last_feed = now;
116 #ifdef USE_STATUS_LED
117  if (status_led::global_status_led != nullptr) {
119  }
120 #endif
121  }
122 }
124  ESP_LOGI(TAG, "Forcing a reboot...");
125  for (auto *comp : this->components_)
126  comp->on_shutdown();
127  arch_restart();
128 }
130  ESP_LOGI(TAG, "Rebooting safely...");
131  for (auto *comp : this->components_)
132  comp->on_safe_shutdown();
133  for (auto *comp : this->components_)
134  comp->on_shutdown();
135  arch_restart();
136 }
137 
139  for (auto *obj : this->components_) {
140  if (obj->has_overridden_loop())
141  this->looping_components_.push_back(obj);
142  }
143 }
144 
145 Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
146 
147 } // namespace esphome
std::string compilation_time_
Definition: application.h:289
void IRAM_ATTR HOT arch_feed_wdt()
Definition: core.cpp:32
float get_actual_setup_priority() const
Definition: component.cpp:146
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:23
optional< uint32_t > next_schedule_in()
Definition: scheduler.cpp:75
uint32_t IRAM_ATTR HOT millis()
Definition: core.cpp:21
void loop()
Make a loop iteration. Call this in your loop() function.
Definition: application.cpp:64
void calculate_looping_components_()
Application App
Global storage of Application pointer - only one Application can exist.
virtual bool can_proceed()
Definition: component.cpp:124
std::vector< Component * > components_
Definition: application.h:254
void arch_restart()
Definition: core.cpp:25
std::vector< Component * > looping_components_
Definition: application.h:255
const uint32_t STATUS_LED_WARNING
Definition: component.cpp:37
StatusLED * global_status_led
Definition: status_led.cpp:10
void IRAM_ATTR HOT yield()
Definition: core.cpp:20
void register_component_(Component *comp)
Definition: application.cpp:14
Library based on https://github.com/miguelbalboa/rfid and adapted to ESPHome by . ...
Definition: a4988.cpp:4
value_type value_or(U const &v) const
Definition: optional.h:93
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:22