Skip to content

fix(tesla): honor runtime BLE client bindings - #111

Merged
Bre77 merged 2 commits into
mainfrom
fm/tfa-ble-client-binding
Aug 5, 2026
Merged

fix(tesla): honor runtime BLE client bindings#111
Bre77 merged 2 commits into
mainfrom
fm/tfa-ble-client-binding

Conversation

@Bre77

@Bre77 Bre77 commented Aug 5, 2026

Copy link
Copy Markdown
Member

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] on establish_connection is 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() a characteristic_resolution line, each naming the chained exception's type and message so the underlying transport failure is diagnosable on the next occurrence; both still raise BluetoothTransportError with __cause__ preserved. A post-connect is_connected check raises if establish_connection hands 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

  • Resolve bleak.BleakClient and bleak.BleakScanner at call time so Home Assistant/habluetooth runtime replacements are honored.
  • Add stage-specific BLE connection and characteristic-resolution diagnostics, including a post-connect status check while preserving the original error cause.
  • Add regression coverage for late client/scanner binding, connection diagnostics, scan behavior, and unchanged router failover semantics.

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 unavailable

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 unavailable

Pipeline

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.

  • Inspected git diff --stat and changed paths between base 4b82766737558dc5b4fc6f73b361ac173d2fe728 and target fe14b38c58aab106ef83a33624caef42caa41940.
  • uv run pytest -q tests/test_ble_client_binding.py tests/test_find_vehicle_scan_filter.py
  • Manual async consumer-style check replacing bleak.BleakClient after 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.

firstmate crewmate 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.
@Bre77 Bre77 added the fm Opened by a Firstmate crewmate label Aug 5, 2026
@Bre77
Bre77 merged commit 3f28874 into main Aug 5, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fm Opened by a Firstmate crewmate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant