Garmin LiveTrack tracking package 🗺️

I want to share a package file for integrate information from a Garmin LiveTrack event.

I use the IMAP sensor get the url automatic, named sensor.homeassistant below. But it’s also possible to share the url into the input field.

I had to create a empty json file in www folder to have a document to point to when HASS starts to reduce errors in log. Change to your url.

# /www/none_garmin.json
{"trackPoints":[]}

garmin_livetrack.yaml package file

# Garmin Livetrack
# garmin_livetrack.yaml

input_text:
  garmin_livetrack_link:
    name: Garmin LiveTrack link
    max: 250
    icon: mdi:link
    initial: ""

sensor:
  - platform: rest
    resource_template: "{{ state_attr('sensor.garmin_livetrack_id','data_link') if state_attr('sensor.garmin_livetrack_id','data_link') != None else 'https://homeassistant-domain/local/none_garmin.json'}}"
# CHANGE url above,!
    
    name: Garmin LiveTrack
    value_template: "{{ value_json.trackPoints[-1].dateTime if 'trackPoints' in value_json and (value_json.trackPoints | length) > 0 }}"
    scan_interval: 2592000 #30d
    timeout: 10
    headers:
      Content-Type: application/json
    json_attributes_path: "$.trackPoints[-1:]"
    json_attributes: 
    - dateTime
    - position
    - fixType
    - altitude
    - fitnessPointData
    - speed

template:
- trigger:
  - platform: state
    entity_id: input_text.garmin_livetrack_link
  - platform: state
    entity_id: sensor.garmin_livetrack_link_from_email 
  sensor:
  - name: Garmin Livetrack id
    state: >-
      {%- if "livetrack.garmin.com" in trigger.to_state.state -%}
      {{- (trigger.to_state.state | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-]+)/token', ignorecase=True))[0] -}}
      {%- elif trigger.entity_id == "sensor.garmin_livetrack_link_from_email" and trigger.to_state.state != "" -%}
      {{- trigger.to_state.state -}}
      {%- endif -%}
    attributes:
      link: >-
        https://livetrack.garmin.com/session/
        {%- if "livetrack.garmin.com" in trigger.to_state.state -%}
        {{- (trigger.to_state.state | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-]+/token/+[a-z0-9-]+)', ignorecase=True))[0] -}}
        {%- elif trigger.entity_id == "sensor.garmin_livetrack_link_from_email" and trigger.to_state.state != "" -%}
        {{- trigger.to_state.attributes.token -}}
        {%- endif -%}
      data_link: >-
        https://livetrack.garmin.com/services/session/
        {%- if "livetrack.garmin.com" in trigger.to_state.state -%}
        {{- (trigger.to_state.state | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-]+)/token', ignorecase=True))[0] -}}
        {%- elif trigger.entity_id == "sensor.garmin_livetrack_link_from_email" and trigger.to_state.state != "" -%}
        {{- trigger.to_state.state -}}
        {%- endif -%}/trackpoints
    icon: mdi:map

# Sensor to get link from email with integration: https://www.home-assistant.io/integrations/imap_email_content/
- sensor:
  - name: Garmin LiveTrack link from email
    state: >-
      {{ (state_attr('sensor.homeassistant','body') | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-\n\r=]+)/token', ignorecase=True))[0] | replace('\n','') | replace('\r','') | replace('=','')
         if 'body' in states.sensor.homeassistant.attributes }}
    attributes:
      token: >-
        {{ ((state_attr('sensor.homeassistant','body') | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-\n\r=]+/token/+[a-z0-9-\n\r=][^"]+)', ignorecase=True))[0]) | replace('\n','') | replace('\r','') | replace('=','')
         if 'body' in states.sensor.homeassistant.attributes }}
       

- binary_sensor:
  - name: Garmin Livetrack
    state: "{{ is_state_attr('automation.garmin_livetrack', 'current',1) }}"
    attributes:
      latitude: "{{ states.sensor.garmin_livetrack.attributes.position.lat if 'position' in states.sensor.garmin_livetrack.attributes }}"
      longitude: "{{ states.sensor.garmin_livetrack.attributes.position.lon if 'position' in states.sensor.garmin_livetrack.attributes }}"
      start: "{{ states.sensor.garmin_livetrack.attributes.fitnessPointData.activityCreatedTime if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      datetime: "{{ states.sensor.garmin_livetrack.attributes.dateTime if 'dateTime' in states.sensor.garmin_livetrack.attributes }}"
      duration: "{{ timedelta(seconds=(states.sensor.garmin_livetrack.attributes.fitnessPointData.totalDurationSecs | float(0) ))[:-7] if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      activity: "{{ (states.sensor.garmin_livetrack.attributes.fitnessPointData.activityType if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes ) | lower }}"
      speed_ms: "{{ states.sensor.garmin_livetrack.attributes.speed if 'speed' in states.sensor.garmin_livetrack.attributes }}"
      speed: "{{ (states.sensor.garmin_livetrack.attributes.speed)*3.6 if 'speed' in states.sensor.garmin_livetrack.attributes }}"
      pace: "{{ 16.666666667/(states.sensor.garmin_livetrack.attributes.speed) if 'speed' in states.sensor.garmin_livetrack.attributes }}"
      altitude: "{{ states.sensor.garmin_livetrack.attributes.altitude if 'altitude' in states.sensor.garmin_livetrack.attributes }}"
      distance: "{{ (states.sensor.garmin_livetrack.attributes.fitnessPointData.distanceMeters | int(0) )/1000 | round(1) if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      heartbeats: "{{ states.sensor.garmin_livetrack.attributes.fitnessPointData.heartRateBeatsPerMin if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      watt: "{{ (states.sensor.garmin_livetrack.attributes.fitnessPointData.powerWatts if 'powerWatts' in states.sensor.garmin_livetrack.attributes.fitnessPointData) if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      event: "{{ states.sensor.garmin_livetrack.attributes.fitnessPointData.eventTypes if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes }}"
      status: "{{ (states.sensor.garmin_livetrack.attributes.fitnessPointData.pointStatus if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes ) | lower }}"

    
automation:
- alias: Garmin LiveTrack new link
  id: "garmin_livetrack"
  mode: restart
  trigger:
  - platform: state
    entity_id: sensor.garmin_livetrack_id
  condition:
    - condition: template
      value_template: "{{ trigger.to_state.state != '' }}"
    - condition: template
      value_template: "{{ trigger.to_state.state != 'unknown' }}"
    - condition: template
      value_template: '{{ trigger.from_state.state != trigger.to_state.state }}'
  action:
  - variables:
      update_min: 2
  - alias: "Notify start"
    service: notify.mobile_app_xxx
    data:
        title: "Garmin LiveTrack"
        message: "Start"
        data:
          group: Garmin
          tag: garmin_livetrack
          clickAction: "entityId:binary_sensor.garmin_livetrack"
          timeout: 180
          notification_icon: "mdi:run-fast"
          actions:
          - action: "URI"
            uri: "{{ state_attr('sensor.garmin_livetrack_id','link') }}"
            title: "Show Garmin livetrack"
  - repeat:
      until:
      - condition: or
        conditions:
        - condition: template
          value_template: "{{ (as_timestamp(states('sensor.garmin_livetrack')) | int(0) ) > 0 }}"
        - condition: template
          value_template: "{{ repeat.index >= 10 }}"
      sequence:
      - service: homeassistant.update_entity
        entity_id: sensor.garmin_livetrack
      - delay: "00:00:15"
  - alias: "Turn on automations with actions depending on Livetrack"
    service: automation.turn_on
    entity_id: 
    - automation.garmin_livetrack_kilometer
  - repeat:
      until:
      - condition: or
        conditions:
          - condition: template
            value_template: "{{ 'END' in states.sensor.garmin_livetrack.attributes.fitnessPointData.eventTypes if 'fitnessPointData' in states.sensor.garmin_livetrack.attributes else false }}"
          - condition: template
            value_template: "{{ as_timestamp(now())-int(as_timestamp(states('sensor.garmin_livetrack'),as_timestamp(now())) ) > 60*30 }}"
          - condition: template
            value_template: "{{ trigger.to_state.state != states('sensor.garmin_livetrack_id') }}"
          - condition: template
            value_template: "{{ repeat.index > (11*60/update_min) }}" # 11h * 60 min /2 min
      sequence:
      - service: homeassistant.update_entity
        entity_id: sensor.garmin_livetrack
      - delay:
          minutes: "{{ update_min }}"
      
  - alias: "Notify end"
    service: notify.mobile_app_xxx
    data:
        title: "Garmin Livetrack"
        message: |
          End!
          {{ state_attr('binary_sensor.garmin_livetrack','duration') }}
          {{ state_attr('binary_sensor.garmin_livetrack','distance') }}
          {{ state_attr('binary_sensor.garmin_livetrack','activity') }}
          {{ state_attr('binary_sensor.garmin_livetrack','event') }}
        data:
          group: Garmin
          tag: garmin_livetrack
          clickAction: "entityId:binary_sensor.garmin_livetrack"
          timeout: 300
          notification_icon: "mdi:stop-circle"
          actions:
          - action: "URI"
            uri: "{{ state_attr('sensor.garmin_livetrack_id','link') }}"
            title: "Show Garmin Livetrack"
  - service: automation.turn_off
    entity_id: 
    - automation.garmin_livetrack_kilometer

Good luck! 🏃‍♂:dash::japan::world_map:

1 Like

Wow! this project is great! I test it tomorrow. Thanks :wink:

I added the package, could you explain how to display the data in the dashboard? Thank you

You could lockup binary_sensor.garmin_livetrack in the map or put it in a dashboard map.
Or use the data to activate som automation.

1 Like

I have 2 warning:
Template variable warning: ‘value_json’ is undefined when rendering ‘{{ value_json.trackPoints[-1].dateTime if ‘trackPoints’ in value_json and (value_json.trackPoints | length) > 0 }}’

  • Template variable warning: ‘None’ has no attribute ‘attributes’ when rendering ‘{{ (state_attr(‘sensor.homeassistant’,‘body’) | regex_findall(find=‘https://livetrack.garmin.com/session/([a-z0-9-\n\r=]+)/token’, ignorecase=True))[0] | replace(’\n’,’’) | replace(’\r’,’’) | replace(’=’,’’) if ‘body’ in states.sensor.homeassistant.attributes }}’
  • Template variable warning: ‘None’ has no attribute ‘attributes’ when rendering ‘{{ ((state_attr(‘sensor.homeassistant’,‘body’) | regex_findall(find=‘Garmin Live Tracking - Powered by Garmin Connect™’, ignorecase=True))[0]) | replace(’\n’,’’) | replace(’\r’,’’) | replace(’=’,’’) if ‘body’ in states.sensor.homeassistant.attributes }}’

Do you use the IMAP sensor?
Otherwise you could remove the senor:

- sensor:
  - name: Garmin LiveTrack link from email
    state: >-
      {{ (state_attr('sensor.homeassistant','body') | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-\n\r=]+)/token', ignorecase=True))[0] | replace('\n','') | replace('\r','') | replace('=','')
         if 'body' in states.sensor.homeassistant.attributes }}
    attributes:
      token: >-
        {{ ((state_attr('sensor.homeassistant','body') | regex_findall(find='https://livetrack.garmin.com/session/([a-z0-9-\n\r=]+/token/+[a-z0-9-\n\r=][^"]+)', ignorecase=True))[0]) | replace('\n','') | replace('\r','') | replace('=','')
         if 'body' in states.sensor.homeassistant.attributes }}

Yes, I have IMAP sensor

Change sensor.homeassistant to the name of your sensor.

Nothing to do, in my case it doesn’t work.
It doesn’t fetch the link from the mail and it doesn’t show tracking, even if the imap sensor correctly shows the arrival of a new mail