From 91bcb14c0972be50b198e416cdce83b2833812ef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Aug 2026 21:02:10 -0500 Subject: [PATCH] Restore merged pairing dispatch and capability doc --- esphome/components/ble_device_base/ble_hub.h | 5 +++-- .../bluetooth_proxy/bluetooth_proxy.cpp | 18 +++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/esphome/components/ble_device_base/ble_hub.h b/esphome/components/ble_device_base/ble_hub.h index a27a4fb121..d40682b506 100644 --- a/esphome/components/ble_device_base/ble_hub.h +++ b/esphome/components/ble_device_base/ble_hub.h @@ -78,8 +78,9 @@ struct HubCapabilities { /// may only see them where the receiver merges per address (Home Assistant does). bool merges_scan_response; /// GATT client connections are available: the platform has a - /// bluetooth_connection backend implementing ble_device_base::BLEGattConnection - /// (ble_gatt_client.h). Today: esp32 and rp2. + /// bluetooth_connection backend (rp2 binds the BLEGattConnection alias in + /// bluetooth_connection_gatt_backend.h; esp32 uses its Bluedroid client). + /// Today: esp32 and rp2. bool gatt; /// request_scan_mode() is honored at runtime. Distinct from active_scan: /// a passive-only controller (bk72xx) can never switch, and a hub may diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 2a0d62c69b..5d5aedc195 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -315,12 +315,13 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest break; } case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR: { -#ifdef USE_ESP32 + // Both connection classes expose the same pairing surface; success is + // reported when the platform's pairing completion arrives. auto *connection = this->get_connection_(msg.address, false); if (connection != nullptr) { if (!connection->is_paired()) { auto err = connection->pair(); - if (err != ESP_OK) { + if (err != CONN_OK) { this->send_device_pairing(msg.address, false, err); } } else { @@ -330,15 +331,18 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest // Answer instead of leaving the client to time out. this->send_device_pairing(msg.address, false, GATT_NOT_CONNECTED); } -#else - // Explicit pairing is not offered (FEATURE_PAIRING is not advertised); - // peripheral-initiated security still works through the platform's SM. - this->send_device_pairing(msg.address, false, GATT_NOT_CONNECTED); -#endif break; } case api::enums::BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR: { conn_err_t ret = bluetooth_connection::unpair_device(msg.address); + if (ret == CONN_OK) { + // The bond is gone; a live connection must not short-circuit the + // next PAIR as already paired. + auto *connection = this->get_connection_(msg.address, false); + if (connection != nullptr) { + connection->set_unpaired(); + } + } this->send_device_unpairing(msg.address, ret == CONN_OK, ret); break; }