Skip to content

fix(tesla): reduce BLE connection retry delay - #114

Merged
Bre77 merged 2 commits into
mainfrom
fm/tfa-ble-retry-budget
Aug 6, 2026
Merged

fix(tesla): reduce BLE connection retry delay#114
Bre77 merged 2 commits into
mainfrom
fm/tfa-ble-retry-budget

Conversation

@Bre77

@Bre77 Bre77 commented Aug 6, 2026

Copy link
Copy Markdown
Member

Intent

Shorten the BLE connect retry budget so a contended connection slot (all phone/watch connection slots held) fails over to cloud fast instead of burning ~81 seconds. On real hardware, bleak_retry_connector's default (4 attempts x its own fixed, unexposed ~20s per-attempt timeout, plus backoff) burns ~81s before BluetoothTransportError finally lets the Router fall back to cloud - indistinguishable from a hang from the user's perspective. Discovery works fine in that state; only connects fail. Fix: reduce the BLE connect retry budget (attempts) so a contended-slot scenario surfaces failure much faster, without breaking legitimate slow-connect cases (car waking, weak RF) that genuinely need a retry or two. Tune the existing mechanism (the max_attempts default passed to bleak_retry_connector's establish_connection via VehicleBluetooth.connect()/connect_if_needed() in tesla_fleet_api/tesla/vehicle/bluetooth.py) rather than adding a new parallel retry mechanism. Investigated whether per-attempt timeout could also be reduced: bleak_retry_connector hardcodes BLEAK_TIMEOUT=20.0 inside its own establish_connection implementation and does not expose it as an overridable parameter, so monkeypatching that global constant was deliberately rejected (it would mutate process-wide state shared with any other consumer of the same dependency in the same process, e.g. other Home Assistant integrations) - attempt count is therefore the only safe budget lever available. Implemented: added a new DEFAULT_CONNECT_ATTEMPTS = 2 constant in tesla_fleet_api/tesla/vehicle/bluetooth.py and changed connect()'s and connect_if_needed()'s max_attempts default from bleak_retry_connector's own MAX_CONNECT_ATTEMPTS (4) to this new constant, cutting the worst-case stall from ~81s to ~40s while still allowing one retry for genuinely transient failures. Callers can still pass a larger max_attempts explicitly for scenarios that need more retries. This does not differentiate 'device seen in discovery but connect times out' from 'device not seen' with separate budgets - the simplest single-constant budget cut was chosen over building that additional machinery, matching the instruction not to over-engineer this. Added tests/test_ble_connect_retry_budget.py covering: the new default is smaller than bleak_retry_connector's own default, connect() and connect_if_needed() both pass the reduced default through to establish_connection, a caller-supplied override is still honored, a contended-slot failure (establish_connection exhausting its internal budget and raising) still surfaces as BluetoothTransportError, and Router still fails over to the cloud secondary after that failure. This PR rides on top of the just-merged PR #111 (runtime BLE client-binding fix); scope is intentionally limited to the retry budget only, no unrelated changes.

What Changed

  • Reduce the default BLE connection retry budget from four attempts to two, cutting worst-case connection delays from roughly 81 seconds to 40 seconds while retaining one retry.
  • Preserve explicit max_attempts overrides and cloud fallback through VehicleRouter when BLE connection attempts are exhausted.
  • Document the retry behavior and add regression coverage for defaults, overrides, transport errors, and router failover.

Risk Assessment

✅ Low: The source change is narrowly scoped and the default/override propagation and Router failure path remain consistent with the stated containment goal; no material defects were found.

Testing

No prior baseline output was supplied; focused retry-budget tests, adjacent BLE connection/lifecycle regressions, and an API-level contended-slot Router failover demonstration all passed, with a reviewer-visible transcript captured. No visual artifact was appropriate because this is a backend Python API behavior change with no rendered UI.

Evidence: BLE retry budget and Router cloud-failover transcript

library connector default attempts: 4 Tesla BLE default attempts: 2 attempt budget passed to connector: 2 routed wake_up response after BLE failure: {'response': {'result': True, 'source': 'cloud'}}

library connector default attempts: 4
Tesla BLE default attempts: 2
attempt budget passed to connector: 2
routed wake_up response after BLE failure: {'response': {'result': True, 'source': 'cloud'}}

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 a76839606c18be12a2d88907e0023101a7117334..0bcec2b98bebb5aca398e41eeb67fe03b2bcfa38
  • uv run pytest -q tests/test_ble_connect_retry_budget.py
  • uv run pytest -q tests/test_ble_client_binding.py::LateBleakClientBindingTests tests/test_ble_client_binding.py::ConnectStageDiagnosticsTests tests/test_ble_client_binding.py::RouterFailoverUnchangedTests tests/test_ble_send_transport.py::ConnectTransportErrorTests tests/test_ble_keepalive.py::KeepaliveLifecycleTests
  • Ran a mocked consumer-level VehicleRouter.wake_up() call with BLE slot contention and captured the passed retry budget plus returned cloud response in /tmp/no-mistakes-evidence/01KZA9EWYWTNBF9EEPP4QSCHYV/ble-retry-router-failover.txt
  • Verified git status --short was clean after removing transient build metadata changes
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

firstmate crewmate added 2 commits August 6, 2026 11:00
bleak_retry_connector's default max_attempts (4) pairs with its fixed,
unexposed ~20s per-attempt connect timeout, so a contended connection
slot burns ~81s before BluetoothTransportError lets a Router fail over
to cloud - indistinguishable from a hang. DEFAULT_CONNECT_ATTEMPTS (2)
still allows one retry for a genuinely transient failure (car waking,
weak RF) while capping the worst case at ~40s; callers can still pass
a larger max_attempts explicitly.
@Bre77 Bre77 added the fm Opened by a Firstmate crewmate label Aug 6, 2026
@Bre77
Bre77 merged commit fe1b3db into main Aug 6, 2026
6 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