AirTag "integration" (user friendly + device tracker)

thanks for that simplier test, it make the works whitout the space and the \n

resource_template: >
    {% set address = states('input_text.airtag').split('eze')[1].split('•')[0] %}
    {% if "Domicile" in address %}
    {% set home = "251 hugues-pommier, boucherville" %}

tested it in developement tool and this works but was also working with the /n and the space in a non fashion way.

the .strip().lower() %} dosn’nt work, return list object has no element 1

but i do some testing and it look like my problem is with the json attribute path.
I set the return from geoapify in the value_json to test it, and does not seem to work

- platform: rest
  name: airtag_cle_eze_geo
   {% set value_json = {
   "results":[
      {
         "country_code":"ca",
         "street":"Rue Hugues-Pommier",
         "country":"Canada",
         "county":"Longueuil",
         "state":"Quebec",
         "city":"Boucherville",
         "state_code":"QC",
         "lon":-73.455478,
         "lat":45.590507,
         "result_type":"street",
         "formatted":"Rue Hugues-Pommier, Boucherville, QC, Canada",
         "address_line1":"Rue Hugues-Pommier",
         "address_line2":"Boucherville, QC, Canada",
         "timezone":{
            "name":"America/Toronto",
            "offset_STD":"-05:00",
            "offset_STD_seconds":-18000,
            "offset_DST":"-04:00",
            "offset_DST_seconds":-14400,
            "abbreviation_STD":"EST",
            "abbreviation_DST":"EDT",
            }
            }
            ]
            }%}

  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: 10 # every 15 min
  force_update: true

the dev tool give me that return:

value_template: “Rue Hugues-Pommier, Boucherville, QC, Canada”
json_attributes_path: “$.results[0]”
json_attributes:
- lon
- lat
- district
- city
- postcode
- street
- housenumber
- state
- country
- country_code
verify_ssl: true
scan_interval: 10 # every 15 min
force_update: true

resource_template: >

  https://api.geoapify.com/v1/geocode/search?text=251%20hugues-pommier%2C%20boucherville&apiKey=APIKEY&format=json

I don’t see any error in log but maybe find an hint. Now I’m handling 4 AirTags and in my idea the text is longer than 255 and so it is not imported in input_text and sensor and automation are no longer triggered.

There’s a way to split text before sending it to ha?

Maybe creating input_text.airtag1 input_text.airtag2 or something similar?

Since we are using ‘*’ to identify airtag text, yes you can modify the shortcut to split the data into two different helpers!

1 Like

Ok. I’ll search the web to learn how to do it . If you can point me to some learning content I’ll appreciate that. :grinning:

To be honest, this is the first time i use shortcuts since i am not Apple user :sweat_smile:

Anyway, i think it should be simple if you read the shortcut. Try to clone the shortcut pointing to different helpers, then play with the Index number after splitting text.

I have not run into the length issue, but it interested me enough to look into :). This thread points to some solutions: Splitting sensor text result into two new helper sensors - Configuration - Home Assistant Community (home-assistant.io)

I have this basically working well. One thing I did to improve the device tracker (to remove all the unknown results, whenever a “last seen” was happening), was to add a condition to the automation to have it only update if the status is “available”,

condition:
  - condition: state
    entity_id: !input 'airtag'
    attribute: status
    state: available

Also, at least with UK english last seen doesn’t include a : character, so I’ve changed the template to look for the work Last.

{% if "Last" in states('input_text.airtag').split('Car')[1].split('•')[0] %}

1 Like

I’m having some trouble implementing this. I’m very new to HAOS but have given it a go. I’m getting the error:
Triggers: extra keys not allowed @ data[‘action’]

known_devices.yaml

Milo:
  name: airtag_milo
  mac:
  icon: mdi:bag-personal-tag ## Replace this icon with the one that represents your item.
  picture: local/images/mochila.png ## Replace this path with the one to the image that represents your item.
  track: true

automations.yaml

- id: '1719610029203'
  alias: Set Milo Location da Airtag
  trigger:
  - platform: state
    entity_id: sensor.airtag_milo
    action:
      - delay:
        hours: 0
        minutes: 0
        seconds: 5
        milliseconds: 0
      - service: device_tracker.see
        data:
          dev_id: airtag_milo
          gps:
          - "{{ state_attr('sensor.airtag_milo', 'latitude') }}"
          - "{{ state_attr('sensor.airtag_milo', 'longitude') }}"
  mode: single

sensor.yaml

- platform: rest
  name: airtag_milo_geo
  value_template: "{{ value_json.results[0].formatted }}"
  json_attributes_path: "$.results[0]"
  json_attributes:
    - lon
    - lat
  verify_ssl: true
  scan_interval: 900 # every 15 min
  force_update: true
  resource_template: >
    {% set address = states('input_text.airtag').split('milo')[1].split('•')[0] %}
    {% if address == "Home" %}
      {% set home = "Home Address" %}
      {{
        "https://api.geoapify.com/v1/geocode/search?text="
        + home | urlencode
        + "&apiKey=KEYREMOVE&format=json"
      }}
    {% else %}
      {% set fix = address + "Foxton Beach, New Zealand" %}
      {{
        "https://api.geoapify.com/v1/geocode/search?text="
        + fix | urlencode
        + "&apiKey=KEYREMOVED&format=json"
      }}
    {% endif %}
- platform: template
  sensors:
    airtag_milo:
      friendly_name: "milo"
      value_template: >
        {% set home = "Signal Street`" %}
        {% if ":" in states('input_text.airtag').split('milo')[1].split('•')[0] %}
        {{ states('input_text.airtag').split('milo')[1].split('•')[0].split(',')[0] }}
        {% elif home in states('input_text.airtag').split('milo')[1].split('•')[0] %}Home
        {% else %}
        {{ states('sensor.airtag_milo_geo') }}
        {% endif %}
      attribute_templates:
        latitude: >
          {% if ":" in states('input_text.airtag').split('milo')[1].split('•')[0] %}null
          {% else %}{{ state_attr('sensor.airtag_milo_geo','lat') }}
          {% endif %}
        longitude: >
          {% if ":" in states('input_text.airtag').split('milo')[1].split('•')[0] %}null
          {% else %}{{ state_attr('sensor.airtag_milo_geo','lon') }}
          {% endif %}
        status: >
          {% if ":" in states('input_text.airtag').split('milo')[1].split('•')[0] %}unavailable
          {% else %}available
          {% endif %}
        last_update: "{{ as_timestamp(states.input_text.airtag.last_updated)|timestamp_custom ('%d/%m/%Y %H:%Mh') }}"
      icon_template: mdi:bag-personal

sensor.airtag_milo:

latitude: -40.xxx
longitude: 175.xxx
status: available
last_update: 02/07/2024 21:23h
icon: mdi:bag-personal
friendly_name: milo

What did I miss?

ok so basically I made it. I created the shortcut from scratch because somehow the variable names were still in spanish so were not working when I just added a pasted action.

The new shortcut sent data to input_text.airtag1 and 2 and then I have a new automation that merge (and clean up removing extra text) the 2 input_text to regular input_text.airtag that is used by the 2 sensors.

I also edited the automation by removing location_name to have home not home but also the zones names.

Now a (new) question: does the latest ios and ipad os allows to turn on the screen an unlocked device ?

You automation has an error, i have a similar automation for something else and it looks like this below, i think the indentation of action is not correct in your automation, it needs to go to the left:

alias: System - Create device cargps
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.gps365_lon
action:
  - service: device_tracker.see
    data:
      dev_id: cargps
      gps:
        - "{{ states('sensor.gps365_lat') }}"
        - "{{ states('sensor.gps365_lon') }}"

I doubt if ios can turn on the screen. I just have an iphone lying somewhere with the screen dimmed almost to the max for this to work. And then have it set in setting to never turn off the screen.

1 Like

I played around with various versions of checking the address, but I have the issue, that in German at home it’s “Privat” (even after removing my private address from my iphone).
Because there is a street in Hamburg hhich is called “Privatweg”, it always locks on this street instead of recognizing it as “home”.
I also tried:

 {% if address == "Privat" and address != "Privatweg" %}

But I never managed to get rid of the “Privatweg”.
Any suggestion would be greatly appreciated.

I have several airtags reporting the exact same lat-lon coordinates based on the state attribues showing up. When they get posted to the map they overlay each other so one is visible and the others are not visible. Would there be a way to offset the lat-lon attributes slightly in order to make them visible on the maps? Thanks for any advice.

i played around a lot with the sensors.yaml file, look like the problem is in the adress url, some caracter are not allowed

https://api.geoapify.com/v1/geocode/search?text=251 Hugues-Pommier,quebec,canada&apiKey=95f133a4aaa04d5cba7b0f39ee2d81b7&format=json
2024-07-15 11:43:19.816 ERROR (MainThread) [homeassistant.components.sensor] Error while setting up rest platform for sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 364, in _async_setup_platform
    await asyncio.shield(awaitable)
  File "/usr/src/homeassistant/homeassistant/components/rest/sensor.py", line 85, in async_setup_platform
    await rest.async_update(log_errors=False)
  File "/usr/src/homeassistant/homeassistant/components/rest/data.py", line 100, in async_update
    response = await self._async_client.request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 1561, in request
    request = self.build_request(
              ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 345, in build_request
    url = self._merge_url(url)
          ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 375, in _merge_url
    merge_url = URL(url)
                ^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/httpx/_urls.py", line 115, in __init__
    self._uri_reference = urlparse(url, **kwargs)
                          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/httpx/_urlparse.py", line 162, in urlparse
    raise InvalidURL("Invalid non-printable ASCII character in URL")
httpx.InvalidURL: Invalid non-printable ASCII character in URL

anyone has issue when using this from outside my lan? Suddently it no longer works while it continue to works when I’m home.

Good morning, excuse the “trivial” question but I am ignorant of everything related to IOS.
I have almost perfectly integrated an AirTag clone, now I would like to integrate a second one.
How do I do it? Do I just create a second shortcut on the iPhone with the information of the second AirTag? Thank you and sorry for the trivial question

Hi!

You dont need It. The shortcut splits the information, so you just need to create a second sensor to get the data.

Please follow the guide :blush:

Thanks, I read and reread the guide but I missed this point, sorry.
Then the 2 airtags that I use were together and in the sensor I always and only saw the first one, this morning I brought the second one with me and it magically appeared with its new position.
THANK YOU

1 Like

Yeah the solution is a bit hacky, but very creative and for now the only option we have. Until Apple adds the devices to the website.

Or better (I hate Apple products), that the android tags get a bit cheaper and Google adds an API for them

1 Like

Agree! I am looking forward to find some cheap android tracker.

I am sure will have them soon.

1 Like