
Tired of manually checking Google Maps and your calendar to figure out when to leave for your next meeting?
I recently realized that Home Assistant already has all the necessary pieces – my current geolocation, calendar events, and Waze travel time – so I put together an automation to provide real-time notifications telling me exactly when I need to head out the door.
It’s pretty simple, following these steps every five minutes:
- Retrieve all events in the next 4 hours from my work and personal calendars
- Eliminate all-day events, events with no location, or events I’ve already been reminded of (stored in a helper input sensor called last_notified_event_id)
- For the remaining events, retrieve Waze travel time from my current location to the event location (using entity location versus a static address or lat/long is important because I might not be at home, affecting travel time)
- Determine departure time (start time minus travel time minus 5 minutes of wiggle room)
- Determine reminder time (30 minutes prior to departure time)
- Send a notification to my phone alerting me to the upcoming event, estimated travel time, and the time I need to leave
- Store a synthetic “event ID” (the start time and summary) in an input helper sensor, so we can make sure I’m not reminded again
Note: I’m pretty new to Home Assistant templating (though a past life as a Perl dev has hammered YAML syntax into my head irreversably) so there may be stupidity in this automation. But, it works for me (so far!)
alias: Drive time alert
description: ""
# fire every five minutes
triggers:
- trigger: time_pattern
minutes: /5
conditions: []
actions:
- action: calendar.get_events
metadata: {}
data:
duration:
hours: 4
minutes: 0
seconds: 0
target:
entity_id:
- calendar.personal_calendar
- calendar.work_calendar
response_variable: cal_events
- repeat:
for_each: "{{ cal_events.values() | map(attribute='events') | sum(start=[]) }}"
sequence:
- variables:
thisEventId: "{{ repeat.item.start }} {{ repeat.item.summary }}"
- condition: template
value_template: |
{{ repeat.item.location is not none and
(repeat.item.location | string | trim != "") and
'T' in (repeat.item.start | string) and
states('input_text.last_notified_event_id') and
thisEventId != states('input_text.last_notified_event_id') }}
- data:
origin: person.mike
destination: "{{ repeat.item.location }}"
region: us
response_variable: waze_eta_result
continue_on_error: false
action: waze_travel_time.get_travel_times
- variables:
wiggle_room: "{{ 5 }}"
waze_duration: "{{ waze_eta_result['routes'][0].duration | round(0) }}"
start_time: "{{ repeat.item.start }}"
start_time_friendly: "{{ as_datetime(start_time).strftime('%I:%M %p') }}"
location: "{{ repeat.item.location }}"
summary: "{{ repeat.item.summary }}"
departure_time: >-
{{ as_datetime(start_time) - timedelta(minutes=waze_duration) -
timedelta(minutes=wiggle_room) }}
departure_time_friendly: "{{ as_datetime(departure_time).strftime('%I:%M %p') }}"
reminder_time: "{{ as_datetime(departure_time) - timedelta(minutes=30) }}"
- condition: template
value_template: |
{{ as_datetime(reminder_time) <= now() }}
- action: notify.mobile_app_pixel_6_mike
metadata: {}
data:
data:
ttl: 0
priority: high
message: >-
Drive time to your next appointment ({{summary}}) is
{{waze_duration}} minutes. Depart by {{departure_time_friendly}}
for arrival by {{start_time_friendly}}.
title: Drive Time Alert - {{ repeat.item.summary }}
- action: input_text.set_value
metadata: {}
data:
value: "{{ thisEventId }}"
target:
entity_id: input_text.last_notified_event_id
mode: single
Leave a Reply