From 45d019a7e4a21b319e9cf06b3d865d5165ada221 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 May 2025 19:18:19 -0500 Subject: [PATCH] Improve BLE Connection Reliability by Enabling Software Coexistence (#8683) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/esp32_ble_tracker/__init__.py | 6 +++++ .../esp32_ble_tracker/esp32_ble_tracker.cpp | 25 ++++++++++++++++--- .../esp32_ble_tracker/esp32_ble_tracker.h | 3 +++ .../esp32_ble_tracker/test.esp32-ard.yaml | 1 + .../esp32_ble_tracker/test.esp32-c3-ard.yaml | 1 + .../esp32_ble_tracker/test.esp32-c3-idf.yaml | 1 + .../esp32_ble_tracker/test.esp32-idf.yaml | 1 + 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index 2c877367f8..a4425b9680 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -44,6 +44,7 @@ CONF_ESP32_BLE_ID = "esp32_ble_id" CONF_SCAN_PARAMETERS = "scan_parameters" CONF_WINDOW = "window" CONF_ON_SCAN_END = "on_scan_end" +CONF_SOFTWARE_COEXISTENCE = "software_coexistence" DEFAULT_MAX_CONNECTIONS = 3 IDF_MAX_CONNECTIONS = 9 @@ -203,6 +204,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_ON_SCAN_END): automation.validate_automation( {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BLEEndOfScanTrigger)} ), + cv.OnlyWith(CONF_SOFTWARE_COEXISTENCE, "wifi", default=True): bool, } ).extend(cv.COMPONENT_SCHEMA), ) @@ -310,6 +312,8 @@ async def to_code(config): if CORE.using_esp_idf: add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) + if config.get(CONF_SOFTWARE_COEXISTENCE): + add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", True) # https://github.com/espressif/esp-idf/issues/4101 # https://github.com/espressif/esp-idf/issues/2503 # Match arduino CONFIG_BTU_TASK_STACK_SIZE @@ -331,6 +335,8 @@ async def to_code(config): cg.add_define("USE_OTA_STATE_CALLBACK") # To be notified when an OTA update starts cg.add_define("USE_ESP32_BLE_CLIENT") + if config.get(CONF_SOFTWARE_COEXISTENCE): + cg.add_define("USE_ESP32_BLE_SOFTWARE_COEXISTENCE") ESP32_BLE_START_SCAN_ACTION_SCHEMA = cv.Schema( diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 0dc0f58fa2..be45b177ff 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -21,6 +21,10 @@ #include "esphome/components/ota/ota_backend.h" #endif +#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE +#include +#endif + #ifdef USE_ARDUINO #include #endif @@ -194,9 +198,17 @@ void ESP32BLETracker::loop() { https://github.com/espressif/esp-idf/issues/6688 */ - if (this->scanner_state_ == ScannerState::IDLE && this->scan_continuous_ && !connecting && !disconnecting && - !promote_to_connecting) { - this->start_scan_(false); // first = false + if (this->scanner_state_ == ScannerState::IDLE && !connecting && !disconnecting && !promote_to_connecting) { +#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE + if (this->coex_prefer_ble_) { + this->coex_prefer_ble_ = false; + ESP_LOGD(TAG, "Setting coexistence preference to balanced."); + esp_coex_preference_set(ESP_COEX_PREFER_BALANCE); // Reset to default + } +#endif + if (this->scan_continuous_) { + this->start_scan_(false); // first = false + } } // If there is a discovered client and no connecting // clients and no clients using the scanner to search for @@ -213,6 +225,13 @@ void ESP32BLETracker::loop() { ESP_LOGD(TAG, "Promoting client to connect..."); // We only want to promote one client at a time. // once the scanner is fully stopped. +#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE + ESP_LOGD(TAG, "Setting coexistence to Bluetooth to make connection."); + if (!this->coex_prefer_ble_) { + this->coex_prefer_ble_ = true; + esp_coex_preference_set(ESP_COEX_PREFER_BT); // Prioritize Bluetooth + } +#endif client->set_state(ClientState::READY_TO_CONNECT); } break; diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index ca2e53c343..2e45d9602c 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -299,6 +299,9 @@ class ESP32BLETracker : public Component, int discovered_{0}; int searching_{0}; int disconnecting_{0}; +#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE + bool coex_prefer_ble_{false}; +#endif }; // NOLINTNEXTLINE diff --git a/tests/components/esp32_ble_tracker/test.esp32-ard.yaml b/tests/components/esp32_ble_tracker/test.esp32-ard.yaml index 070fffd68b..3bfdb8773f 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-ard.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-ard.yaml @@ -1,4 +1,5 @@ <<: !include common.yaml esp32_ble_tracker: + software_coexistence: true max_connections: 3 diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml index 070fffd68b..2e3c48117a 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-c3-ard.yaml @@ -2,3 +2,4 @@ esp32_ble_tracker: max_connections: 3 + software_coexistence: false diff --git a/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml index 5e09f5020e..b71896bad5 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-c3-idf.yaml @@ -2,3 +2,4 @@ esp32_ble_tracker: max_connections: 9 + software_coexistence: false diff --git a/tests/components/esp32_ble_tracker/test.esp32-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml index 5e09f5020e..1ffcfb9988 100644 --- a/tests/components/esp32_ble_tracker/test.esp32-idf.yaml +++ b/tests/components/esp32_ble_tracker/test.esp32-idf.yaml @@ -1,4 +1,5 @@ <<: !include common.yaml esp32_ble_tracker: + software_coexistence: true max_connections: 9