[FR][3/4] Weather Station Gateway : Complément d’analyse

Dans l’article précédent je n’avais pas dévoilé où la température était cachée dans le contenu de la data, mais j’avais laissé un indice :

C’est dans la partie rose clair, celle juste après le numéro de séquence.

Si on reprend ces trois octets des différentes captures wireshark, avec la température associée, ça nous donne ça :

00 F3 0A => 24,3°C
00 F3 0A => 24,3°C
00 F2 0A => 24,2°C
[...]
00 F2 0A => 24,2°C
80 F5 8A => 24,5°C

Julius a posté la solution en commentaire de l’article précédent, il suffit de prendre l’octet du milieu et de diviser par 10. Ainsi :

F3 = 243 => 24,3. 
F2 = 242 => 24,2°C
etc...

Mais alors deux questions se posent :

  • A quoi servent les deux autres octets ?
  • Que se passe-t-il lorsque la température passe au dessus de 25,5 (0xFF) ?

Eh bien les réponses sont en partie liées. Effectivement pour un octet la valeur maximale ne peut pas aller au dessus de 255 (0xFF) donc le protocole doit trouver un moyen de représenter les valeurs à partir de 25,6°C. Alors j’ai sorti un sèche cheveux et j’ai fait l’expérience :

00 FB 0A => 25,1°C
00 FD 0A => 25,3°C
81 05 0A => 26,1°C

81 ? En réalité c’est le 1 qui compte. le 0x80 est un flag (je ne sais pas à quoi celui-ci sert). Vous pouvez trouver dans la FAQ les explications sur ce qu’est un flag en programmation.

Lorsque l’octet n°2 passe au dessus de 0xFF, le bit de poids faible (bit0) de l’octet n°1 passe à 1 et l’octet n°2 repasse à 0x00. De cette façon on peut lire la température en concaténant le bit de poids faible de l’octet n°1 devant l’octet n°2 :

0x00FE = 254
0x00FF = 255
0x0100 = 256
0x0101 = 257
[...]
0x0104 = 260
0x0105 = 261

D’accord et une fois qu’on arrive à 0x01FF (511) il se passe quoi ensuite ? Je ne sais pas si ce capteur de température prévoit de mesurer des valeurs au dessus de 51,1°C, mais si c’est le cas je suppose que l’octet n°1 passerait de 0x01 à 0x02 donc on pourrait atteindre des mesures jusqu’à 76,7°C (0x02FF). Si on a bien deux bits sur l’octet 1 pour compléter la valeur de l’octet 2, alors on peut également monter jusqu’à 0x03FF (102,3°C), explication en FAQ. Donc selon moi voici une supposition de l’utilité de chaque bit de ces trois octets (j’ai utilisé un exemple en bas de l’image)

J’ai mis 10 bits pour la température, mais c’est une supposition. Actuellement je suis juste sur qu’elle est sur 9 bits

La couleur verte est utilisée ici pour indiquer les bits que l’ont sait qui peuvent changer. Pour l’instant je ne sais pas à quoi servent les flags de A à N, je ne suis même pas sûr que ce soit tous des flags. Une question qui pourrait se poser est « Que se passe-t-il lorsque la température passe en négatif ? » Je ferai probablement un article bonus dès que j’aurai fait l’expérience.

Pour terminer cette analyse de la trame de requête, on va finir par 5 octets qu’on a pas encore analysés et qui pourraient se révéler utiles pour notre serveur factice :

Les trois octets 0x00 0xF2 0x0A devraient vous être familiers, ce sont les trois octets de la partie température mais c’est ceux de la trame précédente (envoyé 7 minutes avant la trame en cours donc). Pareil pour 0x42 qui est l’humidité envoyée lors de la précédente trame. Dans ce message on peut donc voir que la sonde a relevé pour la température 0x00 0xF2 0xA 0x42 (24,2°C et 66% d’humidité) et que la fois d’avant elle avait relevé exactement la même chose.

Alors, pourquoi envoyer de nouveau ces données qui ont déjà été envoyées 7 minutes avant ? Je suppose que c’est au cas où le message d’avant se perde (mauvaise transmission / réception), grâce cette répétition de données on pourrait donc avoir les données actuelles plus celles qui ont été perdues la fois d’avant. Si par contre on perd deux messages d’affilée alors là le premier des deux sera perdu à tout jamais.

Et le dernier octet semble être justement celui qui permet de vérifier si la trame est valide (intègre) ou pas, c’est un octet de CRC-8. Il est le résultat d’un calcul fait par la sonde sur l’ensemble des octets du message avant d’être ajouté en fin de trame. Lorsque la gateway va recevoir la trame, elle va recalculer le CRC-8 de l’ensemble du message et le comparer à celui qui est à la fin du message. Si les deux sont identiques, c’est que le message a été transmis correctement, sinon la gateway va simplement ne pas prendre en compte le message (et ne pas l’envoyer au serveur).

Analyse du paquet de réponse du serveur

Bon on est capable de récupérer tout ce qui nous intéresse dans les données que la sonde envoie et qui sont relayées par la gateway (à savoir la température et l’humidité pour ceux qui viennent d’arriver). Mais tout ça ne servira à rien si on est pas capable de répondre à la gateway de manière crédible, elle va simplement cesser d’envoyer des données car pour elle une réponse invalide équivaut à pas de réponse du tout. La gateway va d’ailleurs jouer une séquence d’allumage de led en façade pour signifier que le serveur est injoignable.

Alors regardons trois trames de réponse du serveur officiel:

5F… ça ne vous dit rien ? C’est encore une date unix sur 4 octets et c’est les seuls octets qui changent dans cette trame de réponse (si on exclut la date dans l’en-tête http). Trame de réponse qui a la même structure pour une réponse à un paquet de boot ou un paquet de transmission de données. Je ne connais pas l’utilité des autres octets non nuls qui sont dans dans cette trame (comme 0x17 0x61 0xD4 0x80) mais on s’en moque vu qu’ils ne changent jamais.

Finalement c’était facile, nous avons donc tout ce qui nous faut pour créer notre serveur factice, c’est ce que nous verrons dans la quatrième et dernière partie de ce sujet.

FAQ

Q: Qu’est ce qu’un flag ? 

A: On utilise généralement un flag pour indiquer qu’une option est activée ou pas. La particularité d’un flag est que, du fait qu’il ne peut prendre seulement 0 (false) ou 1 (true) comme valeur, on peut le faire tenir sur un seul bit. Et comme il y a 8 bits dans un octet on peut donc faire tenir 8 flags dans un seul octet ! Donc on peut faire contenir la valeur de 8 options dans un octet. Un flag permet (entre autre) de sauvegarder de l’espace mémoire : en utilisant un octet pour stocker 8 options booléennes à la place de 8 octets.

Q: Pourquoi peut-on stocker la valeur 3 sur seulement 2 bits ?

A: Sur un bit on peut stocker 2 valeurs (0 ou 1), et sur deux bits on peut stocker 4 valeurs :

0 0     0
0 1     1
1 0     2
1 1     3

Si par contre on veut la valeur 4 (pour monter jusqu’à 127,9°C [0x04FF]) il faut rajouter un bit supplémentaire et grâce à lui on peut monter jusqu’à la valeur 7 (mais je doute que les constructeurs de la sonde soient allés jusque là) :

0 0 0         0
0 0 1         1
0 1 0         2
0 1 1         3
1 0 0         4
...
1 1 0         6
1 1 1         7

 

Q: Pourquoi tu considères que l’octet n°3 fait partie de la température ?

A: C’est en réalité une erreur de ma part. Dans ma première analyse j’avais supposé que ces trois octets contenaient l’information sur la température parce qu’ils précédent l’octet sur l’humidité donc je ne voyais pas ce qu’ils pouvaient être d’autre. Mais il y a de grandes chances que le troisième octet ne contienne que des flags et n’ait aucun rapport avec la température.

Q: T’avais pas annoncé que le troisième article serait sur comment créer un serveur factice ?

A: Oui, mais j’ai menti. Ce sera pour le prochain, j’avais besoin de clôturer complètement la partie sur l’analyse avant de passer à la programmation du service.

 

 

 

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.