Simplify tracking of BLE connection handle & improve thread safety. (#10390)

- Redefine isConnected in terms of nimbleBluetoothConnHandle. isConnected was not safe because BLEServer::getConnectedCount is not thread-safe (https://github.com/espressif/arduino-esp32/issues/12538) while isConnected is called from various threads. Now we can avoid checking bleServer every time before calling isConnected.
- getRssi: don't try to "populate nimbleBluetoothConnHandle", that requires calling BLEServer::getPeerDevices which is not thread-safe (same issue as above).
This commit is contained in:
Catalin Patulea
2026-05-29 06:48:43 -05:00
committed by GitHub
co-authored by GitHub
parent 1971e5ab13
commit d3c7f05baa
+13 -30
View File
@@ -187,11 +187,9 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
LOG_INFO("BLE onConfigStart");
// Prefer high throughput during config/setup, at the cost of high power consumption (for a few seconds)
if (bleServer && isConnected()) {
uint16_t conn_handle = nimbleBluetoothConnHandle.load();
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
requestHighThroughputConnection(conn_handle);
}
uint16_t conn_handle = nimbleBluetoothConnHandle.load();
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
requestHighThroughputConnection(conn_handle);
}
}
@@ -200,11 +198,9 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
LOG_INFO("BLE onConfigComplete");
// Switch to lower power consumption BLE connection params for steady-state use after config/setup is complete
if (bleServer && isConnected()) {
uint16_t conn_handle = nimbleBluetoothConnHandle.load();
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
requestLowerPowerConnection(conn_handle);
}
uint16_t conn_handle = nimbleBluetoothConnHandle.load();
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
requestLowerPowerConnection(conn_handle);
}
}
@@ -337,7 +333,7 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread
}
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() override { return bleServer && bleServer->getConnectedCount() > 0; }
virtual bool checkIsConnected() override { return nimbleBluetoothConnHandle.load() != BLE_HS_CONN_HANDLE_NONE; }
void requestHighThroughputConnection(uint16_t conn_handle)
{
@@ -732,32 +728,19 @@ bool NimbleBluetooth::isActive()
bool NimbleBluetooth::isConnected()
{
return bleServer && bleServer->getConnectedCount() > 0;
return nimbleBluetoothConnHandle.load() != BLE_HS_CONN_HANDLE_NONE;
}
int NimbleBluetooth::getRssi()
{
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
if (!bleServer || !isConnected()) {
uint16_t conn_handle = nimbleBluetoothConnHandle.load();
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
return 0; // No active BLE connection
}
uint16_t connHandle = nimbleBluetoothConnHandle.load();
if (connHandle == BLE_HS_CONN_HANDLE_NONE) {
const auto peers = bleServer->getPeerDevices(true);
if (!peers.empty()) {
connHandle = peers.begin()->first;
nimbleBluetoothConnHandle = connHandle;
}
}
if (connHandle == BLE_HS_CONN_HANDLE_NONE) {
return 0; // Connection handle not available yet
}
int8_t rssi = 0;
const int rc = ble_gap_conn_rssi(connHandle, &rssi);
const int rc = ble_gap_conn_rssi(conn_handle, &rssi);
if (rc == 0) {
return rssi;
@@ -879,7 +862,7 @@ void NimbleBluetooth::setupService()
/// Given a level between 0-100, update the BLE attribute
void updateBatteryLevel(uint8_t level)
{
if ((config.bluetooth.enabled == true) && bleServer && nimbleBluetooth->isConnected()) {
if ((config.bluetooth.enabled == true) && nimbleBluetooth->isConnected()) {
BatteryCharacteristic->setValue(&level, 1);
BatteryCharacteristic->notify();
}
@@ -894,7 +877,7 @@ void NimbleBluetooth::clearBonds()
void NimbleBluetooth::sendLog(const uint8_t *logMessage, size_t length)
{
if (!bleServer || !isConnected() || length > 512) {
if (!isConnected() || length > 512) {
return;
}
logRadioCharacteristic->setValue(logMessage, length);