Skip to content

fix(ble): drop scan-time service UUID filter from find_vehicle - #45

Merged
Bre77 merged 2 commits into
mainfrom
fm/tfa-findveh-filter-r3
Jul 9, 2026
Merged

fix(ble): drop scan-time service UUID filter from find_vehicle#45
Bre77 merged 2 commits into
mainfrom
fm/tfa-findveh-filter-r3

Conversation

@Bre77

@Bre77 Bre77 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Intent

  • Bug: find_vehicle scan-time filter hides the vehicle on a direct BlueZ adapter
    • The vehicle advertises no 128-bit service UUID in either its ADV_IND or its scan response - only its VIN-derived local name (^S[a-f0-9]{16}[CDRP]$) is advertised, and only in the SCAN_RSP. SERVICE_UUID only exists as a GATT service after connecting.
    • find_vehicle scanned with BleakScanner(service_uuids=[SERVICE_UUID]), a discovery-time filter. Since the car never advertises that UUID, a direct bleak/BlueZ adapter returns zero devices and the vehicle is never found.
    • This was masked in prior testing because discovery went through an ESPHome bluetooth proxy (bleak-esphome/habluetooth), whose scanner doesn't enforce the service-UUID filter the same way - the car was still found there, papering over the bug for anyone on a direct local adapter.
  • Fix
    • Drop the service_uuids filter; scan unfiltered and match by the existing VIN-derived name lookup (find_device_by_name), which is the actual discriminator the car exposes pre-connect.
    • Explicitly request active scanning (scanning_mode="active") so the scan response - which carries the name - is captured. This matches bleak's own default, but makes the requirement explicit rather than incidental.
    • SERVICE_UUID itself and its post-connect GATT uses (establish_connection(..., services=[SERVICE_UUID])) are untouched - it's still correct there, only the scan-time filter use was wrong.
    • Scope: this is a single, minimal fix to the discovery filter. No other BLE behavior changed.

What Changed

  • tesla_fleet_api/tesla/vehicle/bluetooth.py: find_vehicle's default BleakScanner no longer passes service_uuids=[SERVICE_UUID]; it now passes scanning_mode="active" instead.
  • tests/test_find_vehicle_scan_filter.py (new): asserts the default scanner is constructed without a service_uuids filter and with active scanning, and that name-based matching still works end to end.

Risk Assessment

Low, and safe by construction: removing a discovery filter can only surface more devices to the name-match step, never hide the target vehicle. Post-connect GATT behavior (SERVICE_UUID usage in connect()) is unchanged.

Testing

  • uv run pytest tests - 58 passed, 8 subtests passed.
  • uv run ruff check / uv run ruff format --check on touched files - clean.
  • uv run pyright tesla_fleet_api - 0 errors.
  • Added a focused unit test verifying the scanner is built without the service-UUID filter and that name-based discovery is preserved.
  • Not verified against a live direct-BlueZ adapter in this environment; the bug was originally surfaced via live BLE discovery through an ESPHome proxy, which showed the vehicle advertises only the VIN-derived name (in the scan response) and no service UUID pre-connect - the proxy's scanner just doesn't enforce the filter the way a direct BlueZ adapter does, which is why this went unnoticed until now.
Full narrative / original brief

find_vehicle scans with BleakScanner(service_uuids=[SERVICE_UUID]) (the Tesla vehicle BLE service UUID) as a discovery-time filter. But a Tesla vehicle does not advertise that 128-bit service UUID in its advertisement or scan-response - it advertises only its VIN-derived local name (^S[a-f0-9]{16}[CDRP]$) in the scan response, plus a nameless iBeacon ADV_IND. The service UUID only exists as a GATT service after you connect. So filtering the scan by that UUID means a direct BlueZ/bleak adapter returns zero devices and find_vehicle never sees the car.

This was masked in testing because discovery went through an ESPHome bluetooth proxy (bleak-esphome/habluetooth), whose scanner does not enforce the service-UUID filter the same way - so the car was still found. On a direct local adapter it would not be.

Fix: drop the scan-time service_uuids filter, scan unfiltered, match by the existing VIN-derived local name, and require active scanning so the scan response (which carries the name) is captured. Keep all post-connect SERVICE_UUID GATT usage intact.

firstmate crewmate added 2 commits July 9, 2026 16:10
The vehicle advertises no 128-bit service UUID in its advertisement or
scan response - only its VIN-derived name (in the scan response).
SERVICE_UUID only exists as a GATT service after connecting. Filtering
BleakScanner discovery by service_uuids therefore hides the vehicle
entirely on a direct BlueZ adapter; this was masked in testing because
an ESPHome bluetooth proxy doesn't enforce that filter the same way.

Scan unfiltered and match by name instead, with active scanning
required so the scan response (which carries the name) is captured.
Post-connect GATT use of SERVICE_UUID is untouched.
Durable knowledge from the find_vehicle scan-filter fix: the vehicle
advertises no service UUID pre-connect, so a BleakScanner service_uuids
filter hides it on a direct BlueZ adapter.
@Bre77
Bre77 merged commit c16d254 into main Jul 9, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant