From 216707f507d5c77667fb31daaca38ed771c234ad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 10 Sep 2026 08:06:53 -0500 Subject: [PATCH] [esp32_ble] Cancel a pending transition instead of ignoring the opposite request enable() while a disable was still pending was ignored, so a disable followed by an enable before the next loop pass left BLE off. Cancel the pending transition in both directions; nothing has been torn down or brought up yet. The tracker only restarts its scan after a re-enable from IDLE, since a cancelled disable never stopped it. --- esphome/components/esp32_ble/ble.cpp | 10 ++++++++++ .../components/esp32_ble_tracker/esp32_ble_tracker.cpp | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 085cfbba1c..4b5505f5ad 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -84,6 +84,11 @@ void ESP32BLE::setup() { } void ESP32BLE::enable() { + if (this->state_ == BLE_COMPONENT_STATE_DISABLE) { + // The teardown has not run yet; the stack is still up. + this->state_ = BLE_COMPONENT_STATE_ACTIVE; + return; + } if (this->state_ != BLE_COMPONENT_STATE_DISABLED) return; @@ -91,6 +96,11 @@ void ESP32BLE::enable() { } void ESP32BLE::disable() { + if (this->state_ == BLE_COMPONENT_STATE_ENABLE) { + // The bring-up has not run yet; the stack is still down. + this->state_ = BLE_COMPONENT_STATE_DISABLED; + return; + } if (this->state_ == BLE_COMPONENT_STATE_DISABLED) return; diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index cbf3378723..9e5f424c87 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -78,8 +78,9 @@ void ESP32BLETracker::loop() { return; } else if (this->ble_was_disabled_) { this->ble_was_disabled_ = false; - // If the BLE stack was disabled, we need to start the scan again. - if (this->scan_continuous_) { + // Start the scan again after a disable. A cancelled disable never stopped + // it, so only start from IDLE. + if (this->scan_continuous_ && this->scanner_state_ == ScannerState::IDLE) { this->start_scan(); } }