From aed7ef481e045f1f268a309ff902976bbea0d333 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 May 2025 23:22:36 -0400 Subject: [PATCH] Fix API connection sending ping too early after connection establishment (#8840) --- esphome/components/api/api_connection.cpp | 11 +++++++---- esphome/components/api/api_connection.h | 3 +++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index b7db88e6ba..27dd44ae86 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -79,7 +79,11 @@ APIConnection::APIConnection(std::unique_ptr sock, APIServer *pa #endif } void APIConnection::start() { - this->last_traffic_ = millis(); + this->last_traffic_ = App.get_loop_component_start_time(); + + // Set next_ping_retry_ to prevent immediate ping + // This ensures the first ping happens after the keepalive period + this->next_ping_retry_ = this->last_traffic_ + KEEPALIVE_TIMEOUT_MS; APIError err = this->helper_->init(); if (err != APIError::OK) { @@ -163,17 +167,16 @@ void APIConnection::loop() { if (!this->initial_state_iterator_.completed() && this->list_entities_iterator_.completed()) this->initial_state_iterator_.advance(); - static uint32_t keepalive = 60000; static uint8_t max_ping_retries = 60; static uint16_t ping_retry_interval = 1000; 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) { + if (now - this->last_traffic_ > (KEEPALIVE_TIMEOUT_MS * 5) / 2) { on_fatal_error(); ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_combined_info_.c_str()); } - } else if (now - this->last_traffic_ > keepalive && now > this->next_ping_retry_) { + } else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && now > this->next_ping_retry_) { ESP_LOGVV(TAG, "Sending keepalive PING..."); this->sent_ping_ = this->send_ping_request(PingRequest()); if (!this->sent_ping_) { diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index e8a29b9c7f..f965a9e795 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -15,6 +15,9 @@ namespace esphome { namespace api { +// Keepalive timeout in milliseconds +static constexpr uint32_t KEEPALIVE_TIMEOUT_MS = 60000; + using send_message_t = bool (APIConnection::*)(void *); /*