fix(tesla): reduce BLE connection retry delay - #114
Merged
Conversation
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.
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
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
max_attemptsoverrides and cloud fallback throughVehicleRouterwhen BLE connection attempts are exhausted.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'}}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.
Inspectedgit diff a76839606c18be12a2d88907e0023101a7117334..0bcec2b98bebb5aca398e41eeb67fe03b2bcfa38uv run pytest -q tests/test_ble_connect_retry_budget.pyuv 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::KeepaliveLifecycleTestsRan a mocked consumer-levelVehicleRouter.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.txtVerifiedgit status --shortwas clean after removing transient build metadata changes✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.