diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index fc95760cf8..15c370d3e2 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -580,6 +580,14 @@ void ESP32BLE::loop_handle_state_transition_not_active_() { this->mark_failed(); return; } + // Whatever the old stack queued while going down (close events for the + // links it tore down, scan completions) must not replay against the next + // stack, which hands out the same interface ids. + BLEEvent *ble_event; + while ((ble_event = this->ble_events_.pop()) != nullptr) { + this->ble_event_pool_.release(ble_event); + } + this->ble_events_.get_and_reset_dropped_count(); this->state_ = BLE_COMPONENT_STATE_DISABLED; } else if (this->state_ == BLE_COMPONENT_STATE_ENABLE) { ESP_LOGD(TAG, "Enabling"); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index b3c905c8d8..7ae2ce568d 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -225,6 +225,15 @@ void ESP32BLETracker::ble_before_disabled_event_handler() { client->ble_before_disabled_event_handler(); } #endif + // The stop above never completes: the stack is torn down and its queued + // events are dropped, so settle the scanner here. start_scan_() refuses + // anything but IDLE once the stack is back. + if (this->scanner_state_ != ScannerState::IDLE) { +#ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT + this->skip_next_scan_end_ = false; +#endif + this->cleanup_scan_state_(true); + } } bool ESP32BLETracker::stop_scan_() {