Bonjour à tous, je rédige un article rapide pendant que je travaille sur l’API de la ZiGate. Afin de rendre compatible les objets répondant à la norme ZHA, notamment les produits Xiaomi, je liste les fonctionnalités (les clusters et attributs). Cependant, sur les capteurs Xiaomi, il me restait à trouver comment récupérer les tensions des capteurs.
Dans les trames ZigBee récupérées, je ne percevais que les données utiles aux capteurs, comme la température, l’humidité relative, la pression atmosphérique, les différents types de clics sur les boutons, les mouvements etc … mais à aucun moment, je ne percevais en clair une trame sur les tensions ( entre 2.7V et 3.1V).
J’ai donc laissé tourner quelques temps ma ZiGate et j’ai aperçu, en fonction des capteurs des trames illisibles ayant des attributs propriétaires (0xFF01, 0xFF02) sur le cluster « Basic » (0x000). Donc, je me suis dis que ça ne pouvais être que là dedans que je trouverai mon bonheur.
J’ai donc décidé de mettre au point une stratégie
Votre note :
Ma stratégie
Bon, il faut dire que parmi tout ce que j’ai à faire sur la ZiGate (bientôt un édito sur le sujet) pour vous offrir un bon produit, cette partie me « chaffouinait » tout particulièrement. Ne pas avoir la remontée de la tension de pile des Xiaomi était un point très négatif.
J’ai aussi remarqué que la réception de ces fameuses trames (illisibles) pouvait être déclenchée à chaque appairage de capteur. (ce qui est plutôt pratique pour tester)
Voici comment j’ai procédé :
- J’ai démarré mon fidèle sniffer ZigBee
- J’ai démarré la gateway Xiaomi et je l’ai paramétrée en mode debug (pour quelle envoie les données en UDP). Il y a plein de tutos sur le net, je vous laisse chercher.
- J’ai lancé Wireshark en filtrant les trames UDP provenant de l’ip de la gateway Xiaomi
Une fois tout ce petit beau monde lancé, je me suis muni d’un capteur de température / humidité (rond ou carré c’est compatible) et j’ai lancé la procédure d’appairage avec l’application MIHOME sur mon téléphone.
Résultats
Voici les résultats côté Wireshark :
Trames UDP de la Gateway XIAOMI
Premier constat de la part de la gateway Xiaomi, il y a deux trames UDP consécutives. Il semblerait que la première trame soit une trame avec des valeurs erronées (on comprendra mieux avec la trame ZigBee)
La deuxième trame semble plus cohérente avec une tension de 2995 –> 2.995VDC –> 0xBB3 (en hexadécimal)
Voyons maintenant ce qui se passe côté sniffer ZigBee :
Trames ZigBee correspondantes
On observe qu’après le « Device announce » (appairage), nous avons deux trames provenant du capteur avec un cluster Basic (0x0000). Est-ce que ça explique les deux trames UDP précédentes ? …. surement…
Sachant que la première trame indique simplement que c’est un lumi.sensor_ht avec la version du logiciel. Je suppose donc que le mode debug de la passerelle envoie une trame UDP à chaque trame « Basic » mais comme dans les données JSON, il n’y a ni la version, ni le nom du modèle et que c’est les premières données … il envoie les données par défaut … (ça reste une supposition hein).
Attardons nous sur la deuxième trame qui est une trame assez illisible (au niveau de la payload) avec un attribut propriétaire (0xFF01)
Trames Basic avec attribut propriétaire
J’ai oublié de le surligner mais dans cette capture d’écran, on retrouve notre cluster Basic (0x0000) une commande « Report Attributes » (0x0A) et l’attribut « 0xFF01 » avec comme type de données une chaine de caractères…
La chaine de caractères se trouve juste en dessous et ne ressemble pas à de l’ASCII … Voyons maintenant les valeurs hexadécimales de cette chaine :
Données hexadécimales de la trame
Les parties colorées correspondent aux couleurs du dessus. Donc, prenons la partie verte et cherchons la tension 2.995VDC. On a vu au dessus que cette valeur en hexadécimal était 0xBB3.
Alors je ne sais plus la pour quelle raison (ça date de l’école et c’est devenu un quotidien) mais sachez que les mots (de 2 octets) sont quasi tout le temps inversés… (n’hésitez pas à donner la raison en commentaire).
Donc, je me suis mis à chercher 0xB3 0x0B et il est apparu au grand jour 😉 (surligné sur la capture d’écran).
Bingo !
Alors pour être sûr que ce soit réellement ça, j’ai mis en place deux manipulations :
La première, j’ai alimenté un capteur sur une alimentation de bureau que j’ai fixé à 2.70VDC.
Et j’ai attendu (1 heure environ) de recevoir une nouvelle trame UDP.
Et la tension correspond bien. (j’ai attendu plutôt que re appairer parce que j’ai moyennement confiance à la première trame qui calcule la tension…)
La deuxième manipulation a été de laisser tourner un capteur de température Xiaomi pendant X temps avec la ZiGate et de récupérer les logs:
Et voici le résultat, la tension sur 2-3 jours baissent et les données sont cohérentes… la tension est surlignée en gris…
Bon ok, la première méthode aurait suffit mais je voulais vous montrer ce fichier complet car il est intéressant:
il nous apprend que :
Les capteurs de températures humidité Xiaomi carré ou rond ont une même base (comprenant la tension).
La première version du capteur de température à moins de données.
Il existe plein d’autres informations que je n’ai pas encore décodé et je vous invite à le faire 😉 ( ne me demandez pas comment, débrouillez-vous 😉 )
Conclusion
Voici un petit article qui me semblait intéressant à partager. Avec le projet ZiGate, j’apprends quasiment tous les jours (du coup je m’endors moins bête que la veille chaque jour) et je découvre toujours quelques subtilités.
Je sais aussi (je lis aussi sur les différents forums) que cette histoire de tensions de piles sur les produits Xiaomi vous chagrinent et je voulais vous apporter quelques précisions sur cette partie. En même temps, il était indispensable pour moi de découvrir comment récupérer la tension de pile des capteurs Xiaomi pour mon projet ZiGate.
Autre chose, En faisant les mêmes manipulations sur les boutons poussoirs Xiaomi, je me suis aperçu que c’était une autre trame avec un fonctionnement complètement différent qui donnait la tension de pile (grrrrrrr) une trame de type « Basic » (0x0000) mais cette fois-ci avec un attribut (0xFF02) .. et non géré par la ZiGate (pour le moment).
Bref, encore une partie que je vais devoir rajouter… du coup, je vous laisse et j’y retourne 😉
A bientôt !
Plus je lis tes articles plus je me félicite de t’avoir pris un ZiGate 🙂
Bonne continuation
Je plussois
Merci.
Ça me fait penser qu’il faut que je me trouve une alimentation de laboratoire, il y en a un tas sur Banggood (et GearBest of course) va falloir que j’épluche les avis avec rigueur 😉
Et sinon dit bon boulot d’investigation et reverse engineering comme d’hab !
Merci
Bravo !
C’est beau
Continuez sur cette voie
L’inversion de l’ordre des octets de poids fort et de poids faible dans un mot est historique. A l’origine les octets étaient dans le bon ordre (configuration appelée big-indian), avec les octets de poids fort en premier. C’était le cas des processeur IBM, Motorola où DEC au départ. La configuration little-indian (octet de poids faible en premier sur un mot) a été introduite par DEC avec son modèle PDP11. Cette configuration a ensuite été reprise par Intel dans son l’architecture x86. Raison pour laquelle elle est si fréquente aujourd’hui.
Quand un programme est écrit pour fonctionner sur un processeur fonctionnant en litle-indian, il y a de fortes chances pour que les données soient stockées/échangées sous cette forme inversée. Mais, même si ce n’est pas le cas, le litle-indian étant statistiquement dominant, même dans des environnement big-indian, les données peuvent se retrouver stockées en litle-indian afin de favoriser le cas le plus courant.
Donc bien souvent, comme dans ce cas, dès que l’on cherche une valeur stockée sous la forme d’un mot de 16 ou 32 bits, il y a de fortes chances pour qu’elle soit notée en little-indian.
Remarque: certains processeurs (ARM par exemple qui est en little-indian par défaut) ont la particularité d’avoir une instruction permettant de switcher le fonctionnement du processeur entre les modes little-indian et big-indian.
Merci pour les précisions. La remarque concerne les capteurs xiaomi
Bonjour
Encore un article excellent ! Et que c’est beau le partage de connaissance !
Vivement la suite de tes aventures à la Christophe Colomb.
Merci
Merci à toi de partager tes expériences ,
c’est pourquoi je vais en faire de même, alors sur le hub au niveau du connecteur P1 (l’avant dernière broche en bas à doite) communique en série en 115200 b/s.
Il te suffit d’y connecter RX ( d’un esp8266 par exemple) pour y lire les données importantes .
Tu pourras y lire bien plus d’informations qu’avec wireshark.
Voici un exemple :
=recv zigbee message:Free=39040 ,t=8f00;l=12;data= 00 90 15 01 03 00 06 00 00 10 00 a6
=recv zigbee message:Free=38976 ,t=8f00;l=12;data= 00 90 15 01 04 00 06 00 00 10 01 a6
03-07 02:38:16.728 {« id »:57, »sid »: »lumi.158d00010d5437″, »model »: »lumi.sensor_switch.v2″, »method »: »event.click », »params »:[]}
03-07 02:38:16.739 {« id »:58, »method »: »event.start_play_music », »params »:[« m_10 »]}
Personnellement j’utilise cette astuce avec plus ou moins de succès pour récupérer les info json par mqtt.
Bonne chance pour la suite.
Yeah ! Merci pour l’astuce !
Merci pour ces infos qui démontrent l étendu de tes connaissances.
Comment regretter d avoir fait le pari zigate au vu de tous cela \o/
Bravo
Bonjour ,
y a til une chance de contacter Xiaomi et d etre referencer comme un devloppeur (si gratuit etc…).
Autrement nous allons utiliser un processus d acces au information non stable dans le temps. En effet tout changement de la structure des payloads, de clefs , imposeront une nouvelle recherche et dans tout les cas du code. En general la recherche de la bonne info prends plus de temps.
Il serait bienvenue de connaitre les API officielles quitte a favoriser les produits des fabriquants qui jouent le jeu!
cdt
Leo
Bonjour,
Je crois peu au changement de payload ou clef car ça imposerait aussi à Xiaomi de changer la passerelle pour la rendre compatible. Je pense pas qu’ils souhaitent se rajouter du travail. Après le protocole utilisé, même si ce n’est pas officiel, est normé. La recherche consiste juste avoir la bonne commande. Alors au début c’est un peu long, mais ces efforts ne seront pas amenés à être souvent répétés.
Mais tu as raison, c’est toujours plus efficace d’être en partenariat avec le fabricant. Il me semble que le blogueur Lunarok soit en contact avec les développeurs de Xiaomi mais à quel niveau, je n’en sais rien… Difficile de faire pression sur une firme comme Xiaomi pour les pousser à jouer le jeu.
Bonne explication Laurent Simon. Du reste les indiens n’y sont pour rien.
Il faut lire little endian et big endian 😉
En effet
Merci pour cette information!
J’utilise Google translate pour écrire ceci, donc je m’excuse pour toute erreur.
Bien qu’il soit vrai que les utilisateurs de SmartThings aient eu du mal à lire les données de batterie des appareils Xiaomi, beaucoup de gens ne peuvent pas non plus les garder connectés à leur hub de contrôleur SmartThings après plusieurs heures. Pouvez-vous partager des informations sur la manière dont les périphériques Xiaomi établissent une connexion permanente au contrôleur?
Salut akila et merci pour tes travaux sur les capteurs Xiaomi.
Pour compléter ton analyse : dans la chaine de caractères, on trouve aussi 640B et 6F23 qui donnent 2916 et 9071 en décimal… ce sont les valeurs de température et d’humidité qu’on retrouve dans la trame UDP. Le capteur remonte donc la température et l’humidité dans ce message propriétaire en plus des clusters dédiés. Les données supplémentaires pour les capteurs carrés doivent correspondre à la mesure de pression atmosphérique qui n’existe pas sur le capteur rond.
Merci pour les infos !
Alors je viens de faire le test chez moi avec un capteur carré.
La chaine de caractères reçue est : 0121a90b0421a8430521060006240000000000642976076521dc0d662b888d01000a210000
Dedans je trouve :
A90B = 2985 => Tension pile = 29,85V
7607 = 1910 => Température = 19,10°C
DC0D = 3548 => Humidité = 35,48%
888d0100 = 101768 => Pression atmo = 1017,68mb
A chaque fois les deux octets avant les données (0121, 6429, 6521 et 662B) sont identiques aux tiens, ça doit être des étiquettes qui indiquent le type de données qui suit.
Correction sur la tension de la pile : 2,985V bien sur …
Génial ! Merci pour ces précisions !
Bonjour,
@Laurent Simon: endian, pas indian !
Merci à l’auteur pour l’article.