Vous consultez actuellement AirTag dans Home Assistant : exploitez enfin Find My

AirTag dans Home Assistant : exploitez enfin Find My

Transparence : Cet article présente une installation réalisée avec mes propres AirTags et mon installation Home Assistant. Il ne s’agit ni d’une méthode officielle Apple ni d’une intégration native de Home Assistant. Je partage ici la méthode que j’ai réellement réussi à faire fonctionner, avec ses limites et les quelques erreurs importantes qui peuvent vous éviter de perdre plusieurs heures.

Tags : AirTag Home Assistant Find My

0. Contexte

J’utilise plusieurs AirTags au quotidien.

L’un accompagne Leia, notre chat. Un autre est installé dans la voiture et un troisième dans le camping-car.

Dans l’application Localiser d’Apple, rien de révolutionnaire : j’ouvre l’application et je peux voir la dernière position connue de chacun.

Mais forcément, en tant que passionné de domotique, regarder simplement un point sur une carte a rapidement commencé à me frustrer.

Je voulais que cette information arrive dans Home Assistant.

Pas simplement pour reproduire la carte de Localiser, mais pour pouvoir m’en servir réellement.

Si Leia revient à la maison alors que nous sommes absents, je veux pouvoir être prévenu.

Si le camping-car ou la voiture se déplace en pleine nuit, je veux que Home Assistant m’alerte.

Et si je souhaite créer demain une nouvelle automatisation autour de leur position, je veux pouvoir traiter mes AirTags comme n’importe quel autre device_tracker.

Le problème est qu’Apple ne propose pas d’API publique simple permettant à Home Assistant de récupérer directement les positions de véritables AirTags.

J’ai donc passé pas mal de temps à chercher une solution et à essayer plusieurs méthodes avant de réussir avec hass-FindMy.

La bonne nouvelle est qu’une fois l’installation terminée, il n’est pas nécessaire de laisser un Mac fonctionner 24h/24.

Le principe consiste à utiliser macOS pour récupérer les informations nécessaires à nos AirTags, puis à les importer dans Home Assistant.

Après cela, le Mac n’intervient plus dans le fonctionnement quotidien.

1. Ce qu’il faut savoir avant de commencer

1.1 Comment va fonctionner notre AirTag dans Home Assistant ?

Un AirTag ne communique jamais directement avec Home Assistant.

Il utilise le réseau Apple Find My.

Des appareils Apple passant à proximité de l’AirTag peuvent participer à la remontée de sa position dans le réseau Find My. hass-FindMy va ensuite nous permettre d’exploiter ces informations dans Home Assistant.

Notre chaîne ressemble donc à ceci :

AirTag Apple
      ↓
Réseau Apple Find My
      ↓
hass-FindMy
      ↓
device_tracker
      ↓
Carte Home Assistant
Zones
Automatisations
Notifications

L’objectif du tutoriel est finalement assez simple : récupérer les informations nécessaires à chacun de mes AirTags, les fournir à hass-FindMy puis laisser Home Assistant travailler.

1.2 Installer hass-FindMy avant toute chose

Avant de toucher à macOS, commençons par préparer Home Assistant.

L’intégration utilisée est hass-FindMy, une intégration communautaire permettant de créer des entités de suivi à partir du réseau Find My.

Son dépôt officiel recommande une installation via HACS.

Dans HACS, ajoutez le dépôt :

https://github.com/malmeloo/hass-FindMy

puis installez l’intégration FindMy.

Une fois l’installation terminée, activez l’intégration dans Home Assistant depuis :

Paramètres
→ Appareils et services
→ Ajouter une intégration
→ FindMy

puis vous logguer avec vos identifiants apple pour la mise a jour des coordonnées

Un point important : hass-FindMy évolue encore rapidement.

Au moment où j’ai réalisé cette installation, je n’ai pas réussi à utiliser une méthode plus directe avec mes véritables AirTags. J’ai donc dû passer par l’extraction de leurs données sous macOS et leur import sous forme de fichiers .plist.

Le dépôt actuel documente désormais également une configuration reposant sur un compte Apple et un tracker.

Je ne vais pas prétendre avoir testé une solution que je n’ai pas utilisée.

La suite de cet article documente donc la méthode qui fonctionne réellement chez moi. Selon la version de hass-FindMy installée lorsque vous lirez ces lignes, certains menus peuvent avoir légèrement évolué.

1.3 Pour cette méthode, il nous faut macOS

Pour récupérer les informations dont j’ai eu besoin, macOS est indispensable.

Dans la suite du tutoriel, je vais parler d’un Mac par simplicité et parce que c’est la solution que je recommande au lecteur.

Ce Mac n’a pas besoin de rester allumé ensuite.

Il sert uniquement pendant la phase d’extraction.

Il doit en revanche être correctement connecté au compte Apple auquel sont associés les AirTags.

Avant de poursuivre, vérifiez impérativement :

  • que votre compte Apple est connecté ;
  • que l’application Localiser fonctionne ;
  • que le trousseau macOS est synchronisé ;
  • que vos AirTags apparaissent dans Localiser > Objets.

Dans mon environnement, Leia, la voiture et le camping-car étaient bien présents dans Localiser avant de commencer.

Sans cette synchronisation, inutile d’aller beaucoup plus loin : les informations que nous allons rechercher ne seront pas disponibles.

1.4 Et avec une machine virtuelle ?

Techniquement, la même extraction peut également être réalisée depuis un environnement macOS virtualisé correctement configuré.

Cela peut être pratique lorsque l’on dispose déjà d’une infrastructure de virtualisation.

Je ne détaillerai volontairement pas dans cet article la création d’une machine virtuelle macOS.

Apple encadre l’utilisation et la virtualisation de macOS par ses propres conditions de licence. Si vous choisissez cette solution, c’est à vous de vous assurer que votre environnement respecte ces conditions.

Pour le reste du tutoriel, cela ne change pas le principe : ce qui nous intéresse est d’avoir un environnement macOS correctement authentifié auprès d’Apple, avec Localiser et le trousseau synchronisés.

La procédure que j’ai validée correspond à macOS Ventura 13.7.8. Je préfère donc ne pas affirmer que toutes les versions plus récentes se comporteront exactement de la même manière.

1.5 Pourquoi je déconseille de vouloir contourner macOS

Avant d’arriver à cette méthode, j’avais justement essayé de faire autrement.

J’avais tenté une solution depuis un serveur Linux en SSH.

Sur le papier, c’était idéal : mes serveurs étaient déjà disponibles et cela évitait complètement macOS.

Dans mon cas, l’expérience s’est très mal terminée.

Apple a fini par considérer les connexions comme suspectes, mon accès a été bloqué et j’ai dû modifier mes mots de passe.

Autant dire que j’ai arrêté là les expérimentations autour de mon compte Apple principal.

Je ne prétends pas qu’aucune autre méthode ne peut exister.

Je dis simplement qu’après cette expérience, je préfère clairement travailler depuis un environnement macOS reconnu par Apple plutôt que de chercher à contourner cette étape.

1.6 Les fichiers que nous recherchons

macOS synchronise différentes informations liées à Find My.

Deux éléments vont particulièrement nous intéresser.

Le premier est Items.data.

Il permet notamment de retrouver :

  • le nom de l’objet ;
  • son UUID Find My ;
  • sa latitude et sa longitude ;
  • un timestamp ;
  • l’adresse ;
  • l’état de la batterie ;
  • la précision.

Il m’a surtout permis d’établir cette correspondance :

UUID 1 → Leia
UUID 2 → Camping-car
UUID 3 → Voiture

Mais Items.data ne contient pas à lui seul les informations nécessaires pour hass-FindMy.

Les données qui nous intéressent réellement pour la suite se trouvent dans les fichiers OwnedBeacons. C’est la distinction importante à retenir.

2. Installation et configuration

2.1 Vérifier que Find My a bien synchronisé les AirTags

Les données utilisées dans ma configuration se trouvent dans :

~/Library/com.apple.icloud.searchpartyd

Vous pouvez commencer par examiner les dossiers présents :

find ~/Library/com.apple.icloud.searchpartyd \
-maxdepth 2 \
-type d | sort

Dans mon cas, je retrouvais notamment :

BeaconNamingRecord
BeaconObservationStore
BeaconProductInfoRecord
KeyAlignmentRecords
OwnedBeacons
OwnedDeviceKeyRecord
SharedBeacons
ShareRecord

Le dossier qui va nous intéresser est principalement :

~/Library/com.apple.icloud.searchpartyd/OwnedBeacons

Pour vérifier son contenu :

find ~/Library/com.apple.icloud.searchpartyd/OwnedBeacons \
-type f

Dans mon installation, ce dossier contenait huit fichiers .record.

Parmi eux, je retrouvais bien les UUID correspondant à Leia, au camping-car et à la voiture.

À ce stade, je savais donc que les données nécessaires avaient bien été synchronisées par macOS.

2.2 Utiliser Items.data pour identifier chaque AirTag

Avant de déchiffrer quoi que ce soit, il est pratique de savoir quel UUID correspond à quel objet.

C’est ici que Items.data devient utile.

Grâce aux noms et aux UUID présents dans ce fichier, j’ai pu identifier précisément mes trois AirTags.

L’objectif n’est pas d’utiliser directement Items.data dans Home Assistant.

Il nous sert de table de correspondance pour éviter de nous retrouver quelques minutes plus tard avec plusieurs fichiers .plist impossibles à distinguer.

2.3 Le déchiffreur Swift qui a réellement fonctionné

J’ai essayé plusieurs chemins avant d’arriver à une méthode fiable.

Je ne vais volontairement pas vous faire reproduire toutes ces tentatives.

La méthode que j’ai finalement retenue utilise le script :

airtag-decryptor.swift

Le script utilisé est celui du gist d’Airy permettant de déchiffrer les fichiers présents dans com.apple.icloud.searchpartyd.

Avant de poursuivre, vérifiez que Swift est disponible :

swift --version

Dans mon environnement Ventura, j’obtenais :

Apple Swift version 5.8.1
Target: x86_64-apple-darwin22.6.0

Swift était disponible grâce aux Command Line Tools présents sur le système.

2.4 Télécharger airtag-decryptor.swift

Placez-vous dans le dossier Downloads :

cd ~/Downloads

Puis récupérez le fichier airtag-decryptor.swift depuis le gist utilisé pour cette installation.

À la fin, vous devez simplement retrouver :

~/Downloads/airtag-decryptor.swift

2.5 Pourquoi je ne lance pas le script directement depuis SSH

La plupart des manipulations peuvent être préparées depuis SSH.

Mais l’extraction elle-même m’a posé un problème très précis.

Lorsque je lançais :

swift airtag-decryptor.swift

directement depuis ma session SSH, j’obtenais :

keychainError(status: -25308)

puis, lors de certains essais :

illegal hardware instruction

Le problème venait dans mon cas de l’accès au trousseau.

macOS avait besoin de pouvoir afficher et traiter une demande d’autorisation dans la session graphique.

Une simple connexion SSH ne permettait pas de gérer correctement cette interaction.

2.6 Créer un lanceur pour le Terminal graphique

J’ai donc créé un petit fichier qui lance le déchiffreur depuis le Terminal macOS :

cat > ~/Downloads/run-airtag.command <<'EOF'
#!/bin/zsh
cd ~/Downloads
/usr/bin/swift airtag-decryptor.swift
echo ""
echo "=== FIN DU DECHIFFREMENT ==="
read -k 1 "?Appuie sur une touche pour fermer..."
EOF

On le rend ensuite exécutable :

chmod +x ~/Downloads/run-airtag.command

Puis on demande à macOS de l’ouvrir dans son Terminal graphique :

open -a Terminal ~/Downloads/run-airtag.command

À ce moment, une fenêtre Terminal s’ouvre dans la session macOS.

Si le système demande l’autorisation d’accéder au trousseau, il faut la valider.

Chez moi, c’est cette méthode qui a débloqué l’extraction.

2.7 Retrouver les fichiers déchiffrés

Le déchiffreur parcourt plusieurs éléments, notamment :

OwnedBeacons
OwnedDeviceKeyRecord
BeaconNamingRecord
KeyAlignmentRecords

et génère des fichiers .plist déchiffrés.

J’ai perdu un peu de temps ici parce que je pensais initialement les retrouver directement dans :

/tmp/com.apple.icloud.searchpartyd

Ce n’était pas le cas dans mon environnement.

Le script utilisait le répertoire temporaire de la session macOS, via NSTemporaryDirectory().

Pour connaître ce chemin :

echo "$TMPDIR"

Chez moi, il ressemblait à :

/var/folders/80/xxxxxxxxxxxxxxxx/T/

On peut ensuite rechercher les fichiers avec :

find "$TMPDIR/com.apple.icloud.searchpartyd" \
-type f

Les fichiers qui nous intéressent se trouvent dans :

$TMPDIR/com.apple.icloud.searchpartyd/OwnedBeacons/

2.8 Un fichier .plist par AirTag

À l’intérieur de OwnedBeacons, on retrouve un fichier .plist pour chacun des AirTags concernés.

La logique devient alors :

OwnedBeacons/<UUID>.plist

En reprenant la correspondance effectuée avec Items.data, j’ai pu identifier les trois fichiers puis les renommer de manière plus compréhensible :

Leia.plist
Camping-car.plist
Voiture-Loic.plist

C’est finalement l’une des règles les plus simples de tout le tutoriel :

1 AirTag = 1 fichier .plist

2.9 Sauvegarder immédiatement les fichiers

Attention au fait que ces fichiers se trouvent dans $TMPDIR.

Il s’agit donc d’un répertoire temporaire.

Je vous conseille de les copier immédiatement vers un emplacement permanent :

mkdir -p ~/airtags-export

Puis :

cp "$TMPDIR/com.apple.icloud.searchpartyd/OwnedBeacons/"*.plist \
~/airtags-export/

Vérifiez ensuite :

ls -lah ~/airtags-export

Dans mon cas, le dossier définitif était donc :

/Users/loic/airtags-export

J’ai ensuite transféré les fichiers vers mon PC Windows avec Bitvise en SFTP.

WinSCP ou scp auraient également pu remplir le même rôle. Le point important n’est pas l’outil de transfert, mais de récupérer les fichiers avant la disparition éventuelle du répertoire temporaire.

2.10 Ne récupérer que les fichiers nécessaires

Il n’est pas nécessaire d’envoyer l’ensemble des données Find My vers Home Assistant.

Je n’ai pas importé :

OwnedDeviceKeyRecord
KeyAlignmentRecords
BeaconNamingRecord
ShareRecord
...

Pour hass-FindMy, les fichiers que j’ai utilisés sont simplement ceux provenant de :

OwnedBeacons/*.plist

C’est plus simple et cela évite de manipuler inutilement davantage de données sensibles.

2.11 Attention : ces fichiers sont sensibles

Les fichiers .plist récupérés pendant cette opération ne doivent pas être considérés comme de simples fichiers de configuration.

Ils contiennent les données cryptographiques nécessaires à l’exploitation de vos AirTags avec cette méthode.

Je vous déconseille donc fortement de les partager

2.12 Importer les AirTags dans hass-FindMy

Nous pouvons maintenant revenir dans Home Assistant.

Dans la version que j’utilisais au moment de l’installation, le chemin était :

Paramètres
→ Appareils et services
→ FindMy
→ Ajouter un appareil FindMy

Pour chaque AirTag, j’ai utilisé un appareil de type via find my sur HA :

Puis, pour Leia par exemple :

Dans cette configuration, la logique devient :

1 AirTag
=
1 fichier .plist
=
1 Rolling device
=
1 device_tracker Home Assistant

Je rappelle que hass-FindMy évolue et que le dépôt officiel actuel documente aussi une configuration avec un compte Apple et un tracker. Si votre interface diffère légèrement de mes captures, vérifiez donc la documentation correspondant à votre version.

2.13 Le résultat dans Home Assistant

Une fois importé, l’AirTag apparaît comme un device_tracker.

Parmi les attributs disponibles dans mon installation, je retrouvais notamment :

À partir de là, l’AirTag peut être exploité dans les cartes, les zones et surtout dans les automatisations.

C’est ici que toute la partie technique précédente commence réellement à devenir intéressante.

2.14 detected_at n’est pas last_updated

C’est probablement l’une des informations les plus importantes que j’ai découvertes pendant mes tests.

Home Assistant pouvait par exemple afficher :

Dernière mise à jour : 12:56

alors que l’attribut :

detected_at : 12:28

indiquait une autre heure.

Ce n’est pas une incohérence.

Dans cet exemple :

12:56
= Home Assistant a actualisé l'entité

12:28
= le réseau Find My a réellement détecté l'AirTag

Pour savoir quand Leia ou un véhicule a réellement été vu par le réseau Find My, j’utilise donc :

state_attr('device_tracker.xxx', 'detected_at')

et non last_updated.

Cette différence est capitale pour construire les scénarios de la partie suivante.

2.15 Les quelques choses qui n’ont pas fonctionné

Je pourrais consacrer plusieurs pages à tout ce que j’ai essayé avant d’arriver à cette procédure.

Cela n’apporterait pas grand-chose au lecteur.

Les quelques points à retenir sont les suivants.

J’ai commencé par une tentative sous Linux qui a fini par provoquer un blocage de mon compte Apple et m’a obligé à modifier mes mots de passe.

J’ai ensuite essayé Homebrew sous Ventura. Dans mon environnement, il s’est mis à compiler de nombreuses dépendances, dont OpenSSL et Python, et cela a pris plusieurs heures.

FindMy.py a bien été installé après quelques ajustements, mais la commande de déchiffrement automatique n’a pas réussi à récupérer correctement la BeaconStoreKey, même si celle-ci était présente dans le trousseau.

Enfin, le déchiffreur Swift lancé directement en SSH échouait à cause de l’interaction nécessaire avec le trousseau.

Le lancement depuis le Terminal graphique macOS a été le chemin qui a réellement fonctionné.

Si je devais tout recommencer aujourd’hui, je partirais directement sur :

macOS correctement connecté au compte Apple
        ↓
AirTags visibles dans Localiser
        ↓
OwnedBeacons présents
        ↓
airtag-decryptor.swift
        ↓
Terminal graphique macOS
        ↓
OwnedBeacons/*.plist
        ↓
hass-FindMy
        ↓
device_tracker Home Assistant

2.16 Conserver de quoi refaire une extraction plus tard

Une fois tout cela fonctionnel, le Mac n’a plus besoin de rester allumé en permanence.

Je conseille simplement de conserver :

~/Downloads/airtag-decryptor.swift
~/Downloads/run-airtag.command

Si un jour vous devez refaire une extraction, vous pourrez relancer :

open -a Terminal ~/Downloads/run-airtag.command

puis récupérer de nouveau :

$TMPDIR/com.apple.icloud.searchpartyd/OwnedBeacons/

Je ne referais pas toute cette procédure simplement pour :

  • redémarrer Home Assistant ;
  • redémarrer le serveur ;
  • changer la pile d’un AirTag ;
  • effectuer une opération classique tant que l’AirTag continue à fonctionner.

En revanche, je referais probablement l’extraction si l’AirTag est supprimé du compte Apple, réinitialisé, réassocié, remplacé, si son ancien .plist ne fonctionne plus ou si j’ajoute un nouvel AirTag.

3. Ce que j’en fais réellement dans Home Assistant

3.1 Savoir que Leia est revenue alors que nous sommes absents

C’est la première utilisation que je voulais réellement obtenir.

Leia porte un AirTag.

Lorsque nous sommes présents à la maison, savoir qu’elle est elle aussi dans le secteur n’a pas énormément d’intérêt.

En revanche, lorsque la maison est en mode Absent ou Vacances, je trouve intéressant d’être prévenu si son AirTag est de nouveau détecté dans la zone Maison.

La logique est donc :

Leia = Maison

ET

Mode maison = Absent
OU
Mode maison = Vacances

→ Notification

Je peux recevoir par exemple :

Leia détectée à la maison

Leia présente à 14:23 en mode Absent.

Mais je ne veux pas afficher l’heure à laquelle Home Assistant a simplement rafraîchi le tracker.

Je récupère donc directement detected_at :

- variables:
    detected: "{{ state_attr('device_tracker.leia', 'detected_at') }}"
    heure_detection: >
      {% if detected %}
        {{ as_local(as_datetime(detected)).strftime('%H:%M') }}
      {% else %}
        {{ now().strftime('%H:%M') }}
      {% endif %}

J’obtiens ainsi l’heure correspondant à la détection réelle par le réseau Find My.

C’est exactement le type d’utilisation que je recherchais : l’AirTag cesse d’être simplement un point à regarder dans Localiser et devient une information utilisable par la maison.

alias: AirTag - Leia présente maison en mode Absent/Vacance
description: >
  Notifie sur TheGypsyKingUP6 lorsque Leia est détectée à la maison alors que le
  mode Maison est Absent ou Vacance. L'heure affichée correspond au detected_at
  réel de FindMy.
triggers:
  - trigger: state
    entity_id:
      - device_tracker.findmy_leia
    to:
      - home
    id: leia_home
  - trigger: state
    entity_id: input_select.mode_maison
    to: Absent
    id: mode_absent
  - trigger: state
    entity_id: input_select.mode_maison
    to: Vacance
    id: mode_vacance
conditions:
  - condition: state
    entity_id: device_tracker.findmy_leia
    state:
      - home
  - condition: template
    value_template: |
      {{ states('input_select.mode_maison') in ['Absent', 'Vacance'] }}
actions:
  - variables:
      mode_maison: '{{ states(''input_select.mode_maison'') }}'
      detected: '{{ state_attr(''device_tracker.leia'', ''detected_at'') }}'
      heure_detection: |
        {% if detected %}
          {{ as_local(as_datetime(detected)).strftime('%H:%M') }}
        {% else %}
          {{ now().strftime('%H:%M') }}
        {% endif %}
  - action: notify.mobile_app_thegypsykingup6
    data:
      title:  Leia détectée à la maison
      message: |
        Leia présente à {{ heure_detection }} en mode {{ mode_maison }}.
      data:
        push:
          interruption-level: time-sensitive
mode: single

3.2 Détecter le déplacement de la voiture ou du camping-car pendant la nuit

Pour mes deux véhicules, j’avais un autre besoin.

Lorsque la maison est en mode Nuit, la voiture ou le camping-car n’ont normalement aucune raison de se déplacer de manière importante.

Je voulais donc être averti si l’un d’eux bougeait.

Le scénario surveille l’attribut :

attribute: detected_at

Ainsi, chaque nouveau rapport Find My peut déclencher une vérification.

Home Assistant compare alors l’ancienne position avec la nouvelle.

La fonction utilisée est :

distance(trigger.from_state, trigger.to_state)

3.3 Pourquoi j’ai choisi un seuil de 100 mètres

Un AirTag n’est pas un traceur GPS temps réel.

Entre deux remontées Find My, quelques variations de position sont possibles.

Je ne voulais évidemment pas être réveillé en pleine nuit parce que le point représentant le camping-car s’était déplacé de quelques mètres sur la carte.

J’ai donc retenu cette condition :

{% set d = distance(trigger.from_state, trigger.to_state) %}
{{ d is not none and d >= 0.10 }}

Dans Home Assistant :

0,10 km ≈ 100 mètres

Si le déplacement calculé reste inférieur à cette valeur, aucune alerte n’est envoyée.

S’il dépasse 100 mètres pendant le mode Nuit, cela mérite clairement mon attention.

3.4 Une seule alerte par véhicule et par nuit

Il restait un problème.

Imaginons que je sois moi-même en train de déplacer le camping-car pendant la nuit.

Find My va continuer à produire de nouvelles positions.

Je n’ai aucune envie de recevoir une notification critique toutes les quelques minutes.

J’ai donc créé deux helpers :

input_boolean.alerte_nuit_camping_car
input_boolean.alerte_nuit_voiture_loic

Lorsque la maison passe en mode Nuit, les deux sont remis à :

OFF

Au premier déplacement important du camping-car :

Notification
+
input_boolean.alerte_nuit_camping_car = ON

Toutes les détections suivantes concernant le même véhicule sont ensuite ignorées pendant cette nuit.

La voiture possède son propre helper et reste donc surveillée indépendamment.

Le maximum devient :

1 notification Camping-car
+
1 notification Voiture
par nuit

Lorsque la maison quitte le mode Nuit, les helpers sont également réinitialisés.

Cela garantit que la protection sera automatiquement prête pour la nuit suivante.

3.5 Dans ce cas, je veux une notification critique

Pour ce scénario, une notification classique ne m’intéressait pas vraiment.

Si le camping-car se déplace à 2 h 14 alors que toute la maison dort, je veux être réveillé.

J’utilise donc une notification critique sur mon téléphone :

data:
  push:
    interruption-level: critical
    sound:
      name: default
      critical: 1
      volume: 1

Le message peut prendre cette forme :

Déplacement Camping-car

Attention : déplacement du Camping-car détecté
à 02:14 pendant le mode Nuit.

J’ai ainsi une petite sécurité supplémentaire qui repose sur un objet que j’utilisais jusque-là uniquement avec l’application Localiser.

alias: Sécurité - Déplacement véhicules pendant la nuit
description: >-
  Détecte un déplacement du Camping-car ou de la Voiture Loïc lorsque la maison
  est en mode Nuit. Une seule notification critique par véhicule et par nuit.
  Les alertes sont réinitialisées à l'entrée et à la sortie du mode Nuit.
triggers:
  - trigger: state
    entity_id:
      - device_tracker.findmy_camping_car
    id: camping_car
  - trigger: state
    entity_id:
      - device_tracker.findmy_voiture_loic
    id: voiture_loic
  - trigger: state
    entity_id: input_select.mode_maison
    to: Nuit
    id: debut_nuit
  - trigger: state
    entity_id: input_select.mode_maison
    from: Nuit
    id: fin_nuit
conditions: []
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: |
              {{ trigger.id in ['debut_nuit', 'fin_nuit'] }}
        sequence:
          - action: input_boolean.turn_off
            target:
              entity_id:
                - input_boolean.alerte_nuit_camping_car
                - input_boolean.alerte_nuit_voiture_loic
            data: {}
      - conditions:
          - condition: template
            value_template: |
              {{ trigger.id == 'camping_car' }}
          - condition: state
            entity_id: input_select.mode_maison
            state: Nuit
          - condition: state
            entity_id: input_boolean.alerte_nuit_camping_car
            state: 'off'
          - condition: template
            value_template: |
              {{
                trigger.from_state is not none
                and trigger.to_state is not none
                and trigger.from_state.attributes.get('latitude') is not none
                and trigger.from_state.attributes.get('longitude') is not none
                and trigger.to_state.attributes.get('latitude') is not none
                and trigger.to_state.attributes.get('longitude') is not none
              }}
          - condition: template
            value_template: >
              {% set d = distance(trigger.from_state, trigger.to_state) %} {{ d
              is not none and d >= 0.10 }}
        sequence:
          - variables:
              heure_detection: >
                {% set d = trigger.to_state.attributes.get('detected_at') %} {%
                if d %}
                  {{ as_local(as_datetime(d)).strftime('%H:%M') }}
                {% else %}
                  {{ now().strftime('%H:%M') }}
                {% endif %}
              distance_deplacement: >
                {% set d = distance(trigger.from_state, trigger.to_state) %} {%
                if d is not none %}
                  {{ (d * 1000) | round(0) }}
                {% else %}
                  0
                {% endif %}
          - action: notify.mobile_app_thegypsykingup6
            data:
              title: 🚨 Déplacement Camping-car
              message: >-
                Attention : déplacement du Camping-car détecté à {{
                heure_detection }} pendant le mode Nuit.
              data:
                push:
                  interruption-level: critical
                  sound:
                    name: default
                    critical: 1
                    volume: 1
          - action: input_boolean.turn_on
            target:
              entity_id: input_boolean.alerte_nuit_camping_car
      - conditions:
          - condition: template
            value_template: |
              {{ trigger.id == 'voiture_loic' }}
          - condition: state
            entity_id: input_select.mode_maison
            state: Nuit
          - condition: state
            entity_id: input_boolean.alerte_nuit_voiture_loic
            state: 'off'
          - condition: template
            value_template: |
              {{
                trigger.from_state is not none
                and trigger.to_state is not none
                and trigger.from_state.attributes.get('latitude') is not none
                and trigger.from_state.attributes.get('longitude') is not none
                and trigger.to_state.attributes.get('latitude') is not none
                and trigger.to_state.attributes.get('longitude') is not none
              }}
          - condition: template
            value_template: >
              {% set d = distance(trigger.from_state, trigger.to_state) %} {{ d
              is not none and d >= 0.10 }}
        sequence:
          - variables:
              heure_detection: >
                {% set d = trigger.to_state.attributes.get('detected_at') %} {%
                if d %}
                  {{ as_local(as_datetime(d)).strftime('%H:%M') }}
                {% else %}
                  {{ now().strftime('%H:%M') }}
                {% endif %}
              distance_deplacement: >
                {% set d = distance(trigger.from_state, trigger.to_state) %} {%
                if d is not none %}
                  {{ (d * 1000) | round(0) }}
                {% else %}
                  0
                {% endif %}
          - action: notify.mobile_app_thegypsykingup6
            data:
              title: 🚨 Déplacement Voiture
              message: >-
                Attention : déplacement de la voiture détecté à {{
                heure_detection }} pendant le mode Nuit.
              data:
                push:
                  interruption-level: critical
                  sound:
                    name: default
                    critical: 1
                    volume: 1
          - action: input_boolean.turn_on
            target:
              entity_id: input_boolean.alerte_nuit_voiture_loic
mode: queued
max: 10

3.6 Ce que cela ouvre comme possibilités

Je pourrais facilement imaginer d’autres utilisations.

Mais je préfère m’arrêter à celles que j’ai réellement mises en place.

Aujourd’hui, mes AirTags servent concrètement à deux choses dans Home Assistant : surveiller le retour de Leia lorsque la maison est vide et détecter un déplacement anormal de mes véhicules pendant la nuit.

C’est déjà largement suffisant pour donner du sens à cette intégration.

4. Mon avis

4.1 Ce que j’ai apprécié

Le résultat correspond exactement à ce que je cherchais.

Mes véritables AirTags apparaissent dans Home Assistant comme des device_tracker.

Je peux exploiter leur position dans mes zones, mes modes de maison, mes notifications et mes automatisations.

Surtout, je n’ai pas besoin de transformer un Mac en serveur permanent uniquement pour cela.

Une fois les informations nécessaires extraites et importées, hass-FindMy et Home Assistant fonctionnent sans garder la machine macOS allumée en permanence.

Et finalement, le plus intéressant n’est pas de réussir à afficher Leia sur une carte.

C’est de pouvoir dire à ma maison :

« Nous sommes absents et Leia vient d’être détectée ici : préviens-moi. »

ou :

« Il est deux heures du matin et le camping-car vient de se déplacer de plus de 100 mètres : réveille-moi. »

C’est à ce moment que l’intégration prend réellement tout son sens.

4.2 Les points à connaître

Il faut tout de même garder quelques limites en tête.

hass-FindMy est une intégration communautaire et son fonctionnement évolue.

La méthode présentée ici utilise des mécanismes liés au fonctionnement de Find My qui peuvent eux aussi être modifiés par Apple.

Je ne considère donc pas cette intégration comme quelque chose de garanti pour les dix prochaines années.

Un AirTag n’est pas non plus un véritable GPS temps réel. La fraîcheur d’une position dépend du réseau Find My et du moment où l’AirTag a réellement été détecté.

C’est pour cette raison que l’attribut detected_at est si important dans mes automatisations.

Enfin, les fichiers .plist obtenus pendant l’extraction sont sensibles et doivent rester privés.

Et je le répète : la méthode macOS décrite ici est celle que j’ai réussi à faire fonctionner. Si demain hass-FindMy permet une intégration plus simple de mes AirTags et que je parviens à la valider, je serai évidemment le premier à simplifier cette installation.

4.3 Mon verdict

Je pensais au départ que récupérer mes AirTags dans Home Assistant serait une petite intégration sympathique.

Cela m’a finalement demandé beaucoup plus de recherches que prévu.

Une fois les mauvaises pistes éliminées, le chemin fonctionnel est néanmoins beaucoup plus simple à comprendre :

Mac / environnement macOS
→ compte Apple et Localiser
→ OwnedBeacons
→ déchiffrement
→ fichiers .plist
→ hass-FindMy
→ device_tracker
→ automatisations

Et le résultat en valait la peine.

Je ne regarde plus uniquement la position de mes AirTags dans Localiser.

Home Assistant peut maintenant agir en fonction de cette position.

Pour moi, c’est exactement ce qui fait tout l’intérêt de la domotique : partir d’une information existante et lui donner une vraie utilité dans la maison.

J’espère que cet article vous aura plu.

N’oubliez pas que la vie est une fête.

Loïc

Loïc phoenix castillo

Passionné par informatique dès mon plus jeune âge, j'ai arrêté à mes 21 ans pour me consacrer à mes études d'infirmier et faire la fête. Maintenant père de famille, je me réinvestis dans la domotique ! Bref le kif ! Rédacteur en chef de Youdom