What you get in Home Assistant
One device per car, named as in the app, with these sensors:
- Fuel level, or Battery level on an electric car: the one your car reports appears.
- Range, when the car gives it.
- Odometer, ready for service reminders.
- 12 V battery: the voltage of the car's battery.
- Coolant temperature of the engine.
- Trouble codes: how many, and the codes themselves (for example P0420) in the
codesattribute. - Last trip: the distance, with duration, average and top speed and consumption as attributes.
- Trip in progress and Adapter connected, on or off.
- Fuel in litres, Speed and Engine speed, when the car reports them. Speed and engine speed are off by default.
There are also two events for automations: drivepulse_trip_start when a trip starts and drivepulse_trip_end when it ends, with the summary.
When the car does not give a value, the sensor shows Unavailable, never a made-up number. The odometer, the range and the codes keep their last value between trips.
What leaves the phone: only these numbers, and only to the address of your Home Assistant, if you turn sending on. No GPS position, no VIN, no addresses. The app only reads: it writes nothing to the car.
Install in 3 steps
- Download the integration. In Home Assistant open HACS, search for DrivePulse, select Download and restart Home Assistant. DrivePulse is in the HACS default list: no custom repository needed. On Home Assistant versions with the built-in catalog you find it there under the same name, or with the button that opens your Home Assistant.
- Add it. Settings > Devices & services > Add integration > DrivePulse, then Submit. Home Assistant shows the webhook address: copy it. You can see it again any time in Configure.
- Paste it in the app. In DrivePulse open Settings > Send to Home Assistant, turn on Send the data, paste the address in Webhook address and tap Test send. Then drive: the device appears with the first message of the first trip.
No YAML to write. If you pasted the YAML block from the app's help page, remove it from configuration.yaml before adding the integration, or you will have every sensor twice.
Away from home. On the road the phone is on mobile data, and a home address (homeassistant.local) only answers on your Wi-Fi or through a VPN. The start of a trip, in front of the house, and the end, when the phone is back on Wi-Fi, normally arrive: the app retries them for ten minutes. To receive everything on the road, use a VPN such as Tailscale, or the HTTPS address of your Home Assistant (Nabu Casa or your own domain) and turn off Local network only in Configure.
The id in the webhook address is the secret: anyone who has it can send data to your Home Assistant. Do not publish it.
Five ready-made automations
To paste one: Settings > Automations & scenes > Create automation > Create new automation, then the ⋮ menu > Edit in YAML, paste and Save.
In the examples the car is called “My car”, so the sensors are sensor.my_car_…. Use your car's name as Home Assistant shows it: for a car called Golf, sensor.golf_trouble_codes. You can replace notify.notify with your phone's service, for example notify.mobile_app_marks_iphone.
1. Low fuel
At the end of a trip, when less than 20 % is left in the tank. On an electric car use hv_soc_pct instead of fuel_level_pct.
alias: "DrivePulse: low fuel"
description: "At the end of a trip, when less than 20 % is left in the tank."
triggers:
- trigger: event
event_type: drivepulse_trip_end
conditions:
- condition: template
value_template: >
{{ trigger.event.data.fuel_level_pct is number
and trigger.event.data.fuel_level_pct < 20 }}
actions:
- action: notify.notify
data:
title: "Low fuel"
message: >
{{ trigger.event.data.vehicle }}:
{{ trigger.event.data.fuel_level_pct | round(0) | int }} % left in the tank.
2. New trouble code
When the car reports a code that was not there before. The same code does not notify you twice.
alias: "DrivePulse: new trouble code"
description: "When the car reports a code that was not there before."
triggers:
- trigger: state
entity_id: sensor.my_car_trouble_codes
conditions:
- condition: template
value_template: >
{% set before = trigger.from_state.attributes.codes | default([])
if trigger.from_state is not none else none %}
{% set after = trigger.to_state.attributes.codes | default([]) %}
{{ before is not none
and trigger.from_state.state not in ['unknown', 'unavailable']
and after | reject('in', before) | list | count > 0 }}
actions:
- action: notify.notify
data:
title: "New trouble code"
message: >
{% set before = trigger.from_state.attributes.codes | default([]) %}
{{ trigger.to_state.attributes.codes | reject('in', before) | join(', ') }}:
open DrivePulse to see what it means and whether you can drive.
3. Low 12 V battery
Below 12 V for more than a minute, so the dip while cranking does not count. The reading from the OBD port is usually 0.2-0.4 V lower than a multimeter's.
alias: "DrivePulse: low 12 V battery"
description: "Below 12 V for more than a minute (the dip while cranking does not count)."
triggers:
- trigger: numeric_state
entity_id: sensor.my_car_12_v_battery
below: 12
for: "00:01:00"
actions:
- action: notify.notify
data:
title: "Low 12 V battery"
message: >
{{ states('sensor.my_car_12_v_battery') }} V. With the engine off the
battery is low on charge; with the engine running the alternator is not
charging. Run the battery test in DrivePulse.
4. Trip summary
Distance, duration, average speed and consumption of the trip that just ended.
alias: "DrivePulse: trip summary"
description: "Distance, duration, average speed and consumption of the trip that just ended."
triggers:
- trigger: event
event_type: drivepulse_trip_end
conditions:
- condition: template
value_template: >
{{ trigger.event.data.trip is defined
and trigger.event.data.trip.distance_km is number }}
actions:
- action: notify.notify
data:
title: "{{ trigger.event.data.vehicle }}: trip finished"
message: >
{% set t = trigger.event.data.trip %}
{{ '%.1f' | format(t.distance_km) }} km
{%- if t.duration_min is number %} in {{ t.duration_min | round(0) | int }} min{% endif %}
{%- if t.avg_speed_kmh is number %}, average {{ t.avg_speed_kmh | round(0) | int }} km/h{% endif %}
{%- if t.avg_consumption_l_100km is number %}, {{ '%.1f' | format(t.avg_consumption_l_100km) }} l/100 km{% endif %}.
5. Inspection reminder
First create the date helper: Settings > Devices & services > Helpers > Create helper > Date and/or time, name Car inspection, date only, and set the date of the next inspection. The automation reminds you every time you arrive in the 30 days before, with the odometer.
alias: "DrivePulse: inspection reminder"
description: "Every time you arrive, in the 30 days before the date in the Car inspection helper."
triggers:
- trigger: event
event_type: drivepulse_trip_end
conditions:
- condition: template
value_template: >
{% set ts = state_attr('input_datetime.car_inspection', 'timestamp') %}
{% set days = ((ts - as_timestamp(today_at())) / 86400) | round(0) | int
if ts is number else -1 %}
{{ 1 <= days <= 30 }}
actions:
- action: notify.notify
data:
title: "Inspection coming up"
message: >
{% set ts = state_attr('input_datetime.car_inspection', 'timestamp') %}
{% set days = ((ts - as_timestamp(today_at())) / 86400) | round(0) | int %}
{{ trigger.event.data.vehicle }}: the inspection is due
in {{ days }} {{ 'day' if days == 1 else 'days' }}.
{%- if trigger.event.data.odometer_km is number %}
Odometer: {{ '{:,}'.format(trigger.event.data.odometer_km | round(0) | int) }} km.{% endif %}
A dashboard card
On your dashboard: pencil > Add card > Manual, paste and save. It shows trip in progress, fuel, 12 V battery, codes, odometer, the last trip and the battery over the last seven days.
type: vertical-stack
cards:
- type: tile
entity: binary_sensor.my_car_trip_in_progress
name: Driving
- type: grid
columns: 2
square: false
cards:
- type: tile
entity: sensor.my_car_fuel_level
name: Fuel
- type: tile
entity: sensor.my_car_12_v_battery
name: 12 V battery
- type: tile
entity: sensor.my_car_trouble_codes
name: Trouble codes
- type: tile
entity: sensor.my_car_odometer
name: Odometer
- type: entities
title: Last trip
entities:
- entity: sensor.my_car_last_trip
name: Distance
- type: attribute
entity: sensor.my_car_last_trip
attribute: duration_min
name: Duration
suffix: min
- type: attribute
entity: sensor.my_car_last_trip
attribute: avg_consumption_l_100km
name: Average consumption
suffix: l/100 km
- type: attribute
entity: sensor.my_car_trouble_codes
attribute: codes
name: Codes
- type: history-graph
title: 12 V battery, last 7 days
hours_to_show: 168
entities:
- entity: sensor.my_car_12_v_battery
What you need
An iPhone with DrivePulse, Home Assistant and an ELM327 OBD2 adapter, Bluetooth Low Energy (BLE) or Wi-Fi, in the car's diagnostic port. Adapters that work with iPhone include the Veepeak OBDCheck BLE and the Vgate iCar Pro 2S: the full list is on Which adapters work.
Sending to Home Assistant is off until you turn it on. You can try DrivePulse for 15 trips or 7 days, whichever comes first. After that, automatic sending resumes with the unlock, a one-time purchase, no subscription and no account. Test send always works.
The integration is open source, MIT licence: github.com/davideguida0093/drivepulse-home-assistant.
Questions
Does the data go through a server of yours?
No. The app sends it straight to the address you paste, which is your Home Assistant. No account needed.
Can I send it to another server?
Yes: the app sends a webhook to any address that accepts one, with an optional token. The DrivePulse integration only turns it into Home Assistant sensors without writing YAML.
More than one car?
Yes: each car is a device, up to 20 per address. If you rename a car in the app a new device appears; delete the old one in Devices & services.
How often do the values arrive?
At the start and at the end of every trip. If you also turn on real-time values, a message arrives at every interval, every 10 seconds by default, only while the adapter is connected.