This commit is contained in:
J. Nick Koston
2026-01-01 17:44:39 -10:00
parent 291722c50e
commit dc07926a91
3 changed files with 14 additions and 25 deletions
+9 -23
View File
@@ -25,10 +25,6 @@ namespace esphome::api {
static const char *const TAG = "api";
// Grace period before dropping API clients when network disconnects
// Allows for brief disconnections during WiFi roaming
static constexpr uint32_t NETWORK_DISCONNECT_GRACE_MS = 10000;
// APIServer
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
@@ -110,10 +106,8 @@ void APIServer::setup() {
}
#endif
// Initialize timestamps for timeout tracking
const uint32_t now = App.get_loop_component_start_time();
this->last_connected_ = now;
this->network_last_connected_ = now;
// Initialize last_connected_ for reboot timeout tracking
this->last_connected_ = App.get_loop_component_start_time();
// Set warning status if reboot timeout is enabled
if (this->reboot_timeout_ != 0) {
this->status_set_warning();
@@ -168,22 +162,14 @@ void APIServer::loop() {
// Process clients and remove disconnected ones in a single pass
// Check network connectivity once for all clients
const uint32_t now = App.get_loop_component_start_time();
if (network::is_connected()) {
// Network is up - track this for grace period
this->network_last_connected_ = now;
} else {
// Network is down - check if grace period has expired
// This allows brief disconnections during WiFi roaming without dropping API clients
if (now - this->network_last_connected_ > NETWORK_DISCONNECT_GRACE_MS) {
// Grace period expired - disconnect all clients
for (auto &client : this->clients_) {
client->on_fatal_error();
ESP_LOGW(TAG, "%s (%s): Network down; disconnect", client->client_info_.name.c_str(),
client->client_info_.peername.c_str());
}
// Continue to process and clean up the clients below
if (!network::is_connected()) {
// Network is down - disconnect all clients
for (auto &client : this->clients_) {
client->on_fatal_error();
ESP_LOGW(TAG, "%s (%s): Network down; disconnect", client->client_info_.name.c_str(),
client->client_info_.peername.c_str());
}
// Continue to process and clean up the clients below
}
size_t client_index = 0;
-1
View File
@@ -253,7 +253,6 @@ class APIServer : public Component,
// 4-byte aligned types
uint32_t reboot_timeout_{300000};
uint32_t last_connected_{0};
uint32_t network_last_connected_{0}; // Track when network was last connected (for roaming grace period)
// Vectors and strings (12 bytes each on 32-bit)
std::vector<std::unique_ptr<APIConnection>> clients_;
@@ -242,7 +242,11 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
if (!this->wifi_mode_(true, {}))
return false;
this->wifi_disconnect_();
// Skip disconnect for roaming - let the SDK handle the transition
// This preserves TCP connections during the brief AP switch
if (!this->roaming_connect_active_) {
this->wifi_disconnect_();
}
struct station_config conf {};
memset(&conf, 0, sizeof(conf));