Map Your Family and Send Travel Updates by Push Notifications

I created this because my wife and I have one car and I don’t like when she’s texting me to ask how far I am away when picking her up. So I created this using our device_trackers into a Google map, with zoom and center controls and an ability to subscribe to traffic updates sending push notifications of either locations and the ETA with cool google street view pictures. I’ve tested it over the last few days and works surprisingly well. The push notifications send every 5 minutes until you’ve reached the same location and then will turn off.

IMB_FD9bmm

Pre-Requisites

  • A Google Account using their API for Street View, Static Maps, and Travel times. It may be a good idea to set a budget since they will bill you based on your usage. I just set mine at $3 a month just in case. :open_mouth:
  • Some sort of device_tracker from the phone (I use the iOS app here)
  • Some sort of Notify (Again, using iOS)
  • Optional: an image hosting site. I use www.postimg.org. For best results, use a 32x32 pixel png file. Also if you want the rounded marker type look, you will need to create the png to look like it separately. Google just uses whatever image you are referencing and adds to the static image of the map.

Automations:

#################################################################################################
#                           TRAVEL TIME PUSH NOTIFICATIONS                                      #
#################################################################################################

  - alias: 'Push Travel Time From Jeremy to Anja'
    initial_state: on
    trigger:
      - platform: time
        minutes: '/5'
        seconds: '0'
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ is_state("input_boolean.push_notification_distance_jeremy_to_anja", "on") }}'
        - condition: numeric_state
          entity_id: sensor.google_travel_time_jeremy_to_anja
          above: 1
    action:
      - service: notify.all_anja
        data:
          title: "Jeremy is {{states.sensor.google_travel_time_jeremy_to_anja.state}} minutes away"
          message: "Approximate ETA based on current traffic conditions and last known location"
          data:
            push:
              badge: 1
              category: camera
            entity_id: camera.street_view_jeremy_gps

  - alias: 'Push Travel Time From Anja to Jeremy'
    initial_state: on
    trigger:
      - platform: time
        minutes: '/5'
        seconds: '0'
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ is_state("input_boolean.push_notification_distance_anja_to_jeremy", "on") }}'
        - condition: numeric_state
          entity_id: sensor.google_travel_time_anja_to_jeremy
          above: 1
    action:
      - service: notify.all_jeremy
        data:
          title: "Anja is {{states.sensor.google_travel_time_anja_to_jeremy.state}} minutes away"
          message: "Approximate ETA based on current traffic conditions and last known location"
          data:
            push:
              badge: 1
              category: camera
            entity_id: camera.street_view_anja_gps

  - alias: 'Jeremy Has Arrived'
    initial_state: on
    trigger:
      - platform: numeric_state
        entity_id: sensor.google_travel_time_jeremy_to_anja
        below: 2
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ is_state("input_boolean.push_notification_distance_jeremy_to_anja", "on") }}'
    action:
      - service: notify.all_anja
        data:
          title: "Jeremy has arrived!"
          message: "Jeremy is here."
          data:
            push:
              badge: 1
              category: camera
            entity_id: camera.street_view_jeremy_gps
      - service: input_boolean.turn_off
        entity_id: input_boolean.push_notification_distance_jeremy_to_anja

  - alias: 'Anja Has Arrived'
    initial_state: on
    trigger:
      - platform: numeric_state
        entity_id: sensor.google_travel_time_anja_to_jeremy
        below: 2
    condition:
      condition: and
      conditions:
        - condition: template
          value_template: '{{ is_state("input_boolean.push_notification_distance_anja_to_jeremy", "on") }}'
    action:
      - service: notify.all_jeremy
        data:
          title: "Anja has arrived"
          message: "Anja is here."
          data:
            push:
              badge: 1
              category: camera
            entity_id: camera.street_view_anja_gps
      - service: input_boolean.turn_off
        entity_id: input_boolean.push_notification_distance_anja_to_jeremy

GROUPS:

#################################################################################################
#                           MAPS                                                                #
#################################################################################################

  map_view:
    view: yes
    name: Location
    entities:
      - group.map
      - group.location_map
      - group.device_tracker_street_view
      - group.send_push_updates
  map:
    view: no
    entities:
      - camera.location_map

  device_tracker_street_view:
    view: no
    name: "Street Views"
    entities:
      - camera.street_view_jeremy_gps
      - camera.street_view_anja_gps

  send_push_updates:
    view: no
    name: "Travel Updates"
    entities:
      - input_boolean.push_notification_distance_jeremy_to_anja
      - input_boolean.push_notification_distance_anja_to_jeremy

  location_map:
    view: no
    name: "Map Controls"
    entities:
      - sensor.google_travel_time_jeremy_to_anja
      - sensor.google_travel_time_anja_to_jeremy
      - input_number.map_zoom
      - input_select.center_map_on

INPUT BOOLEANS

  push_notification_distance_jeremy_to_anja:
    name: Send Notifications - To Anja
    icon: mdi:message-alert
  push_notification_distance_anja_to_jeremy:
    name: Send Notifications - To Jeremy
    icon: mdi:message-alert

INPUT SELECT

  center_map_on:
    name: Center Map On
    icon: mdi:account-multiple
    options:
      - Jeremy
      - Anja

INPUT NUMBER

  map_zoom:
    name: Zoom Map
    icon: mdi:magnify
    min: 1
    max: 21
    step: 1

TEMPLATE SENSORS

  center_map_on:
    value_template: >-
      {% set center = states.input_select.center_map_on.state %}
      {% if center == "Jeremy"%}
        {% set lat = states.device_tracker.jeremys_iphone.attributes.latitude %}
        {% set long = states.device_tracker.jeremys_iphone.attributes.longitude %}
      {% elif center == "Anja"%}
        {% set lat = states.device_tracker.anjas_iphone.attributes.latitude %}
        {% set long = states.device_tracker.anjas_iphone.attributes.longitude %}
      {% else %}
        {% set lat = states.device_tracker.jeremys_iphone.attributes.latitude %}
        {% set long = states.device_tracker.jeremys_iphone.attributes.longitude %}
      {% endif %}
      {{ [lat,long]|join(',') }}

SENSORS

  - platform: google_travel_time
    api_key: YOUR_GOOGLE_API_KEY
    name: google_travel_time_anja_to_jeremy
    origin: device_tracker.anjas_iphone
    destination: device_tracker.jeremys_iphone
  - platform: google_travel_time
    api_key: YOUR_GOOGLE_API_KEY
    name: google_travel_time_jeremy_to_anja
    origin: device_tracker.jeremys_iphone
    destination: device_tracker.anjas_iphone

CAMERAS (You’ll need to replace with your hosted icon images and your Google API Key)

- platform: generic
  name: street_view_anja_gps
  still_image_url: https://maps.googleapis.com/maps/api/streetview?size=600x300&location={{states.device_tracker.anjas_iphone.attributes.latitude}},{{states.device_tracker.anjas_iphone.attributes.longitude}}&key=YOUR_GOOGLE_API_KEY
  limit_refetch_to_url_change: true
- platform: generic
  name: street_view_jeremy_gps
  still_image_url: https://maps.googleapis.com/maps/api/streetview?size=600x300&location={{states.device_tracker.jeremys_iphone.attributes.latitude}},{{states.device_tracker.jeremys_iphone.attributes.longitude}}&key=YOUR_GOOGLE_API_KEY
  limit_refetch_to_url_change: true
- platform: generic
  name: location_map
  still_image_url: https://maps.googleapis.com/maps/api/staticmap?center={{states.sensor.center_map_on.state}}&zoom={{states.input_number.map_zoom.state|int}}&size=600x300&maptype=roadmap&markers=icon:YOUR_FIRST_IMAGE_URL|{{states.device_tracker.jeremys_iphone.attributes.latitude}},{{states.device_tracker.jeremys_iphone.attributes.longitude}}&markers=icon:YOUR_SECOND_IMAGE_URL|{{states.device_tracker.anjas_iphone.attributes.latitude}},{{states.device_tracker.anjas_iphone.attributes.longitude}}&key=YOUR_GOOGLE_API_KEY
  limit_refetch_to_url_change: true
30 Likes

Wow! Very nice project… I think I’ll give it a try

this is amazing =) I’ve used your idea for the Location Map control.

I have a question though, what kind of file format do you need for the marker picture? Just now i’m using a .jpg and my url is xxx.duckdns.org/local/xxx.jpg

i can open the url fine and see the picture in my browser, but it doesnt show on the marker.

@Lentron I use png but jpg should work as well. I think the issue may be more the size of the image. I think it has to be under 32x32 pixels.

So, I was messing with this and used 64x64 png images, and they work, but they are big on the maps.

i changed the pictures to .png, and now they do show up on the map.

1 problem though: they aren’t hosted in a marker, they are square pictures instead.

i’m using the format as in the exampke code: markers=icon:URL.png

@Lentron

Yes correct, they will be square pictures. I edited mine and made them look like they are embedded into a marker. You’ll have to do that manually.

@nordlead2005 yeah I think the google API docs said to use 32x32 just to appear the right size. Forgot to mention that above. I will edit the first post.

thankyou =) i’ve got it right. this is a great example, i’ve seen many posts on the forum asking how to embed several markers, hopefully they’ll all find this post

1 Like

@Lentron Awesome. Glad it’s working for you!

I really like what you did and since I just recently re-enabled GPS tracking I used what you had as a base. I made a couple tweaks though.

  • I added “Average” to the center map option and set it as my default. I like this over centering on an individual person as then less of the map is wasted showing maps on the far side of the individual.
  • I defaulted the zoom to 4 and added a +6 offset (in camera template) and shrunk the range (new range sent to google is 7-18). 1 is too far out, 7 is what I would consider the max useful zoom out, 10 is pretty good as a default, and 18 shows less than a few houses so you don’t need more zoom than that.
  • I made a custom component for the travel time component and changed the update interval to 2 minutes. You get 2500 requests/day and something like 100/minute for that specific API and with only a few users you can query it significantly faster and not hit the limit. I did this so I could get a smaller window when I declare the other person arrived.
  • I trigger the notifications when the travel time updates rather than an on independent timer. This allows me to combine my notification logic and use templates/functions to determine which message to send.

In the future I may have it automatically add the “pessimistic” flag to the time estimation if the weather is bad. Currently you can’t do that without creating new sensors, and since I want to update the update interval I may just make it happen and submit it for a future build. Last night it said 24 minutes and it probably took me closer to 45 so it seems like it is worth looking at.

2 Likes

@nordlead2005

Awesome! Yeah I agree it would be nice to have the ability to change both the update interval and the type of request (best_guess vs pessimistic). If we could somehow get this templated, maybe it could be dynamic? When the input_boolean to send updates is on, the update interval is more frequent and goes back to the regular state when off? And same for best_guess vs pessimistic so the user can select which method they prefer by way of an input_select??

Thanks for your ideas!!

So, it turns out that there are no sensors with services. I have it most of the way implemented (traffic model change), but I’m wondering if it is some kind of HA rule where sensors don’t have services and I’ll get push back when I submit it. We’ll see what happens.

I don’t know if you can change the update rate after the sensor is setup. I’ve only modded a handful of components and never changed that after startup. I’ll play with it later and see if it is possible.

2 Likes

I added a configuration file field for setting the update_interval, and I added 2 services. The first changes the traffic model, and the second allows you to add restrictions (avoid highways, tolls, ferries, etc…). So, if you were setting up multiple sensors to track the same person with different parameters, you can now just use 1 sensor and switch the query parameters.

I think this will make it into 0.63, but it hasn’t been merged yet.

1 Like

@nordlead2005 thanks again! Looking forward to trying this out!

Please kindly advice. After trying to get this done yesterday. I have some questions to ask as I couldn’t get the map of the street view to show up on both device trackers and also from the static map only show one device although I have choose another device from input select. I’m sorry that I didn’t capture the picture to make it clearer to see.

  1. I have 2 device trackers to be track and show.
  2. I have enable google travel time, street view, and static map from google console which have api key for each api enable and for each device. That means I have 3 api keys for each device. Total 6 api keys.
  3. I have change device_tracker id and name to match what I have from the sharing given aboved.

Configuration checked OK. After restart HA.

  1. The camera part for location map show only one device which this device use it own api key. Although I choose another device from input select, no another device show up. So I check at the setting of the location map again why only display one device.

    • platform: generic
      name: location_map
      still_image_url: https://maps.googleapis.com/maps/api/staticmap?center={{states.sensor.center_map_on.state}}&zoom={{states.input_number.map_zoom.state|int}}&size=600x300&maptype=roadmap&markers=icon:YOUR_FIRST_IMAGE_URL|{{states.device_tracker.jeremys_iphone.attributes.latitude}},{{states.device_tracker.jeremys_iphone.attributes.longitude}}&markers=icon:YOUR_SECOND_IMAGE_URL|{{states.device_tracker.anjas_iphone.attributes.latitude}},{{states.device_tracker.anjas_iphone.attributes.longitude}}&key=YOUR_GOOGLE_API_KEY <=== this asking for 2 device tracker but have only 1 api key
      limit_refetch_to_url_change: true
  2. street view. I cannot get both to show on frontend. There are 2 display from street view but no map and pictures at all.

@Sunonline First off, you only need 1 API key. The API key is for fetching the URL not how many devices you’re plotting on the map.
I’ll need to see your config so I can see what the issue is? Leave out your API key though when you post.

1 Like

Thank you for your reply. I will post my config again this evening.
Regarding the api key. Both devices come from different google account. So if I put only 1 api key that allow only one device. So how to get or manage to use only 1 api key for 2 devices with different google account.

This setup has nothing to do really with google accounts. You need an API key so you can make calls to google travel time & maps, but I could put any set of lat/lon points in those calls.

I have the api key. As I said the api key I have is from 1 device / 1 api. How to use 1 api key and able to display both devices. Is there any setting needed from google console, please guide me to this.

The api key for travel time I have work fine (I have this work before adding street view and static map api).

The api key for street view is generate from individual google account console, and from setting camera platform, I can put it own device api key in (however, no map of street view display on frontend).

The api key for static map is generate from individual google account console, and from setting camera platform, I have put only 1 api key from 1 device (the png) which can display static map and the device that have api key match in, I have choose another device from input select, this don’t show another device (the png).