AirTag "integration" (user friendly + device tracker)

Hi @TiToTB as anticipated via chat I played a little bit with device_tracker.see to create this device class instead of sensor class to share lat and long.

This is what I achieved so far.

  1. the rest sensor is more or less the same that you already shared. I only added some condition to avoid mismatches (for example when geoapify picks up the correct street but in a different town:
sensor:
  - platform: rest
    name: airtag_herbie
    value_template: "{{ value_json.results[0].formatted }}"
    json_attributes_path: "$.results[0]"
    json_attributes:
      - lon
      - lat
      - district
      - city
      - postcode
      - street
      - housenumber
      - state
      - country
      - country_code
    verify_ssl: true
    scan_interval: 900 # every 15 min
    resource_template: >
      {% set address = states('input_text.airtag').split('Herbie')[1].split('•')[0] %}
      {% set home = "Via xxxxxxxxxxxxxxxxxxxxxxxxxxxx Italy" %}
      {% set work = "Via xxxxxxxxxxxxxxxxxxxxxxxxxxxx Italy" %}
      {% if "Casa" in address %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + home | urlencode
          + "&apiKey=xxxxxxx&format=json"
        }}
      {% elif "Via xxxxxxx" in address %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + work | urlencode
          + "&apiKey=xxxxxxx&format=json"
        }}
      {% elif "Via xxxxxxx" in address %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + work | urlencode
          + "&apiKey=xxxxxxx&format=json"
        }}
      {% else %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + address | urlencode
          + "&apiKey=xxxxxxx&format=json"
        }}
      {% endif %}

the only missing piece is the following: when airtag is not recently updated in Find My I see a message “last update: xx:xx”. Going inside the device details address is colored red, maybe because Apple want to tell us that it may be not so reliable. I’m thinking how to solve this…there’s a way to allow input_text to exclude text with that string?

Below the device tracker automation to create new entitity:

automation:
  - alias: Set Herbie Location da Airtag
    trigger:
      - platform: state
        entity_id: sensor.airtag_herbie
    action:
      - delay:
          hours: 0
          minutes: 0
          seconds: 5
          milliseconds: 0
      - service: device_tracker.see
        data:
          dev_id: airtag_herbie
          # location_name: "{{ states('sensor.airtag_zaino_tigrotto') }}"
          gps:
          - "{{ state_attr('sensor.airtag_herbie', 'lat') }}"
          - "{{ state_attr('sensor.airtag_herbie', 'lon') }}"
    mode: single

another piece that I would like to share is that rest sensor (in my config) il loaded before input_text at HA restart so it happens that sensor fail and all is broken.

As a workaround I wrote this:

  - alias: Reload REST integration after restart
    trigger:
      - platform: homeassistant
        event: start
        id: HA restart
    condition: []
    action:
      # - delay:
      #     hours: 0
      #     minutes: 5
      #     seconds: 0
      #     milliseconds: 0
      # - service: notify.mobile_app_iphone_di_marco
      #   data:
      #     message: Dove sono gli AirTag?
      #     data:
      #       shortcut:
      #         name: AirTag to HA
      - delay:
          hours: 0
          minutes: 5
          seconds: 0
          milliseconds: 0
      - service: rest.reload
    mode: single

as you can see I left commented the part when asking manual updated at boot as well, maybe is a bit overkill.

I also created this for test purpose to avoid waiting 15min during developement:

  - alias: Reload REST integration after shortcut refresh
    trigger:
      - platform: state
        entity_id: input_text.airtag
    action:
      - delay:
          hours: 0
          minutes: 1
          seconds: 0
          milliseconds: 0
      - service: rest.reload

Any feedback is welcome and appreciated :slight_smile:

1 Like

This does not return anything in isolation. I tested, however, the whole template and this was the result:

https://api.geoapify.com/v1/geocode/search?text=%0AHjemme%20&apiKey=MYAPI&format=json

When following the url, it goes to the coordinated address which seems to be a place 5 km away that is called “Hjemme”. “Hjemme” is also the location of the tags in my language (meaning Home). Any ideas how to solve this? :smiley:

I guess the url should be looking for the value specified as the home = “address” rather than “Hjemme”?

 {% set address = states('input_text.airtag').split('Frankie')[1].split('•')[0] %}
      {% if address == "Hjemme" %}
        {% set home = "MYADDRESS" %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + home | urlencode
          + "&apiKey=MYAPI&format=json"
        }}
      {% else %}
        {{
          "https://api.geoapify.com/v1/geocode/search?text="
          + address | urlencode
          + "&apiKey=MYAPI&format=json"
        }}
      {% endif %}

Not sure what I am doing wrong. The template seems to insert the home definition into the url, but as you can see it just searched for “Hjemme”

Frankie Hjemme • Nu Test Hjemme • Nu Identificer fundet genstand Med dig Personer Enheder

This is the state of input_text.airtag, so not sure why

{% set address = states('input_text.airtag').split('Frankie')[1].split('•')[0] %}

is showing empty space. Should it not show Hjemme?

Hi guys,

I am trying to migrate to the new version including the GPS coordinates, but I struggle.
I don’t get the OCR’ed data into HA.
I am not sure why it worked in the past but basically the OCR struggles with “Objekte” (German) which occurs twice in the screenshot.
The first one on top of the various objects (which I am after) is captured when I use Obiekte, the second one (tab at bottom of the screen) is captured using Objekte.

When I swipe the screen upwards to see all my objects (5 in total), the string is not transferred to HA - it is obviously longer than 255 characters.

Questions:
Is this due to the limited 255 characters?
Are there maybe special characters preventing the string to be transferred?

EDIT:
I just recognized that I can set the string length to a higher value :smiley:
I just thought 255 is “hardcoded” :innocent:

EDIT II:
It does not seem to work if I swipe up the screen in general.
I am not sure why yet, but will try to find out.
Currently I am still having Problems transferring the info from the input_text to the single entities.

Any chance you can share what you see when testing this?

{% set address = states('input_text.airtag').split('ITEM')[1].split('•')[0] %}```

Hi,

thanks for the solution.

I get the following error in the log. Do you have an idea for a solution?

Template variable error: list object has no element 1 when rendering '{% set address = states('input_text.airtag').split('MYITEM')[1].split('•')[0] %} {% if address == "Privat" %} {% set home = "MYFULLADRESS" %} {{ "https://api.geoapify.com/v1/geocode/search?text=" + home | urlencode + "&apiKey=MYAPIKEY&format=json" }} {% else %} {{ "https://api.geoapify.com/v1/geocode/search?text=" + address | urlencode + "&apiKey=MYAPIKEY&format=json" }} {% endif %}'

My Helper:

Ok so I found the bug. Apparently the resulting url from the template includes a newline character “%0A”, which can be fixed by adding the “trim” filter:

So changing:

to:

{% set address = states('input_text.airtag').split('Frankie')[1].split('•')[0] | trim %}

worked for me.

Next up, trying to debug the lovelace card as it doesn’t show on the map :sweat_smile:

Hi guys!

I am glad you are playing with this :slight_smile:

Finally i took my time to improved the code with your suggestions:

  • I added to the guide how to avoid miss matches with some locations.
  • I am still working with the device tracker, in order to make a blueprint. But today i don’t have an iphone with me.

@Jokerigno, you can easily exclude “last update: xx:xx” in the input_text value by using this filter at the end.

| replace(‘last update: xx:xx’,‘’)

So it would be like this:

{% set address = states(‘input_text.airtag’).split(‘Herbie’)[1].split(‘•’)[0] | replace(‘last update: xx:xx’,‘’) %}

About the restart issue, i think you found a good workaround. Anyway, if you update the airtag info every, i.e., 15 min, is this really a problem?

Sounds great with the device tracker! For now, I have a person (dog) entity updating via the automation below, which seems to work so far:

alias: Update Frankie Device Tracker
trigger:
- platform: state
  entity_id: sensor.airtag_frankie_device_tracker
- event: start
  platform: homeassistant
action:
  - service: device_tracker.see
    data_template:
      dev_id: frankie
      location_name: >
        {% if "Hjemme" in states('sensor.airtag_frankie_device_tracker') %}
          home
        {% else %}
          not_home
        {% endif %}

I just updated the guide, so you can create de ‘device tracker’ entity and update coordinates, through a blueprint (easy to config in few seconds).

Let me know how it works!

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

1 Like

yes but I don’t know if it solve the issue that is not showing the address is last update is “old”

The ‘last update: xx:xx’ should be replaced with previous state but in order to do so you should keep it in a variable or something similar…

It works alright, but also seems to be the same solution as my automation with device_tracker.see

How would I add multiple airtags to this?

Hi everyone,
I am struggling with this screen while swiped upwards.
I would like to get rid of the end of this text
“Gefundenes Objekt identifizieren” („Identify found object”)


I added a new routine to shortcuts, but I can still find the phrase in the printed result.

I am not familiar with shortcuts and tried it this way:

The first one is capturing the screen
The next one is extracting the text from the word “Objekte”.
Then the second part of the separate a text is used
Then my part: Separate the text on the phrase „Gefundenes Objekt„
And from this result, I take the first part (before the found phrase).

But the returned string still contains “Gefundenes Objekt”

I wonder, if the new lines here are also a problem like mentioned above by @BA8870
(Red mark)
Because the other items are also sometimes not read correctly.

Any help is greatly appreciated

great work !

do you know if we can track the AirTag battery level in HA ? I found the batteries just die without warning.

Sure, you can create an input text helper in order to keep the last value (only if this is not ‘old’ or similar).

However, again, i wonder how it helps to find your items? :sweat_smile: I mean, if you want to track their location you should update them, right?

Yes it is the same, i just make it easier to set it up for less advanced users :sweat_smile:

Also, you can use the blueprint to set as many AirTag as you want :blush:

If you just want to delete that part, you can easily exclude “Gefundenes Objekt identifizieren” in the input_text value by using this filter at the end.

| replace(‘Gefundenes Objekt identifizieren’,‘’)

So it would be like this:

{% set address = states(‘input_text.airtag’).split(‘Herbie’)[1].split(‘•’)[0] | replace(‘Gefundenes Objekt identifizieren’,‘’) %}

because older input text can have details that if are “old” will be removed from new updates.

Tito I’m still playing a little bit and found something intresting. Have a look at location bias

I’m making some test just to see if geoapify can pick closest results to increase reliability.

2 Likes

That looks very promising :smiley:

Thank you for this suggestion.

Actually, I would like to remove this phrase and everything from there.
I do this now by these two guys:

I wonder though if it’s better to use text in the input_text.set_value or dictionary, because the first does not have \n but a REAL newline.
So I wonder if there is a difference.