diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 9b07033cfc..f47642944b 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -145,6 +145,36 @@ void BLEClientBase::connect() { this->remote_addr_type_); this->paired_ = false; + // Set preferred connection parameters before connecting + // Use FAST for all V3 connections (better latency and reliability) + // Use MEDIUM for V1/legacy connections (balanced performance) + uint16_t min_interval, max_interval, timeout; + const char *param_type; + + if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE || + this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) { + min_interval = FAST_MIN_CONN_INTERVAL; + max_interval = FAST_MAX_CONN_INTERVAL; + timeout = FAST_CONN_TIMEOUT; + param_type = "fast"; + } else { + min_interval = MEDIUM_MIN_CONN_INTERVAL; + max_interval = MEDIUM_MAX_CONN_INTERVAL; + timeout = MEDIUM_CONN_TIMEOUT; + param_type = "medium"; + } + + auto param_ret = esp_ble_gap_set_prefer_conn_params(this->remote_bda_, min_interval, max_interval, + 0, // latency: 0 + timeout); + if (param_ret != ESP_OK) { + ESP_LOGW(TAG, "[%d] [%s] esp_ble_gap_set_prefer_conn_params failed: %d", this->connection_index_, + this->address_str_.c_str(), param_ret); + } else { + ESP_LOGD(TAG, "[%d] [%s] Set %s conn params", this->connection_index_, this->address_str_.c_str(), param_type); + } + + // Now open the connection auto ret = esp_ble_gattc_open(this->gattc_if_, this->remote_bda_, this->remote_addr_type_, true); if (ret) { ESP_LOGW(TAG, "[%d] [%s] esp_ble_gattc_open error, status=%d", this->connection_index_, this->address_str_.c_str(), @@ -152,35 +182,6 @@ void BLEClientBase::connect() { this->set_state(espbt::ClientState::IDLE); } else { this->set_state(espbt::ClientState::CONNECTING); - - // Always set connection parameters to ensure stable operation - // Use FAST for all V3 connections (better latency and reliability) - // Use MEDIUM for V1/legacy connections (balanced performance) - uint16_t min_interval, max_interval, timeout; - const char *param_type; - - if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE || - this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) { - min_interval = FAST_MIN_CONN_INTERVAL; - max_interval = FAST_MAX_CONN_INTERVAL; - timeout = FAST_CONN_TIMEOUT; - param_type = "fast"; - } else { - min_interval = MEDIUM_MIN_CONN_INTERVAL; - max_interval = MEDIUM_MAX_CONN_INTERVAL; - timeout = MEDIUM_CONN_TIMEOUT; - param_type = "medium"; - } - - auto param_ret = esp_ble_gap_set_prefer_conn_params(this->remote_bda_, min_interval, max_interval, - 0, // latency: 0 - timeout); - if (param_ret != ESP_OK) { - ESP_LOGW(TAG, "[%d] [%s] esp_ble_gap_set_prefer_conn_params failed: %d", this->connection_index_, - this->address_str_.c_str(), param_ret); - } else { - ESP_LOGD(TAG, "[%d] [%s] Set %s conn params", this->connection_index_, this->address_str_.c_str(), param_type); - } } } @@ -255,6 +256,19 @@ void BLEClientBase::log_event_(const char *name) { ESP_LOGD(TAG, "[%d] [%s] %s", this->connection_index_, this->address_str_.c_str(), name); } +void BLEClientBase::restore_medium_conn_params_() { + // Restore to medium connection parameters after initial connection phase + // This balances performance with bandwidth usage for normal operation + esp_ble_conn_update_params_t conn_params = {{0}}; + memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t)); + conn_params.min_int = MEDIUM_MIN_CONN_INTERVAL; + conn_params.max_int = MEDIUM_MAX_CONN_INTERVAL; + conn_params.latency = 0; + conn_params.timeout = MEDIUM_CONN_TIMEOUT; + ESP_LOGD(TAG, "[%d] [%s] Restoring medium conn params", this->connection_index_, this->address_str_.c_str()); + esp_ble_gap_update_conn_params(&conn_params); +} + bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if, esp_ble_gattc_cb_param_t *param) { if (event == ESP_GATTC_REG_EVT && this->app_id != param->reg.app_id) @@ -322,6 +336,10 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGI(TAG, "[%d] [%s] Connection open", this->connection_index_, this->address_str_.c_str()); if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) { ESP_LOGI(TAG, "[%d] [%s] Using cached services", this->connection_index_, this->address_str_.c_str()); + + // Restore to medium connection parameters for cached connections too + this->restore_medium_conn_params_(); + // only set our state, subclients might have more stuff to do yet. this->state_ = espbt::ClientState::ESTABLISHED; break; @@ -419,15 +437,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ // This balances performance with bandwidth usage after the critical discovery phase if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE || this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) { - esp_ble_conn_update_params_t conn_params = {{0}}; - memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t)); - conn_params.min_int = MEDIUM_MIN_CONN_INTERVAL; - conn_params.max_int = MEDIUM_MAX_CONN_INTERVAL; - conn_params.latency = 0; - conn_params.timeout = MEDIUM_CONN_TIMEOUT; - ESP_LOGD(TAG, "[%d] [%s] Restored medium conn params after service discovery", this->connection_index_, - this->address_str_.c_str()); - esp_ble_gap_update_conn_params(&conn_params); + this->restore_medium_conn_params_(); } this->state_ = espbt::ClientState::ESTABLISHED; diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index 0a2fda4476..b30e9cd444 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -127,6 +127,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { // 6 bytes used, 2 bytes padding void log_event_(const char *name); + void restore_medium_conn_params_(); }; } // namespace esp32_ble_client