mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Reduce number of calls to fetch time in the main loop (#8804)
This commit is contained in:
		
				
					committed by
					
						 Jesse Hills
						Jesse Hills
					
				
			
			
				
	
			
			
			
						parent
						
							316fe2f06c
						
					
				
				
					commit
					15d0b4355e
				
			| @@ -8,6 +8,7 @@ | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/version.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| #ifdef USE_DEEP_SLEEP | ||||
| #include "esphome/components/deep_sleep/deep_sleep_component.h" | ||||
| @@ -146,7 +147,7 @@ void APIConnection::loop() { | ||||
|     } | ||||
|     return; | ||||
|   } else { | ||||
|     this->last_traffic_ = millis(); | ||||
|     this->last_traffic_ = App.get_loop_component_start_time(); | ||||
|     // read a packet | ||||
|     this->read_message(buffer.data_len, buffer.type, &buffer.container[buffer.data_offset]); | ||||
|     if (this->remove_) | ||||
| @@ -163,7 +164,7 @@ void APIConnection::loop() { | ||||
|   static uint32_t keepalive = 60000; | ||||
|   static uint8_t max_ping_retries = 60; | ||||
|   static uint16_t ping_retry_interval = 1000; | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (this->sent_ping_) { | ||||
|     // Disconnect if not responded within 2.5*keepalive | ||||
|     if (now - this->last_traffic_ > (keepalive * 5) / 2) { | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "bedjet_hub.h" | ||||
| #include "bedjet_child.h" | ||||
| #include "bedjet_const.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include <cinttypes> | ||||
|  | ||||
| namespace esphome { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/macros.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| #ifdef USE_ESP32 | ||||
|  | ||||
| @@ -177,7 +178,7 @@ void BluetoothProxy::loop() { | ||||
|   // Flush any pending BLE advertisements that have been accumulated but not yet sent | ||||
|   if (this->raw_advertisements_) { | ||||
|     static uint32_t last_flush_time = 0; | ||||
|     uint32_t now = millis(); | ||||
|     uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|     // Flush accumulated advertisements every 100ms | ||||
|     if (now - last_flush_time >= 100) { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "cse7766.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace cse7766 { | ||||
| @@ -7,7 +8,7 @@ namespace cse7766 { | ||||
| static const char *const TAG = "cse7766"; | ||||
|  | ||||
| void CSE7766Component::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_transmission_ >= 500) { | ||||
|     // last transmission too long ago. Reset RX index. | ||||
|     this->raw_data_index_ = 0; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "current_based_cover.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include <cfloat> | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -60,7 +61,7 @@ void CurrentBasedCover::loop() { | ||||
|   if (this->current_operation == COVER_OPERATION_IDLE) | ||||
|     return; | ||||
|  | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   if (this->current_operation == COVER_OPERATION_OPENING) { | ||||
|     if (this->malfunction_detection_ && this->is_closing_()) {  // Malfunction | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "daly_bms.h" | ||||
| #include <vector> | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace daly_bms { | ||||
| @@ -32,7 +33,7 @@ void DalyBmsComponent::update() { | ||||
| } | ||||
|  | ||||
| void DalyBmsComponent::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (this->receiving_ && (now - this->last_transmission_ >= 200)) { | ||||
|     // last transmission too long ago. Reset RX index. | ||||
|     ESP_LOGW(TAG, "Last transmission too long ago. Reset RX index."); | ||||
|   | ||||
| @@ -70,7 +70,7 @@ void DebugComponent::loop() { | ||||
| #ifdef USE_SENSOR | ||||
|   // calculate loop time - from last call to this one | ||||
|   if (this->loop_time_sensor_ != nullptr) { | ||||
|     uint32_t now = millis(); | ||||
|     uint32_t now = App.get_loop_component_start_time(); | ||||
|     uint32_t loop_time = now - this->last_loop_timetag_; | ||||
|     this->max_loop_time_ = std::max(this->max_loop_time_, loop_time); | ||||
|     this->last_loop_timetag_ = now; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "endstop_cover.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace endstop { | ||||
| @@ -65,7 +66,7 @@ void EndstopCover::loop() { | ||||
|   if (this->current_operation == COVER_OPERATION_IDLE) | ||||
|     return; | ||||
|  | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   if (this->current_operation == COVER_OPERATION_OPENING && this->is_open_()) { | ||||
|     float dur = (now - this->start_dir_time_) / 1e3f; | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include <cstring> | ||||
| #include "ble_uuid.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace esp32_ble { | ||||
| @@ -143,7 +144,7 @@ void BLEAdvertising::loop() { | ||||
|   if (this->raw_advertisements_callbacks_.empty()) { | ||||
|     return; | ||||
|   } | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_advertisement_time_ > this->advertising_cycle_time_) { | ||||
|     this->stop(); | ||||
|     this->current_adv_index_ += 1; | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "esp32_camera.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| #include <freertos/task.h> | ||||
|  | ||||
| @@ -162,7 +163,7 @@ void ESP32Camera::loop() { | ||||
|   } | ||||
|  | ||||
|   // request idle image every idle_update_interval | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (this->idle_update_interval_ != 0 && now - this->last_idle_request_ > this->idle_update_interval_) { | ||||
|     this->last_idle_request_ = now; | ||||
|     this->request_image(IDLE); | ||||
|   | ||||
| @@ -92,7 +92,7 @@ void ESP32ImprovComponent::loop() { | ||||
|  | ||||
|   if (!this->incoming_data_.empty()) | ||||
|     this->process_incoming_data_(); | ||||
|   uint32_t now = millis(); | ||||
|   uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   switch (this->state_) { | ||||
|     case improv::STATE_STOPPED: | ||||
|   | ||||
| @@ -288,7 +288,7 @@ uint32_t ESP32TouchComponent::component_touch_pad_read(touch_pad_t tp) { | ||||
| } | ||||
|  | ||||
| void ESP32TouchComponent::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250; | ||||
|   for (auto *child : this->children_) { | ||||
|     child->value_ = this->component_touch_pad_read(child->get_touch_pad()); | ||||
|   | ||||
| @@ -240,7 +240,7 @@ void EthernetComponent::setup() { | ||||
| } | ||||
|  | ||||
| void EthernetComponent::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   switch (this->state_) { | ||||
|     case EthernetComponentState::STOPPED: | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "feedback_cover.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace feedback { | ||||
| @@ -220,7 +221,7 @@ void FeedbackCover::set_open_obstacle_sensor(binary_sensor::BinarySensor *open_o | ||||
| void FeedbackCover::loop() { | ||||
|   if (this->current_operation == COVER_OPERATION_IDLE) | ||||
|     return; | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   // Recompute position every loop cycle | ||||
|   this->recompute_position_(); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  */ | ||||
| #include "gcja5.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include <cstring> | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -16,7 +17,7 @@ static const char *const TAG = "gcja5"; | ||||
| void GCJA5Component::setup() { ESP_LOGCONFIG(TAG, "Setting up gcja5..."); } | ||||
|  | ||||
| void GCJA5Component::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_transmission_ >= 500) { | ||||
|     // last transmission too long ago. Reset RX index. | ||||
|     this->rx_message_.clear(); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "growatt_solar.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace growatt_solar { | ||||
| @@ -18,7 +19,7 @@ void GrowattSolar::loop() { | ||||
|  | ||||
| void GrowattSolar::update() { | ||||
|   // If our last send has had no reply yet, and it wasn't that long ago, do nothing. | ||||
|   uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_send_ < this->get_update_interval() / 2) { | ||||
|     return; | ||||
|   } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "kuntze.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace kuntze { | ||||
| @@ -60,7 +61,7 @@ void Kuntze::on_modbus_data(const std::vector<uint8_t> &data) { | ||||
| } | ||||
|  | ||||
| void Kuntze::loop() { | ||||
|   uint32_t now = millis(); | ||||
|   uint32_t now = App.get_loop_component_start_time(); | ||||
|   // timeout after 15 seconds | ||||
|   if (this->waiting_ && (now - this->last_send_ > 15000)) { | ||||
|     ESP_LOGW(TAG, "timed out waiting for response"); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "matrix_keypad.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace matrix_keypad { | ||||
| @@ -28,7 +29,7 @@ void MatrixKeypad::setup() { | ||||
| void MatrixKeypad::loop() { | ||||
|   static uint32_t active_start = 0; | ||||
|   static int active_key = -1; | ||||
|   uint32_t now = millis(); | ||||
|   uint32_t now = App.get_loop_component_start_time(); | ||||
|   int key = -1; | ||||
|   bool error = false; | ||||
|   int pos = 0, row, col; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include "max7219font.h" | ||||
|  | ||||
| #include <algorithm> | ||||
| @@ -63,7 +64,7 @@ void MAX7219Component::dump_config() { | ||||
| } | ||||
|  | ||||
| void MAX7219Component::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   const uint32_t millis_since_last_scroll = now - this->last_scroll_; | ||||
|   const size_t first_line_size = this->max_displaybuffer_[0].size(); | ||||
|   // check if the buffer has shrunk past the current position since last update | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "modbus.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace modbus { | ||||
| @@ -13,7 +14,7 @@ void Modbus::setup() { | ||||
|   } | ||||
| } | ||||
| void Modbus::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   while (this->available()) { | ||||
|     uint8_t byte; | ||||
|   | ||||
| @@ -345,7 +345,7 @@ void MQTTClientComponent::loop() { | ||||
|     this->disconnect_reason_.reset(); | ||||
|   } | ||||
|  | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   switch (this->state_) { | ||||
|     case MQTT_CLIENT_DISABLED: | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "pmsx003.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace pmsx003 { | ||||
| @@ -42,7 +43,7 @@ void PMSX003Component::dump_config() { | ||||
| } | ||||
|  | ||||
| void PMSX003Component::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   // If we update less often than it takes the device to stabilise, spin the fan down | ||||
|   // rather than running it constantly. It does take some time to stabilise, so we | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "pzem004t.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include <cinttypes> | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -16,7 +17,7 @@ void PZEM004T::setup() { | ||||
| } | ||||
|  | ||||
| void PZEM004T::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_read_ > 500 && this->available() < 7) { | ||||
|     while (this->available()) | ||||
|       this->read(); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "rf_bridge.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
| #include <cinttypes> | ||||
| #include <cstring> | ||||
|  | ||||
| @@ -128,7 +129,7 @@ void RFBridgeComponent::write_byte_str_(const std::string &codes) { | ||||
| } | ||||
|  | ||||
| void RFBridgeComponent::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now - this->last_bridge_byte_ > 50) { | ||||
|     this->rx_buffer_.clear(); | ||||
|     this->last_bridge_byte_ = now; | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "sds011.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace sds011 { | ||||
| @@ -75,7 +76,7 @@ void SDS011Component::dump_config() { | ||||
| } | ||||
|  | ||||
| void SDS011Component::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|   if ((now - this->last_transmission_ >= 500) && this->data_index_) { | ||||
|     // last transmission too long ago. Reset RX index. | ||||
|     ESP_LOGV(TAG, "Last transmission too long ago. Reset RX index."); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "slow_pwm_output.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace slow_pwm { | ||||
| @@ -39,7 +40,7 @@ void SlowPWMOutput::set_output_state_(bool new_state) { | ||||
| } | ||||
|  | ||||
| void SlowPWMOutput::loop() { | ||||
|   uint32_t now = millis(); | ||||
|   uint32_t now = App.get_loop_component_start_time(); | ||||
|   float scaled_state = this->state_ * this->period_; | ||||
|  | ||||
|   if (now - this->period_start_time_ >= this->period_) { | ||||
|   | ||||
| @@ -20,7 +20,7 @@ SprinklerSwitch::SprinklerSwitch(switch_::Switch *off_switch, switch_::Switch *o | ||||
| bool SprinklerSwitch::is_latching_valve() { return (this->off_switch_ != nullptr) && (this->on_switch_ != nullptr); } | ||||
|  | ||||
| void SprinklerSwitch::loop() { | ||||
|   if ((this->pinned_millis_) && (millis() > this->pinned_millis_ + this->pulse_duration_)) { | ||||
|   if ((this->pinned_millis_) && (App.get_loop_component_start_time() > this->pinned_millis_ + this->pulse_duration_)) { | ||||
|     this->pinned_millis_ = 0;  // reset tracker | ||||
|     if (this->off_switch_->state) { | ||||
|       this->off_switch_->turn_off(); | ||||
| @@ -148,22 +148,23 @@ SprinklerValveOperator::SprinklerValveOperator(SprinklerValve *valve, Sprinkler | ||||
|     : controller_(controller), valve_(valve) {} | ||||
|  | ||||
| void SprinklerValveOperator::loop() { | ||||
|   if (millis() >= this->start_millis_) {  // dummy check | ||||
|   uint32_t now = App.get_loop_component_start_time(); | ||||
|   if (now >= this->start_millis_) {  // dummy check | ||||
|     switch (this->state_) { | ||||
|       case STARTING: | ||||
|         if (millis() > (this->start_millis_ + this->start_delay_)) { | ||||
|         if (now > (this->start_millis_ + this->start_delay_)) { | ||||
|           this->run_();  // start_delay_ has been exceeded, so ensure both valves are on and update the state | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case ACTIVE: | ||||
|         if (millis() > (this->start_millis_ + this->start_delay_ + this->run_duration_)) { | ||||
|         if (now > (this->start_millis_ + this->start_delay_ + this->run_duration_)) { | ||||
|           this->stop();  // start_delay_ + run_duration_ has been exceeded, start shutting down | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|       case STOPPING: | ||||
|         if (millis() > (this->stop_millis_ + this->stop_delay_)) { | ||||
|         if (now > (this->stop_millis_ + this->stop_delay_)) { | ||||
|           this->kill_();  // stop_delay_has been exceeded, ensure all valves are off | ||||
|         } | ||||
|         break; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "time_based_cover.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/hal.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace time_based { | ||||
| @@ -26,7 +27,7 @@ void TimeBasedCover::loop() { | ||||
|   if (this->current_operation == COVER_OPERATION_IDLE) | ||||
|     return; | ||||
|  | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   // Recompute position every loop cycle | ||||
|   this->recompute_position_(); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "uart_switch.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uart { | ||||
| @@ -8,7 +9,7 @@ static const char *const TAG = "uart.switch"; | ||||
|  | ||||
| void UARTSwitch::loop() { | ||||
|   if (this->send_every_) { | ||||
|     const uint32_t now = millis(); | ||||
|     const uint32_t now = App.get_loop_component_start_time(); | ||||
|     if (now - this->last_transmission_ > this->send_every_) { | ||||
|       this->write_command_(this->state); | ||||
|       this->last_transmission_ = now; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #include "uponor_smatrix_climate.h" | ||||
| #include "esphome/core/helpers.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uponor_smatrix { | ||||
| @@ -13,7 +14,7 @@ void UponorSmatrixClimate::dump_config() { | ||||
| } | ||||
|  | ||||
| void UponorSmatrixClimate::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   // Publish state after all update packets are processed | ||||
|   if (this->last_data_ != 0 && (now - this->last_data_ > 100) && this->target_temperature_raw_ != 0) { | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| #include "uponor_smatrix.h" | ||||
| #include "esphome/core/log.h" | ||||
| #include "esphome/core/application.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace uponor_smatrix { | ||||
| @@ -35,7 +36,7 @@ void UponorSmatrixComponent::dump_config() { | ||||
| } | ||||
|  | ||||
| void UponorSmatrixComponent::loop() { | ||||
|   const uint32_t now = millis(); | ||||
|   const uint32_t now = App.get_loop_component_start_time(); | ||||
|  | ||||
|   // Discard stale data | ||||
|   if (!this->rx_buffer_.empty() && (now - this->last_rx_ > 50)) { | ||||
|   | ||||
| @@ -67,22 +67,32 @@ void Application::loop() { | ||||
|   uint32_t new_app_state = 0; | ||||
|  | ||||
|   this->scheduler.call(); | ||||
|   this->feed_wdt(); | ||||
|  | ||||
|   // Get the initial loop time at the start | ||||
|   uint32_t last_op_end_time = millis(); | ||||
|  | ||||
|   // Feed WDT with time | ||||
|   this->feed_wdt(last_op_end_time); | ||||
|  | ||||
|   for (Component *component : this->looping_components_) { | ||||
|     // Update the cached time before each component runs | ||||
|     this->loop_component_start_time_ = last_op_end_time; | ||||
|  | ||||
|     { | ||||
|       this->set_current_component(component); | ||||
|       WarnIfComponentBlockingGuard guard{component}; | ||||
|       WarnIfComponentBlockingGuard guard{component, last_op_end_time}; | ||||
|       component->call(); | ||||
|       // Use the finish method to get the current time as the end time | ||||
|       last_op_end_time = guard.finish(); | ||||
|     } | ||||
|     new_app_state |= component->get_component_state(); | ||||
|     this->app_state_ |= new_app_state; | ||||
|     this->feed_wdt(); | ||||
|     this->feed_wdt(last_op_end_time); | ||||
|   } | ||||
|   this->app_state_ = new_app_state; | ||||
|  | ||||
|   const uint32_t now = millis(); | ||||
|  | ||||
|   auto elapsed = now - this->last_loop_; | ||||
|   // Use the last component's end time instead of calling millis() again | ||||
|   auto elapsed = last_op_end_time - this->last_loop_; | ||||
|   if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) { | ||||
|     yield(); | ||||
|   } else { | ||||
| @@ -94,7 +104,7 @@ void Application::loop() { | ||||
|     delay_time = std::min(next_schedule, delay_time); | ||||
|     delay(delay_time); | ||||
|   } | ||||
|   this->last_loop_ = now; | ||||
|   this->last_loop_ = last_op_end_time; | ||||
|  | ||||
|   if (this->dump_config_at_ < this->components_.size()) { | ||||
|     if (this->dump_config_at_ == 0) { | ||||
| @@ -109,10 +119,12 @@ void Application::loop() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void IRAM_ATTR HOT Application::feed_wdt() { | ||||
| void IRAM_ATTR HOT Application::feed_wdt(uint32_t time) { | ||||
|   static uint32_t last_feed = 0; | ||||
|   uint32_t now = micros(); | ||||
|   if (now - last_feed > 3000) { | ||||
|   // Use provided time if available, otherwise get current time | ||||
|   uint32_t now = time ? time : millis(); | ||||
|   // Compare in milliseconds (3ms threshold) | ||||
|   if (now - last_feed > 3) { | ||||
|     arch_feed_wdt(); | ||||
|     last_feed = now; | ||||
| #ifdef USE_STATUS_LED | ||||
|   | ||||
| @@ -217,6 +217,9 @@ class Application { | ||||
|  | ||||
|   std::string get_compilation_time() const { return this->compilation_time_; } | ||||
|  | ||||
|   /// Get the cached time in milliseconds from when the current component started its loop execution | ||||
|   inline uint32_t IRAM_ATTR HOT get_loop_component_start_time() const { return this->loop_component_start_time_; } | ||||
|  | ||||
|   /** Set the target interval with which to run the loop() calls. | ||||
|    * If the loop() method takes longer than the target interval, ESPHome won't | ||||
|    * sleep in loop(), but if the time spent in loop() is small than the target, ESPHome | ||||
| @@ -236,7 +239,7 @@ class Application { | ||||
|  | ||||
|   void schedule_dump_config() { this->dump_config_at_ = 0; } | ||||
|  | ||||
|   void feed_wdt(); | ||||
|   void feed_wdt(uint32_t time = 0); | ||||
|  | ||||
|   void reboot(); | ||||
|  | ||||
| @@ -551,6 +554,7 @@ class Application { | ||||
|   size_t dump_config_at_{SIZE_MAX}; | ||||
|   uint32_t app_state_{0}; | ||||
|   Component *current_component_{nullptr}; | ||||
|   uint32_t loop_component_start_time_{0}; | ||||
| }; | ||||
|  | ||||
| /// Global storage of Application pointer - only one Application can exist. | ||||
|   | ||||
| @@ -240,10 +240,12 @@ void PollingComponent::stop_poller() { | ||||
| uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } | ||||
| void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } | ||||
|  | ||||
| WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component) | ||||
|     : started_(millis()), component_(component) {} | ||||
| WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() { | ||||
|   uint32_t blocking_time = millis() - this->started_; | ||||
| WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component, uint32_t start_time) | ||||
|     : started_(start_time), component_(component) {} | ||||
| uint32_t WarnIfComponentBlockingGuard::finish() { | ||||
|   uint32_t curr_time = millis(); | ||||
|  | ||||
|   uint32_t blocking_time = curr_time - this->started_; | ||||
|   bool should_warn; | ||||
|   if (this->component_ != nullptr) { | ||||
|     should_warn = this->component_->should_warn_of_blocking(blocking_time); | ||||
| @@ -254,8 +256,11 @@ WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() { | ||||
|     const char *src = component_ == nullptr ? "<null>" : component_->get_component_source(); | ||||
|     ESP_LOGW(TAG, "Component %s took a long time for an operation (%" PRIu32 " ms).", src, blocking_time); | ||||
|     ESP_LOGW(TAG, "Components should block for at most 30 ms."); | ||||
|     ; | ||||
|   } | ||||
|   } | ||||
|  | ||||
|   return curr_time; | ||||
| } | ||||
|  | ||||
| WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {} | ||||
|  | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -339,7 +339,11 @@ class PollingComponent : public Component { | ||||
|  | ||||
| class WarnIfComponentBlockingGuard { | ||||
|  public: | ||||
|   WarnIfComponentBlockingGuard(Component *component); | ||||
|   WarnIfComponentBlockingGuard(Component *component, uint32_t start_time); | ||||
|  | ||||
|   // Finish the timing operation and return the current time | ||||
|   uint32_t finish(); | ||||
|  | ||||
|   ~WarnIfComponentBlockingGuard(); | ||||
|  | ||||
|  protected: | ||||
|   | ||||
| @@ -229,8 +229,11 @@ void HOT Scheduler::call() { | ||||
|       //  - timeouts/intervals get added, potentially invalidating vector pointers | ||||
|       //  - timeouts/intervals get cancelled | ||||
|       { | ||||
|         WarnIfComponentBlockingGuard guard{item->component}; | ||||
|         uint32_t now_ms = millis(); | ||||
|         WarnIfComponentBlockingGuard guard{item->component, now_ms}; | ||||
|         item->callback(); | ||||
|         // Call finish to ensure blocking time is properly calculated and reported | ||||
|         guard.finish(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user