Home Assistant

Parked-car location

When the phone drops the car’s Bluetooth connection, Home Assistant copies the phone’s GPS onto a device tracker so the car shows up on the map.

Difficulty · BeginnerSetup · 20–40 minutesHA · current stable (blueprint)
Get the pack · from $19Have us set it up

The car does not have a tracker of its own. The phone does. While the phone is on the car’s Bluetooth, the person is in the car. The moment that connection drops, the phone is standing next to where the car was parked. This pack writes that GPS fix onto a device_tracker named for the car, so the Home Assistant map keeps the pin after the phone walks away.

Entity ids are blueprint inputs (device_tracker.phone, sensor.phone_bluetooth_connection). Do not publish a phone name, a car name, or a street address. The Bluetooth id you match stays in the blueprint input on your Home Assistant instance. It does not belong in a published file.

A garage bay that measures distance as you pull in is LiDAR garage parking. This pack is the pin for a car left somewhere else.

What problem it solves

You want the map to remember where the car is after you lock it and walk off, without a tracker in the car and without typing a spot number.

How it works

  1. Bluetooth sensor — in the Companion app, enable the Bluetooth connection sensor. Its connected_paired_devices attribute is the list of devices the phone is paired to and currently connected to. This list is an Android Companion sensor. iOS Companion does not publish the same attribute, so this pack does not run on an iPhone.
  2. Which device is the car — open Developer Tools → States, connect the phone to the car, and copy that entry from connected_paired_devices into the blueprint input. The condition matches a prefix of the entry, so a friendly name in parentheses after the id still counts. One automation, one car. A second car is a second automation and a second dev_id.
  3. Disconnect — the trigger is any change of that attribute. The condition passes only when the car id was in the previous list and is absent from the new list. Connecting does not move the pin. Another headset connecting does not move it either.
  4. Fresh fix — while the attribute still contains the car id, the pack asks Companion to send a location update. A phone that only reports every 15 minutes would otherwise save a fix from the highway. The disconnect action then reads latitude and longitude from the phone’s device_tracker.
  5. Pin — device_tracker.see with dev_id: parked_car creates or updates device_tracker.parked_car. The first call also writes a stub in known_devices.yaml. Set track: true and an icon there if you want the pin labeled. Later disconnects update the same id.
  6. Optional push — a Companion notification with a maps link built from the tracker’s latitude and longitude. The link is generated at send time. The pack does not store a street name.

Two phones and one car can share dev_id: parked_car. The last phone to disconnect wins, which is the phone that was in the car.

Hardware notes

  • Phone. Android, Companion installed, location permission allowed, Bluetooth connection sensor enabled, and a device_tracker from that phone with numeric latitude and longitude. A tracker that only says home or away has nothing to copy.
  • Car. The head unit the phone already pairs to. There is no extra beacon in this pack. Apps and a radio you already own do not get a product link.
  • Map. The default Home Assistant map shows device_tracker entities that have GPS coordinates. No custom card is required.

Snippet

The pack ships a blueprint. The car id is an input. Do not paste a hardware id into the YAML you share.

mode: single

variables:
  car_id: !input car_id
  phone_tracker: !input phone_tracker

trigger:
  - platform: state
    entity_id: !input bluetooth_sensor
    attribute: connected_paired_devices

condition:
  - condition: template
    value_template: >
      {% set before = trigger.from_state.attributes.connected_paired_devices | default([]) %}
      {% set after = trigger.to_state.attributes.connected_paired_devices | default([]) %}
      {% set ns = namespace(was=false, now=false) %}
      {% for item in before %}
        {% if item is string and item.startswith(car_id) %}
          {% set ns.was = true %}
        {% endif %}
      {% endfor %}
      {% for item in after %}
        {% if item is string and item.startswith(car_id) %}
          {% set ns.now = true %}
        {% endif %}
      {% endfor %}
      {{ ns.was and not ns.now }}

action:
  - action: device_tracker.see
    data:
      dev_id: parked_car
      gps:
        - "{{ state_attr(phone_tracker, 'latitude') }}"
        - "{{ state_attr(phone_tracker, 'longitude') }}"

The full blueprint also sends command_update_location on a one-minute pattern while the car id is still in the list, and it skips device_tracker.see when latitude or longitude is missing.

Setup outline

  1. Enable the Bluetooth connection sensor and background location on the phone. Pair the phone to the car if it is not already paired.
  2. Sit in the car with Bluetooth connected. In Developer Tools, copy the car’s entry from connected_paired_devices. Confirm the phone tracker has numeric coordinates.
  3. Import the blueprint. Paste that entry’s id into the car-id input. Select the Bluetooth sensor, the phone tracker, and the notify target.
  4. Run device_tracker.see once by disconnecting Bluetooth, or call the action from Developer Tools with a test coordinate pair you are willing to overwrite. Confirm device_tracker.parked_car appears on the map.
  5. Drive a short loop, park, and walk away until the phone drops the car. The pin should sit at the parking spot, not at home and not at the last highway sample.

Troubleshooting

  • The automation never fires. The Bluetooth connection sensor is disabled, or the trigger is watching the sensor state instead of connected_paired_devices. The state string can stay the same while the list changes. The trigger has to be on the attribute.
  • It fires for the wrong device. The car id is a prefix of another entry. Use a longer prefix from the Developer Tools value.
  • The pin is miles away. The phone’s last GPS sample was old. Confirm the location-refresh command runs while Bluetooth is still up, and that Companion is allowed to update location in the background.
  • Manual run works, disconnect does not. The condition wants the id in from_state and gone in to_state. A manual run has no from_state. Disconnect for real, with the attribute changing.
  • No coordinates. The selected tracker is a router or a zone-only person. Point the input at the Companion device_tracker that has latitude and longitude.
  • iPhone. Expected. This sensor list is Android. An iPhone needs a different trigger than this pack.

Credits

Based on the community blueprint Bluetooth Device Last Known Location and the matching gist. This write-up is an original overview of the disconnect-to-map pattern, including a location refresh while the phone is still connected. It is not a paste of that blueprint.

Changelog

v1.0 · Oct 26, 2026: First publish.