Température Bluetooth LE dans domoticz par reverse engineering et MQTT auto-discovery Home Assistant

  • Post category:Domotique / Informatique
  • Post comments:0 commentaire
  • Post last modified:16 juillet 2022
  • Temps de lecture :16 min de lecture

À la recherche de thermomètres simples à intégrer à mon installation domotique, je suis tombé sur des capteurs Bluetooth LE très bons marchés, mais pour lesquels il n’existait pas d’intégration disponible. J’ai donc cherché à faire cette intégration, à la découverte du reverse engineering Android, du protocole Bluetooth LE et de l’auto-discovery MQTT sous Home Assistant et Domoticz.

Le modèle de thermomètre que j’ai repéré est très simple, assez petit (carré de 4 cm de côté), avec un simple affichage de la température et de l’humidité, et un pictogramme qui illustre le confort hygrométrique. On le trouve à moins de 5 € sur des sites comme AliExpress (exemple : https://fr.aliexpress.com/item/1005004073828412.html ; attention, il existe des modèles non Bluetooth très ressemblant, à l’exception du logo Bluetooth sur la droite de la température). Il est alimenté par une pile bouton CR2032 dont je n’ai pas encore d’idée de l’autonomie, mais que l’on trouve également peu chère sur les mêmes sites.

Le thermomètre arrive avec une notice en chinois avec un QR-Code qui pointe vers une application Android ou iOS (qui porte le délicieux nom de “qaqa” 😉 ) qui permet de se connecter au thermomètre et d’afficher les mesures ainsi que l’historique.

 

Reverse Engineering

Le reverse engineering en France n’est autorisé que dans certains cas précis, et notamment à des fins d’interopérabilité, en ayant le droit d’usage du logiciel et lorsque les informations n’ont pas déjà été mises à disposition par leur auteur (source LegiFrance et son analyse par un avocat). Ça tombe bien, c’est exactement notre cas. Cette parenthèse juridique levée, nous pouvons passer à la suite.

Pour comprendre comment cela marche, j’ai commencé par chercher sur internet si je trouvais quelque chose. Rien… Puis par observer ce qui est exposé en Bluetooth ; pour ce faire, la société Nordic Semiconductor qui fabrique des puces de connectivité Bluetooth met à disposition gratuitement une application Android “nRF Connect for Mobile” très bien faite pour observer les périphériques Bluetooth. Cela permet de naviguer dans les différents services et caractéristiques disponibles, et de se rendre compte assez vite qu’il n’y a rien d’évident de disponible et qu’il va falloir creuser un peu plus. Pour les plus fortunés, il existe aussi des analyseurs de protocole Bluetooth pour plusieurs centaines d’euros.

Comme une application Android est disponible, il est possible de l’analyser. En effet, les applications Android sont écrites en Java et le Java se décompile plutôt très bien. Il existe un logiciel particulièrement bien adapté pour faire ça qui s’appelle JADX (également installable via scoop install jadx ). Il faut en premier récupérer l’apk. L’adresse donnée par le QRCode sur la notice est https://d.ihunuo.com/app/dqwu et il suffit de cliquer sur le logo Android pour télécharger le fichier APK (LT_Thermometer-V3.apk). Il faut ensuite lancer jadx-gui, ouvrir le fichier, et le code décompilé apparait !

 

Après un peu de recherche, on trouve rapidement la fonction principale qui permet de décoder la température.  En analysant le reste du fichier, on trouve que le protocole est le suivant :

UUID de la caractéristique Bluetooth de notification, à laquelle il va falloir s’abonner pour recevoir les données : “0000FFE8-0000-1000-8000-00805f9b34fb”

Structure des données reçues :

Octets Contenu
0,1 Header (0xAA0xAA)
2 Type de données :
– 162 : hygrométrie (température + humidité)
– 163 : historique des données
– 164 : information de version
3,4 Taille des données n (Big Endian)
5,5+n Données suivant le type
5+n Checksum des données (somme de tous les octets jusqu’au checksum exclus, modulo 256)
6+n Footer (0x55)

Et pour un type de donnée 162 (hygrométrie), la taille de la structure est de 6 octets et la structure complète est la suivante :

Octets Contenu
0,1 Header (0xAA0xAA)
2 Type de données 162 (0xA2) : hygrométrie (température + humidité)
3,4 Taille des données : 6 (Big Endian)
5,6 Température en Big Indian, à diviser par 10
7,8 Humidité en Big Indian, à diviser par 10
9 Indicateur de pile
10 Unité ; 0 pour Celcius
11 Checksum des données (somme de tous les octets de 0 à 10, modulo 256)
12 Footer (0x55)

En ce qui concerne la version, c’est une simple chaîne de caractère avec le texte de la version, et pour les informations d’historique, un tableau d’entrées de 4 octets contenant la température et l’humidité sur 2 octets chacun suivant la même formule que précédemment. Chaque valeur correspond à une heure, à compter à rebours depuis l’heure courante.

On peut maintenant vérifier avec l’application “nRF Connect for Mobile” que notre compréhension est la bonne avant de passer à l’implémentation :

Pour arriver cet écran, il faut trouver le bon device (généralement LT_xxxx), s’y connecter, repérer le service 0xFFE9 et sa caractéristique de notification 0xFFE8, cliquer sur la petite icone à droite pour s’abonner aux notifications, et attendre quelques secondes pour voir s’afficher la ligne value, qui dans cet exemple est (0x) AA-AA-A2-00-06-01-10-01-86-10-00-95-55 ; nous observons bien:

  • AA-AA : l’en-tête
  • A2 : c’est l’hygrométrie
  • 00-06 : la taille des donnée est de 6 octets
  • 01-10 : 0x0110, soit 256 en décimal, à diviser par 10 : 25,6°  (et ça tombe bien, c’est bien ce que mon thermomètre affiche !)
  • 01-86 : 0x0186, soit 390 en décimal, à diviser par 10 : 39%
  • 01 : indication de pile ; je suppose que 1 veut dire que l’indicateur de pile n’est pas affiché
  • 00 : nous sommes en degrés Celsius
  • 95 : le checksum (et il est correct)
  • 55 : le footer

Nous pouvons maintenant lire les données et passer à la suite !

 

Implémentation du script de décodage

Le script devra s’exécuter sur un périphérique ayant accès à une connectivité Bluetooth LE, et être situé de sorte à pouvoir capter vos thermomètre. Dans mon cas, le seul équipement que j’ai de compatible Bluetooth LE est mon raspberry zéro wifi, le choix sera donc vite fait.

Mon cahier des charges est le suivant :

  • Écouter un ou plusieurs de ces thermomètres
  • Publier les résultats sur un serveur MQTT pour pouvoir réutiliser ensuite
  • En python, mon langage de prédilection pour ce genre de scripts, a minima compatible Linux et plus si possible

J’ai commencé à utiliser la librairie python bluepy que j’ai trouvée utilisée à plusieurs reprises dans d’autres scripts similaires, mais en plus de la documentation défaillante (notamment pour les notifications, utiliser withDelegate et non pas setDelegate, j’ai perdu un temps fou à cause de ce manque de documentation…), je suis tombé sur plusieurs bugs, dont un particulièrement gênant de déconnexion lors de l’exécution d’un autre script de lecture d’une balance connectée (voir l’article https://www.lprp.fr/2021/02/xiaomi-smart-scale-with-domoticz-nodered-raspberry-and-google-fit). Donc, j’ai essayé Bleak, qui en plus de sembler un peu plus stable, plus simple, et se trouve être également plus portable.

Pour MQTT, paho-mqtt semble faire l’unanimité et est effectivement super simple à utiliser pour envoyer un message.

Le code est disponible ici : https://github.com/rpeyron/blelt2mqtt

Version à la date de la rédaction de cet article

Il reprend les différentes étapes détaillées ci-dessus dans l’analyse de protocole et ne comporte pas de difficulté particulière.

 

Auto-discovery et setup dans Domoticz

Lors de précédentes recherches sur Domoticz j’avais repéré l’existence d’un plugin d’auto-discovery MQTT qui semble même maintenant intégré de façon native dans domoticz depuis peu. Il s’agit en fait de l’intégration dans Domoticz d’un protocole défini par Home Assistant pour simplifier la découverte de nouveaux devices via MQTT. J’ai trouvé relativement peu de tutoriels sur le sujet, donc voici ce que j’ai trouvé.

Le principe de l’auto-discovery MQTT repose sur des messages de configuration qui doivent être émis par le device pour se déclarer et mentionner les caractéristiques.  Le topic est sous la forme /homeassistant/<devicetype>/<deviceid>/config  ; par exemple pour définir un device capteur (sensor) nommé LTBureau : /homeassistant/sensor/LTBureau/config  . Le contenu du message est un json qui suit la structure suivante :

Il existe bien sûr d’autres propriétés pour d’autres types d’équipements dont vous trouverez les indications dans la documentation.  L’auto-discovery peut également désinscrire le device (lorsqu’il n’est plus actif par exemple), en envoyant simplement un message vide sur ce même topic.

A noter qu’il n’est pas nécessaire que le topic de statut fasse partie de la même arborescence que le topic d’auto-configuration (c’est même recommandé que ce ne soit pas le cas). Il est même possible d’ajouter plusieurs devices Home Assitant à partir du même topic d’état. C’est par exemple ce qu’il faut faire pour déclarer les mesures de température et d’humidité pour un capteur d’hygrométrie car Home Assistant ne dispose pas d’un device qui supporte les deux valeurs contrairement à Domoticz. Et malheureusement, comme Home Assistant ne supporte pas ce type de device, il n’est pas non plus possible de déclarer un tel device par le protocole d’auto-discovery. J’ai donc conservé l’auto-discovery dans le script si jamais des personnes voudrait l’utiliser dans Home Assistant, mais développé un complément pour Domoticz. Pour domoticz, il faut faire manuellement la création d’un capteur virtuel (via le matériel Dummy dans l’onglet Hardware) dans l’interface et recopier l’idx ainsi obtenu (visible une fois créé dans l’onglet Devices), et lui envoyer les nouvelles valeur via le topic “ domoticz/in ” (ou celui que vous avez paramétré si vous en avez utilisé un différent). La structure du json est documentée sur cette page à envoyer et est super simpledans le cas d’un capteur Température + Humidité :

 

Ainsi au final, le plugin ci-dessus publiera à chaque mesure sur deux topics :

et lors du discovery sur le topic dédié :

Et le résultat dans Domoticz (à gauche le device natif domoticz ajouté manuellement, et à droite celui issu du discovery MQTT) :

 

 

 

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.