Template entity: call + process REST API (e.g. reverse geocoding based on device_tracker lat+lon)?

Would like to add reverse geocoding information for a device_tracker.
Have the feeling the right approach is using a template entity.

I could use a reverse geocoding API, e.g. locationIQ.

https://locationiq.com/v1/reverse.php?key=my_api_key&lat=48.86115&lon= 2.33803&format=json

How do I trigger calling this endpoint in my template? And how do I store e.g. the display_name property as my status and the other JSON data as attributes?

Here’s my approach so far:

template:
  - sensor:
      - name: "my location"
        state: >
{% 
  set url = "https://locationiq.com/v1/reverse.php?key=my_api_key&lat="
  + state_attr('device_tracker.location','latitude') | string
  + ","
  + state_attr('device_tracker.location','longitude') | string
  + "&format=json"
%}

# do something with the {{ url }}

have a look at rest sensor, i did the same, but with another tracker

look this thread:

What is the end result you are expecting? What is sensor.my_loaction supposed to hold?

Hi! Expecting sensor.my_location to hold the value of JSON attribute display_name as the status and as the attributes some/all of the API attributes.

Thanks for your example. That one is based on a fixed scan interval. Can I instead trigger it every time the lat/lon attributes of the device_tracker.location change (=when the entity device_tracker.location is updated)?

What do you expect sensor.my_location to be?..

@Hellis81 I guess I don’t understand your question which I tried to explain in the original post and in reply to your original question. I’ll try to explain in more detail.

For my other car I have set a custom sensor that contains the geocoded address label (coming from another entity):
sensor.location_car1 contains status e.g. “my address”.

sensor:
  - platform: template
    sensors:
      location_car1:
        friendly_name: "location car 1"
        value_template: "{{ state_attr('device_tracker.location_car1','display_name') }}"

Trying to achieve something similar for my car which only returns lat+lon (which means I need to perform a reverse geocoding before I can set the sensor state).

My current implementation

  • helper: input_text.location_car which contains the reverse geocoded address
  • (empty) script: reverse_geocode (with service_data: lat+lon using the state attributes from the device_tracker)
  • Node-RED flow: listen for event service reverse_geocode, call the reverse geocode endpoint, set the input_text.location_car helper
  • automation: called when the latitude attribute of the device tracker changes, calls the (empty) script which triggers the Node-RED flow

But this feels like using too many steps, plus I prefer using a real sensor and not a helper.

The automation:

alias: reverse geocode latlon
description: calls script (caught by Node-RED) which sets input_text.location_car
trigger:
  - platform: state
    entity_id: device_tracker.location
    attribute: latitude
condition: []
action:
  - service: script.reverse_geocode
    data:
      lat: "{{ state_attr('device_tracker.location','latitude') }}"
      lon: "{{ state_attr('device_tracker.location','longitude') }}"
mode: single

You did not include this in the original question.
Had you done that it would have been obvious what you want.

But to say reverse geocoding and display_name doesn’t say much does it?

Just use the custom component places.

I thought I did in the original post when I said I wanted to call a REST endpoint and then:

how do I store e.g. the display_name property as my status and the other JSON data as attributes?

And in the reply to your question:

Expecting sensor.my_location to hold the value of JSON attribute display_name as the status and as the attributes some/all of the API attributes

Thanks for the Places custom component suggestion. Will take a look.

Still interested in the recommended generic approach for the flow I described:

  • state for an entity changes
  • trigger a REST call
  • from the result store an attribute as the state for a new sensor (+ store -some of the- attributes)

So you expect us to read what the endpoint returns instead of you just telling us?

Again, why should I have to read what the API does?
In my opinion a proper question should include what the API returns so that we can help you without reading through an API documentation and/or create an account for said API.

Use a state automation with noting filled in to or from.
Action homeassistant.update_entity (or similar) on the rest API sensor.

This depends on what the API returns. There is no generic answer as far as I know

@Hellis81 let’s not argue, we’re just having trouble understanding each other.

The custom component Places is indeed useful,
and I think I now understand your 2nd suggestion (which expands on @pergola.fabio 's original response):

  • REST sensor: calls the reverse geocode endpoint, using the lat+lon from device_tracker as parameters (note: default scan_interval is 30 seconds, can use large one e.g. 86400 because we only want to run it triggered by the automation)
  • automation: if state (or attribute) of our device_tracker changes then run service homeassistant.update_entity for the REST sensor

I ended up using that approach, using positionstack as the reverse geocoding provider.
If someone else wants to do the same thing, here is my complete (working) result.
In short: device_tracker.location contains the lat+lon we’re interested in, and sensor.location_car is the REST sensor that is set to the reverse geocoded address label.

sensor location_car:
  - platform: rest
    name: location car
    value_template: "{{ value_json.data[0].label }}"
    json_attributes_path: "$.data[0]"
    json_attributes:
      - label
      - type
      - confidence
      - distance
      - name
      - street
      - number
      - postal_code
      - region
      - region_code
      - locality
      - neighbourhood
      - country
    verify_ssl: false
    scan_interval: 86400 # 1 day -- preferred: home_assistant.update_entity
    resource_template: >
      {{ 
        "http://api.positionstack.com/v1/reverse?access_key=MY_API_KEY&limit=1&query="
        + state_attr('device_tracker.location','latitude') | string
        + ','
        + state_attr('device_tracker.location','longitude') | string
      }}

and my automation:

alias: reverse geocode latlon car
trigger:
  - platform: state
    entity_id: device_tracker.location
    attribute: latitude
condition: []
action:
  - service: homeassistant.update_entity
    target:
      entity_id: sensor.location_car
mode: single