fix(tesla): honor runtime BLE client bindings - #111
Merged
Conversation
added 2 commits
August 5, 2026 14:55
Both BLE modules bound BleakClient/BleakScanner via `from bleak import` at module load. Home Assistant's habluetooth replaces those bleak module attributes at runtime with a multi-adapter/proxy-aware client; an import-time binding permanently ignores that replacement and connects on the pristine local backend instead of the HA-selected adapter or ESPHome proxy. Switch to `import bleak` and reference bleak.BleakClient/ bleak.BleakScanner at call time so the late-installed wrapper wins regardless of import order. Add per-stage debug diagnostics to connect() (establish_connection / start_notify / is_connected) and to the characteristic-resolution branch of _send, naming the stage and chaining the original exception type and message, so the underlying connect failure is diagnosable on recurrence. SERVICE_UUID scan/connect behavior and Router failover semantics are unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Make the tesla_fleet_api BLE transport honour the Bluetooth client Home Assistant/habluetooth installs at runtime, and make connect failures diagnosable.
Root defect: both BLE modules (tesla/vehicle/bluetooth.py and tesla/bluetooth.py) bound BleakClient/BleakScanner via 'from bleak import ...' at module import time. Home Assistant's habluetooth replaces those bleak module attributes at runtime with a multi-adapter/proxy-aware client; a name captured at import permanently ignores that replacement and connects on the pristine local backend instead of the HA-selected adapter or ESPHome proxy. Fix: switch to 'import bleak' and reference bleak.BleakClient/bleak.BleakScanner at call time so the late-installed wrapper wins regardless of import order. Type-only imports moved under TYPE_CHECKING.
Two things are deliberately left alone.
services=[SERVICE_UUID]onestablish_connectionis unchanged: the evidence does not implicate characteristic lookup, so removing the filter would not be evidence-based. Router/VehicleRouter failover is unchanged: the cloud fallback behaved correctly and is what let the reported wake eventually succeed.Alongside the binding fix,
connect()now emits a per-stage debug line (stage=establish_connection/start_notify/is_connected) and_send()acharacteristic_resolutionline, each naming the chained exception's type and message so the underlying transport failure is diagnosable on the next occurrence; both still raiseBluetoothTransportErrorwith__cause__preserved. A post-connectis_connectedcheck raises ifestablish_connectionhands back a client that is not actually connected. This is a published library, so backward compatibility is a hard requirement: no public API change, and importing the modules keeps working for consumers who never install a wrapper.Note on cause: this fixes a genuine latent binding bug, but it is not claimed to fix the specific reported wake incident. Live evidence confirmed ESPHome-proxy connection-slot exhaustion was that incident's cause, which this change does not address; the new stage diagnostics are what will distinguish the two failure modes if it recurs.
What Changed
bleak.BleakClientandbleak.BleakScannerat call time so Home Assistant/habluetooth runtime replacements are honored.Risk Assessment
✅ Low: The change is narrowly scoped, dynamically resolves both BLE client and scanner classes as required, preserves existing connection and router semantics, and adds correctly chained stage diagnostics without a source-verifiable regression.
Testing
Focused BLE regressions passed, and a manual runtime transcript demonstrated that a late-installed Home Assistant-style client is selected while connection failures retain the public API, original cause, and actionable stage diagnostics.
Evidence: BLE runtime binding and diagnostics transcript
DEBUG BLE connect failed vin=5YJXCAE43LF123456 stage=establish_connection BleakError: proxy adapter unavailable DEBUG The Bluetooth transport failed before a vehicle response could be awaited. late_runtime_client_selected: True selected_client_name: HomeAssistantRuntimeClient public_exception: BluetoothTransportError cause_preserved: True cause_detail: BleakError: proxy adapter unavailablePipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
Inspectedgit diff --statand changed paths between base4b82766737558dc5b4fc6f73b361ac173d2fe728and targetfe14b38c58aab106ef83a33624caef42caa41940.uv run pytest -q tests/test_ble_client_binding.py tests/test_find_vehicle_scan_filter.pyManual async consumer-style check replacingbleak.BleakClientafter module import, connecting through the replacement, then inducing a connect failure and recording its stage-specific log, public exception, and preserved cause.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.