Mon para-monde - Mot-clé - reverse engineeringtout ce qui n'a pas d'importance impose d'être publié2023-05-28T10:37:08+01:00Fred Senisurn:md5:c0e6ee5eba086a402cc772eec16edf6eDotclearELV Max! Il est temps de passer commandeurn:md5:f785d412cf4477d63f6f0e0e4085da442012-03-19T09:24:06+00:002012-03-19T09:24:07+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>Excusez la blague à 2 balles, il n'est bien sûr pas question d'acheter quelque chose mais de trouver les commandes que le cube peut recevoir et les réponses qu'il peut fournir.</p>
<p>On a déjà vu quelques commandes :</p>
<ul>
<li><a href="http://blog.frederic.senis.org/index.php/2012/01/28/77-j-ai-decouvert-une-commande-de-plus-sur-elv-max-ben-j-aurais-prefere-m-en-passer-" hreflang="fr">"a:" qui remet le cube dans un état vide</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/02/05/78-elv-max-contenu-de-la-config" hreflang="fr">"c:" qui interroge le cube sur la config d'un périphérique</a>.</li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/02/05/79-elv-max-contenu-de-la-ligne-l-ive" hreflang="fr">"l:" qui demande le renvoi des données L:ive</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/02/13/81-elv-max-commande-s-syntaxe-generale" hreflang="fr">"s:" qui envoie des commandes de configuration aux périphériques</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/02/13/81-elv-max-commande-s-syntaxe-generale" hreflang="fr">"s: mode 0x11" pour le réglage des températures par défaut</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/03/18/82-quelques-ordres-s-" hreflang="fr">"s: mode 0x12" pour le réglage des caractéristiques de la valve</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/03/18/82-quelques-ordres-s-" hreflang="fr">"s: modes 0x20 et 0x21" pour le pairage de périphériques (thermostat mural et valve par exemple)</a></li>
<li><a href="http://blog.frederic.senis.org/index.php/2012/03/18/82-quelques-ordres-s-" hreflang="fr">"s: modes 0x22 et 0x23" pour l'installation dans les groupes/pièces</a></li>
</ul>
<p>Le sniffing du réseau et le classique essai/erreur permettent d'en trouver quelques autres :</p>
<ul>
<li><strong>"m:"</strong> qui modifie les données de la M:aison</li>
<li><strong>"z:"</strong> qui est envoyé avant un groupe de commandes</li>
<li><strong>"n:"</strong> qui met le cube en mode apprentissage</li>
<li><strong>"x:"</strong> annule une commande en cours de type "n:"</li>
<li><strong>"d:"</strong> et <strong>"e:"</strong> qui décodent et encodent une chaine binaire (quel algorithme ? mystère)</li>
</ul>
<p>Comme les lignes reçues, la macrosyntaxe est <lettre de commande>:<enchaînement de champs séparés par des virgules>.</p>
<p>Dans les champs, les données sont soit codées en hexadécimal ou en texte brut (p. exemple : "<strong>z:1e,G,02</strong>" ) soit encodées partiellement ou totalement en base64 (p. exemple : "<strong>s:AAAAiAAAAAPx4AAI=</strong>" )</p>
<p>Toutes les commandes que je trouverai seront rajoutées ici au fur et à mesure avec des liens vers chaque description.</p>https://blog.frederic.senis.org/index.php?post/2012/03/19/80-elv-max-il-est-temps-de-passer-commande#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/80Quelques ordres S: (S12,S20,S21,S22,S23)urn:md5:a47f4f406a8fa4875e5f9cfe3b763ae82012-03-18T22:17:45+00:002012-03-19T09:52:23+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>J'ai été très occupé ces derniers temps, pas eu trop le temps d'écrire les articles sur d'autres fonctions S:(end) de l'ELV Max!</p>
<p>En voici quelques unes :</p>
<p><strong>ConfigValve (Commande 0x12)</strong></p>
<pre>00 00
01 Bitfield : 76543210
10 = broadcast (?)
02 12 COMMANDE
03 00
04 00
05 00
06 AABBCC Adresse d'émission
07 ..
08 ..
09 XX RoomId
10 XX Configuration du Boost (1)
11 XX Configuration du cycle de détartrage (2)
12 XX Position Max de la valve
13 XX Position Min de la valve</pre>
<p>(1) La configuration du Boost se fait sur un octet sous forme de 2 champs de bits :</p>
<ul>
<li>3 bits pour la durée du Boost en tranche de 5min</li>
<li>5 bits pour l'ouverture de valve en tranche de 5%</li>
</ul>
<p>(2) Le détartrage se règle lui aussi sur un champ de 8 bits :</p>
<ul>
<li>3bits pour le jour (0=Samedi, 1=Dimanche... 6=Vendredi)</li>
<li>5bits pour l'heure de mise en route par tranche de 30 minutes</li>
</ul>
<p><strong>AddDirectLinkFromTo (0x20) et RemoveDirectLinkFromTo (0x21)</strong></p>
<pre>00 00
01 Bitfield : 76543210
10 = broadcast (?)
02 20/21 COMMANDE
03 00
04 00
05 00
06 AABBCC Adresse d'émission du périphérique référence
07 ..
08 ..
09 AABBCC Adresse d'émission du périphérique de pilotage
10 ..
11 ..
12 XX Type de périphérique</pre>
<p><strong>setGroupRFaddr (0x22) et removeGroupRFaddr (0x23)</strong></p>
<pre>00 00
01 Bitfield : 76543210
10 = broadcast (?)
02 22/23 COMMANDE
03 00
04 00
05 00
06 AABBCC Adresse d'émission du périphérique à ajouter ou retirer de la pièce
07 ..
08 ..
09 XX RoomId</pre>
<p>On a pas fini, il reste encore quelques commandes s:, en particulier le réglage des programmes journaliers (mode 0x10) et le changement de modes (mode 0x40) qui sont incontournables et un peu velus.</p>https://blog.frederic.senis.org/index.php?post/2012/03/18/82-quelques-ordres-s-#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/82ELV Max! commande "s:" syntaxe générale et commande de réglage des températures par défaut (0x11)urn:md5:3e12fa9abf4cfc7e1fc99e9074be03f82012-02-13T22:32:19+00:002012-02-14T11:17:48+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>La commande "s:" sert à envoyer une commande (send en anglais quoi).</p>
<p>Le format général est s:<chaine en base64></p>
<p>Pour illustrer voici la commande générée par la modification du décalage de température sur un thermostat dont l'adresse est 00fb6d.</p>
<pre>s:AAARAAAAAPttACoiPQkJGAM=</pre>
<p>Le décodage ramène une chaine binaire (ici en hexa) :</p>
<pre>00 00 11 00 00 00 00 fb 6d 00 2a 22 3d 09 09 18 03
#0 #1 #2 #3 #4 #5 #6 #7 #8 #9 #A #B #C #D #E #F #10</pre>
<p>Si on décortique, en premier lieu, on trouve tout de suite à partir de #6 une adresse de périphérique.</p>
<p>Une modification du même paramètre fait varier uniquement l'octet #E tandis que le changement d'autres paramètres de température font varier individuellement les autres octets de #A à #10.</p>
<p>Ces valeurs ne sont cependant pas encodées directement. Ainsi une température qui se règle par pas de 0,5° et encodée sous la forme T°x2 et le décalage de température qui peut aller de -3,5 à 3,5 est encodé par dT°x2+7 .</p>
<p>Au final voici le payload de la fonction 11(hex) :</p>
<pre>00 00
01 Bitfield : 76543210
10 = broadcast (?)
02 11 COMMANDE (ici réglage des températures par défaut)
03 00
04 00
05 00
06 AABBCC Adresse d'émission
07 ..
08 ..
09 XX RoomId
10 XX Température de comfort
11 XX Température éco
12 XX Température max réglable sur la tête
13 XX Température min réglable sur la tête
14 XX Décalage de température
15 XX Température lorsqu'une fenêtre est ouverte
16 XX Durée de la consigne de fenêtre ouverte</pre>
<p>Le retour de l'envoi d'une telle commande est une ligne "S:"</p>
<p>Celle-ci contient 3 champs séparés par des virgules :</p>
<pre>1 : Ce chiffre semble augmenter de temps en temps
2 : Succés/Echec (0/1)
3 : Ce chiffre diminue au maximum de 1 à chaque commande passée, il peut aussi augmenter le maximum est 30(hex) soit 48(dec).</pre>
<p>Je pense que les commandes sont envoyées aux têtes par bloc ou par cycles, le champ 1 identifie le bloc courant et le 3 le nombre d'emplacements libres dans ce bloc. C'est pour cela que le champ 3 ne diminue pas toujours ; des commandes sont envoyées en même temps que d'autres sont reçues.</p>https://blog.frederic.senis.org/index.php?post/2012/02/13/81-elv-max-commande-s-syntaxe-generale#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/81ELV Max! Contenu de la ligne L:iveurn:md5:f29dc9297d1b4b0a193c30ddcc3ee5002012-02-05T14:29:05+00:002012-02-05T20:26:36+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>A la différence des lignes de C:onfig qui sont aussi nombreuses qu'il y a de périphériques branchés, la ligne L:ive est unique. Tous les périphériques sont regroupés en une seule ligne.</p>
<p>Par ailleurs il n'y a pas d'information sur le cube dans la ligne L:</p>
<p><strong>Interogation du cube</strong></p>
<p>On peut demander une nouvelle ligne L:ive mise à jour par l'envoi de "l:" (L minuscule) suivi de CR+LF
Le cube répond alors par une ligne L: contenant les dernières données dont il dispose.</p>
<p><strong>Structure générale d'une ligne L:</strong></p>
<p>La ligne L: ne possède qu'un champ encodé en Base64</p>
<pre>par exemple :
L:CwD7bQASGEcpAAAA</pre>
<p><strong>Contenu du champ</strong></p>
<p>L'exemple ci-dessus se décode en :</p>
<pre>0b 00 fb 6d 00 12 18 47 29 00 00 00</pre>
<p>On repère tout de suite les octets 2,3,4 "00fb6d" correspondant à une adresse.
Par ailleurs, le premier octet contient 0x0b correspondant au nombre d'octets qui suivent (lorsqu'il y a plusieurs périphériques connectés, on retrouve à nouveau cette même structure <longueur><contenu> répétée autant de fois qu'il y a de périphériques.</p>
<p>On remarque aussi, pas mal d'octets à 0x00, ca va pas nous aider à dépiauter la bêêête mais ça s'arrange après avoir modifier des éléments de config <img src="/themes/default/smilies/smile.png" alt=":)" class="smiley" /> .</p>
<pre>Position Champ
0 1 octet = longueur du morceau de réponse suivant (je n'ai rencontré que des enregistrements de 11 caractères : 0x0b)
1 3 octets = Adresse
4 1 octet = ?
5 1 octet = ?
6 1 octet = ?
bits 1-2 = ?
bit 3 = Verrouillage clavier
bits 4-6 = ?
bits 7-8 = Mode
7 1 octet = Position de la valve (0-100)
8 1 octet = Température de consigne réglée sur la tête
9-10 2 octets = Date de fin
11 1 octet = Heure de fin</pre>
<p>Les octets 4-6 ne sont pas souvent modifiés par des actions par la webapp ou par modification des réglages de la tête, les seuls bits modifiés de façon synchrone sont sur l'octet 6 (bits 7 et 8) et correspondent au mode (0b00 : mode auto, 0b01 : mode manu, 0b10 : mode temporaire, 0b11 : mode Boost)</p>
<p>Date et heure ne sont valides que lorsqu'on est en mode "temporaire".</p>https://blog.frederic.senis.org/index.php?post/2012/02/05/79-elv-max-contenu-de-la-ligne-l-ive#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/79ELV Max! Contenu de la config (ligne C:)urn:md5:35b497c8207df7f4bd0b18095d3cca442012-02-05T11:44:52+00:002012-02-05T15:06:26+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>La ligne C: se décompose en 2 champs principaux. Outre l'entête "C:", on retrouve le code d'adressage en hexadécimal sur 6 caractères (donc une fois retransformé, sur 24bits) suivi d'une virgule et à nouveau un contenu encodé en Base64.</p>
<pre>C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==</pre>
<p>Voici donc la ligne correspondant au périphérique 007ead. Dans le cas présent, il s'agit du cube lui-même et je n'en étudierai pas la config tout de suite car peu intéressante, pour le plaisir voici le décodage (les données alphanumériques sont soulignées, le reste est en hexadécimal) :</p>
<p>ED <strong>007EAD</strong> 00 09 01 00 <ins>IEQ0112240</ins> 00 0B 00 04 40 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 0B 00 04 40 00 00 00 00 00 00 00 41 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF <ins>http://www.max-portal.elv.de:80/cube</ins> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <ins>CET</ins> 00 00 0A 00 03 00 00 0E 10 <ins>CEST</ins> 00 03 00 00 00 00 1C 20</p>
<p>On y découvre entre autre l'URL du backend du portail web (l'adresse du frontend est à http://www.max-portal.elv.de/ ).</p>
<p><strong>Intéressons-nous plutôt aux thermostats.</strong></p>
<p>La config est là-aussi contenue dans un champ encodé en base64. Celle-ci étant particulièrement longue, je vous en fait grâce et je vais me contenter d'en faire le détail :</p>
<pre>Position Champ
0 1 octet = ?
1 3 octets = Adresse
4 1 octet = Type de périphérique (0=Cube?, 1=Thermostat)
5 1 octet = ?
6 10 octets= Numéro de série (IEQXXXXXXX)
16 1 octet = Température de confort (*)
17 1 octet = Température Eco (*)
18 1 octet = Température maximale de réglage (4.5° soit 0x09 = valeur de 'off')
19 1 octet = Température minimal de réglage (30.5° soit 0x3d = valeur de 'on')
20 1 octet = Décalage de réglage température (*)
21 1 octet = Température en cas d'ouverture de fenêtre (*)
22 1 octet = Durée de changement de consigne en cas d'ouverture de fenêtre (*)
23 1 octet = bitfield de 8 bits
3 bits = durée du Boost (*)
5 bits = valeur de valve du Boost (*)
24 1 octet = bitfield de 8 bits
3 bits = Jour du cycle de détartrage de la valve (*)
5 bits = heure de détartrage de la valve (*)
25 1 octet = position maximum de la valve ? (255) peut-être dépendant du réglage initial de course
26 1 octet = position de départ de la valve ? (0) peut-être dépendant du réglage initial de course
27 début des programmes journaliers (7 groupes = 1 par jour) (*)
(*) les valeurs sont modifiables depuis la webapp</pre>
<p>Les températures sont exprimées en multiples de 0,5° (Température = Valeur/2)</p>
<p>La liste des jours commence le Samedi(=0 ???) jusqu'au Vendredi (=7)</p>
<p>Le décalage de température est exprimé en multiples de 0,5° à ajouter à -3,5° (Décalage = Valeur/2 - 3.5)</p>
<p>La durée du boost se calcule donc par Durée = (Valeur & 0xE0)>>5 et la valeur de valve par Valve = (Valeur & 0x1F)</p>
<p>Idem pour le détartrage : Jour = (Valeur & 0xE0)>>5 et Heure = (Valeur & 0x1F)</p>
<p>Un programme journalier est constitué de 26 octets, 13 blocs de 2 octets pour être plus précis soit 13 paliers programmables par jour.
Sur ses 16bits (composant les 2 octets MSB et LSB), sont encodées 2 grandeurs : la température de consigne et l'heure de fin.</p>
<pre>0TTTTTTH.HHHHHHHH</pre>
<p>La Température est à nouveau exprimée en multiple de 0,5 tandis que l'heure est exprimée en multiple de 5 minutes</p>
<p>Donc partant du principe qu'on lit les octets un par un, on a :</p>
<pre>Température = ((MSB & 0x7E)>>1)/2
Heure de fin = ((MSB & 0x01)*256+LSB)*0.5</pre>
<p>Il me reste donc 2 champs dont je n'arrive pas à comprendre la signification (0 et 5).</p>
<p><strong>Demander une ligne de C:onfig</strong></p>
<p>Il est possible de demander la ligne de configuration d'un périphérique spécifique si on connait son adresse.</p>
<p>Pour cela il faut envoyer la commande "c:" suivie de l'adresse en hexadécimal par exemple (terminer par CR+LF) :</p>
<pre>c:007ead
C:007ead,<........................></pre>
<p>Le résultat est la ligne C: telle qu'on peut la voir en haut de l'article. Si l'adresse est inconnue, il n'y a pas de réponse.</p>
<p><strong>Méthodologie</strong></p>
<p>La méthode pour repérer tout cela est principalement de lancer depuis l'interface web des commandes unitaires puis de récupérer la configuration immédiatement après afin d'isoler les différences et d'en tirer une signification.</p>
<p>Pour les champs non modifiables (température maxi ou min), il faut faire des essais ("si c'était une température, si je divise par 2 est-ce que ca donne une valeur qui a du sens ?") éventuellement avec le manuel pas loin</p>https://blog.frederic.senis.org/index.php?post/2012/02/05/78-elv-max-contenu-de-la-config#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/78J'ai découvert une commande de plus sur ELV Max!, ben j'aurais préféré m'en passer... :)urn:md5:bdf7a2be05459a24b0e648182de826f62012-01-28T13:05:03+00:002012-01-28T13:06:53+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>Alors que je bidouillais le Cube via netcat, j'ai lancé quelques commandes de la forme <lettre><:><cr><lf></p>
<p>Et bien, ca m'a permis de découvrir à mon corps défendant la commande "a:" que l'on peut désormais surnommer "Reset sauvage de toute les métadonnées".</p>
<p>4 petits caractères suffisent à ramener le cube dans un état immaculé :</p>
<pre>H:IEQ0112240,007ead,0109,00000000,2ee8c053,00,32,0c011c,0c2b
M:
C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==
L:</pre>
<p>On voit le champ M: vide, l'absence de données L:ive et une seule ligne de config pour le Cube lui-même...</p>
<p>La bonne nouvelle, c'est qu'après avoir fait le réapprentissage d'un thermostat, il semble que la config soit retrouvée (retéléchargée du la tête ?)</p>
<pre>H:IEQ0112240,007ead,0109,00000000,233903cd,04,32,0c011c,0d04
M:00,01,VgIBAQZCdXJlYXUA+20BAQD7bUlFUTAxODQ5OTkHQnVyZWF1MQEB
C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==
C:00fb6d,0gD7bQEBFP9JRVEwMTg0OTk5KiI9CQcYAzAM/wBESFUIRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERIVQhFIEUgRSBFIEUgRSBFIEUgRSBFIEUgREhUbETMVRRFIEUgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIERIVGxEzFUURSBFIEUgRSBFIEUgRSBFIEUgREhUbETMVRRFIEUgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIA==
L:CwD7bQASGEcpAAAA</pre>
<p>On peut noter au passage que le champ 6 de H: a changé (00 -> 04) mais je ne sais pas pourquoi..</p>https://blog.frederic.senis.org/index.php?post/2012/01/28/77-j-ai-decouvert-une-commande-de-plus-sur-elv-max-ben-j-aurais-prefere-m-en-passer-#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/77ELV MAX! Lignes Host (H:) et Maison (M:)urn:md5:79bf928501e74747fbe1437c3ed1eee82012-01-27T10:24:11+00:002012-01-27T11:42:18+00:00Fred SenisInformatiquedomotiqueelv maxreverse engineering <p>Revenons à l'étude de la réponse initiale du Cube Max!</p>
<p>Le format le plus global est :</p>
<ul>
<li>un ensemble de lignes commençant toutes par une lettre suivie d'un "deux points" lui même suivi d'un contenu</li>
<li>chaque ligne est terminée par un marqueur assez classique : cr/lf (carriage return/line feed)</li>
</ul>
<p>Voici ce que j'ai pu tirer pour l'instant des lignes H et M</p>
<p><ins><strong>H:</strong></ins></p>
<p>Contient des données très basiques sur le système :
Les champs du contenu sont séparés par des virgules</p>
<pre>H:IEQ0112240,007ead,0109,00000000,35e2322f,00,32,0c011b,0909</pre>
<p>que l'on peut découper en :</p>
<ul>
<li>IEQ0112240 = numéro de série du Cube (invariant dans la même installation, il est imprimé sous le cube), format alphanumérique</li>
<li>007ead = nombre constant (on le retrouve ailleurs sur la première ligne C:, on le verra plus tard), c'est donc d'une certaine manière un moyen d'adressage, format hexadécimal sur 3 octets</li>
<li>0109 = la version du microcode embarqué a priori (le code a changé après une mise à jour)</li>
<li>00000000 = euh comment dire... des zéros ?</li>
<li>35e2322f = un nombre variant totalement à chaque connexion, probablement un identifiant de connexion mais on ne le retrouve nulle par ailleurs, format hexadécimal sur un long (32bits)</li>
<li>00 = encore des 0... impossible d'en savoir la signification</li>
<li>32 = toujours 32 là aussi... impossible d'en tirer une conclusion</li>
<li>0c011b = là aussi un invariant</li>
<li>0909 = Est-ce que ca ne serait pas 9 heures 09 (si c'est le cas, le cube n'est pas à l'heure <img src="/themes/default/smilies/smile.png" alt=":)" class="smiley" /> ), à voir lorsqu'on passera</li>
</ul>
<p><ins><strong>M:</strong></ins></p>
<pre>M:00,01,VgIHAQdDdWlzaW5lAP4uAgtTYWxsZSBkJ2VhdQD99QMNQ2hhbWJyZSBMdWNhcwCWrAQTQ2hhbWJyZSBGcmVkIExvdWxvdQCZbwUGQnVyZWF1APttBg1TYWxsZSBkZSBiYWluAPx4BwVTYWxsZQCWkgcBAP4uSUVRMDE4NDgxMgdDdWlzaW5lAQEA/fVJRVEwMTg0NzQ0C1NhbGxlIGQnZWF1AgEAlqxJRVEwMTg2MTYyDUNoYW1icmUgTHVjYXMDAQCZb0lFUTAxODMzMTcTQ2hhbWJyZSBGcmVkIExvdWxvdQQBAPttSUVRMDE4NDk5OQZCdXJlYXUFAQD8eElFUTAxODUxNjYNU2FsbGUgZGUgYmFpbgYBAJaSSUVRMDE4NjExNw9TYWxsZSDDoCBtYW5nZXIHAQ==</pre>
<p>La ligne M: là aussi contient des champs séparés par des virgules. Et là aussi les 2 premiers sont invariants d'une connexion à l'autre (toujours 00 et 01)
Suit un champ beaucoup plus long qui semble codé mais on note qu'on a affaire à des caractères tous "imprimables" et qu'en fin de ligne on retrouve des "=" typiques du remplissage final en <a href="http://fr.wikipedia.org/wiki/Base64" hreflang="fr">base64</a></p>
<p>Si on décode ce 3ème champ comme du base64 on récupère en effet un contenu contenant des éléments reconnaissables et cohérents (les caractères non imprimables ont été supprimés) :</p>
<pre>V(...)Cuisine(...)Salle d'eau(...)Chambre Lucas(...)Chambre Fred Loulou(...)Bureau(...)Salle de bain(...)Salle(...)IEQ0184812 Cuisine(...)IEQ0184744 Salle d'eau(...)IEQ0186162 Chambre Lucas(...)IEQ0183317 Chambre Fred Loulou(...)IEQ0184999 Bureau(...)IEQ0185166 Salle de bain(...)IEQ0186117 Salle à manger(...)</pre>
<p>Dans ce contenu binaire on peut retrouver une certaine organisation : Il y a 3 sous-ensembles.</p>
<p><br />** un préambule de 2 octets au contenu inconnu
<br />** une structure décrivant les pièces (organisation logique)
<br />** une structure décrivant les périphériques (organisation physique)</p>
<p><ins>Format de la liste des pièces</ins></p>
<p>Le premier octet contient le nombre de pièces définies (roomCount).
A sa suite, on retrouve répétée <em>roomCount</em> fois une structure définissant une pièce :</p>
<ul>
<li>Nombre de caratères du nom de la pièce (1 octet)</li>
<li>Nom de la pièce (X octets cf supra)</li>
<li>ID de la pièce (1 octet)</li>
<li>3 octets dont le contenu ressemble au champ qualifié d'adressage sur la ligne H:, mais il ne semble pas utilisé (ID est utilisé ensuite)</li>
</ul>
<p>Immédiatement après la liste des pièces on attaque la liste des périphériques (thermostats)
Le principe est le même que la liste des pièces.</p>
<p><ins>Format de la liste des périphériques</ins></p>
<p>Le premier octet contient le nombre de périphériques définis (devCount).</p>
<p>La aussi on retrouve <em>devCount</em> fois une structure de périphérique :</p>
<ul>
<li>Type de périphérique (1 octet) 0=Cube, 1=Tête thermostatique, peut-être y en a t'il d'autres pour par exemple le thermostat mural (mais je n'en ai pas)</li>
<li>3 octets "d'adressage", le contenu de ce champ se retrouve comme premier champ des lignes C: suivantes permettant de les rattacher à un périphérique</li>
<li>10 octets de numéro de série</li>
<li>1 octet de nombre de caractères du nom du périphérique</li>
<li>Nom du périphérique (X octets ci-dessus)</li>
<li>ID de la pièce de rattachement (1 octet)</li>
</ul>
<p>Voilà, avec la ligne M: on peut construire la structure de notre maison.</p>
<p>La prochaine fois, je m'attaque à la ligne C: qui donne la config courante d'un périphérique.</p>https://blog.frederic.senis.org/index.php?post/2012/01/27/76-elv-max-lignes-host-h-et-maison-m-#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/76ELV MAX! Début d'explorationurn:md5:668a0d8c063fe0b9c1121f8faf7c7b092012-01-25T20:29:04+00:002012-01-25T20:34:22+00:00Fred SenisGeneraldomotiqueelv maxreverse engineering <p>Je vais vous épargner le détail de la méthodologie mais pour faire simple. Il faut sniffer le réseau entre l'appli java qui réside sur l'ordinateur et le boîtier. Pour cela, j'ai fait brutal (parce que bien sur l'appli ne marche que sous Windows) : j'ai intercalé un ordi entre les 2, mis en place l'IP forwarding et lancé mon fidèle wireshark (un logiciel de capture de trame réseau et d'analyse). On peut aussi bien sur capturer directement sur l'ordinateur "source".</p>
<p>Voici les premiers constats :</p>
<ul>
<li>l'appli se connecte à son lancement au cube sur le port 80, on se dit alors <em>Chouette il y a un serveur web embarqué</em>. Hélas on déchante vite car une fois l'appli connectée, impossible d'initier une autre connexion TCP/IP vers le port 80. Le cube ne supporte qu'un seul logiciel de commande à la fois...</li>
<li>il ne s'agit pas de HTTP non plus. En effet, toute connexion même sans envoi de requête génère une réponse du cube. Voici un exemple de réponse à l'ouverture d'une connexion (sans rien envoyer) :</li>
</ul>
<pre>H:IEQ0112240,007ead,0109,00000000,673a0152,00,32,0c0110,1306
M:00,01,VgIHAQdDdWlzaW5lAP4uAgtTYWxsZSBkJ2VhdQD99QMNQ2hhbWJyZSBMdWNhcwCWrAQTQ2hhbWJyZSBGcmVkIExvdWxvdQCZbwUGQnVyZWF1APttBg1TYWxsZSBkZSBiYWluAPx4BwVTYWxsZQCWkgcBAP4uSUVRMDE4NDgxMgdDdWlzaW5lAQEA/fVJRVEwMTg0NzQ0C1NhbGxlIGQnZWF1AgEAlqxJRVEwMTg2MTYyDUNoYW1icmUgTHVjYXMDAQCZb0lFUTAxODMzMTcTQ2hhbWJyZSBGcmVkIExvdWxvdQQBAPttSUVRMDE4NDk5OQZCdXJlYXUFAQD8eElFUTAxODUxNjYNU2FsbGUgZGUgYmFpbgYBAJaSSUVRMDE4NjExNw9TYWxsZSDDoCBtYW5nZXIHAQ==
C:007ead,7QB+rQAJAf9JRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwACAAAcIA==
C:00fdf5,0gD99QECFP9JRVEwMTg0NzQ0KCA9CQcYAzAM/wBESFiFRNhY8FEDRSBFIEUgRSBFIEUgRSBFIERIWIZE2VEDRSBFIEUgRSBFIEUgRSBFIEUgREhYbETeWORRAkUgRSBFIEUgRSBFIEUgRSBESFhsRN5Y5FD3RSBFIEUgRSBFIEUgRSBFIERIWGxE2VEDRSBFIEUgRSBFIEUgRSBFIEUgREhYbETeWORRAkUgRSBFIEUgRSBFIEUgRSBESFhsRNhRFUUgRSBFIEUgRSBFIEUgRSBFIA==
C:0096ac,0gCWrAEDFP9JRVEwMTg2MTYyKCA9CQcYAzAM/wBEYFD+RSBFIEUgRSBFIEUgRSBFIEUgRSBFIERgUP5FIEUgRSBFIEUgRSBFIEUgRSBFIEUgQElUYkDTUQVBIEEgQSBFIEUgRSBFIEUgRSBASVRiQNNRBUEgQSBBIEUgRSBFIEUgRSBFIERgUP5FIEUgRSBFIEUgRSBFIEUgRSBFIEUgQElUYkDTUQVBIEEgQSBFIEUgRSBFIEUgRSBASVRiQNNRBUEgQSBBIEUgRSBFIEUgRSBFIA==
C:00fb6d,0gD7bQEFFP9JRVEwMTg0OTk5KCA9CQcYAzAM/wBEVFEKRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERUUQpFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRRCkUgRSBFIEUgRSBFIEUgRSBFIEUgRSBEVFEKRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERUUQpFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRRCkUgRSBFIEUgRSBFIEUgRSBFIEUgRSBEVFEKRSBFIEUgRSBFIEUgRSBFIEUgRSBFIA==
C:00fc78,0gD8eAEGFP9JRVEwMTg1MTY2KCA9CQcYAzAM/wBFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRSBFIETRVPBFIEUgRSBFIEUgRSBFIEUgRSBFIEUgPSA9ID0gPSA9ID0gPSBFIEUgRSBFIEUgRSA9ID0gPSA9ID0gPSA9IEUgRSBFIEUgRSBFID0gPSA9ID0gPSA9ID0gRSBFIEUgRSBFIEUgPSA9ID0gPSA9ID0gPSBFIEUgRSBFIEUgRSA9ID0gPSA9ID0gPSA9IEUgRSBFIEUgRSBFIA==
C:00996f,0gCZbwEEFP9JRVEwMTgzMzE3KCA9CQcYAzAM/wBEYFR0ROpRFEUgRSBFIEUgRSBFIEUgRSBFIERgVHRE6lEURSBFIEUgRSBFIEUgRSBFIEUgREhUYkTSVQNFIEUgRSBFIEUgRSBFIEUgRSBESFRiRNJVA0UgRSBFIEUgRSBFIEUgRSBFIERgVHRE6lEURSBFIEUgRSBFIEUgRSBFIEUgREhUYkTSVQNFIEUgRSBFIEUgRSBFIEUgRSBESFRiRNJVA0UgRSBFIEUgRSBFIEUgRSBFIA==
C:00fe2e,0gD+LgEBFP9JRVEwMTg0ODEyKCA9CQcYAzAM/wBEVFR4UMBU8EUgRSBFIEUgRSBFIEUgRSBFIERUVHhQwFTwRSBFIEUgRSBFIEUgRSBFIEUgRE9UbUzbVPBFIEUgRSBFIEUgRSBFIEUgRSBET1RtTNtU8EUgRSBFIEUgRSBFIEUgRSBFIERPVG1M21TwRSBFIEUgRSBFIEUgRSBFIEUgRE9UbUzbVPBFIEUgRSBFIEUgRSBFIEUgRSBET1RtTNtU8EUgRSBFIEUgRSBFIEUgRSBFIA==
C:009692,0gCWkgEHFP9JRVEwMTg2MTE3KCA9CQcYAzAM/wBEVFUJRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERUVQlFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRVCUUgRSBFIEUgRSBFIEUgRSBFIEUgRSBEVFUJRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERUVQlFIEUgRSBFIEUgRSBFIEUgRSBFIEUgRFRVCUUgRSBFIEUgRSBFIEUgRSBFIEUgRSBEVFUJRSBFIEUgRSBFIEUgRSBFIEUgRSBFIA==
L:CwD99QkSGA0oAN0ACwCWrAkSGAAoAN8ACwD7bQkSGAAnANcACwD8eAkSGAAeAKkACwCZbwkSGAAqAP8ACwD+LgkSGC8qAM8ACwCWkgkSGGQqAMsA</pre>
<ul>
<li>Les paramètres comme on peut le voir ne sont pas très intuitifs, il va falloir creuser.</li>
<li>Certains éléments sont invariants et permettent d'avoir quelques indices : Le premier champ de la ligne H: reprend exactement le numéro de série situé sous le Cube. Je l'appelle ligne "Hôte" ("Host" en anglais)</li>
<li>L’enchaînement de ces lignes est immuable mais certains éléments varient beaucoup (par exemple le 5ème champ de la ligne H: différent à chaque reconnexion et ne semblant suivre aucune logique de progression) ou peu (Le contenu de la ligne L: )</li>
<li>Les données situées après la virgule des lignes C: sont probablement des données spécifiques à chaque élément du système (1 ligne par élément) car on trouve 8 lignes dans 2 formats (1 ligne dans 1 format et 7 dans un autre) et j'ai 7 thermostats et 1 cube. De plus la ligne H: qui contient le n° de série du Cube possède en champ 2 "007ead" présent en entête de la ligne C: dont le format diffère des autres. A priori ces données ne varient pas si on ne dérègle rien dans l'appli, j'imagine que ce sont les lignes de configuration. Petit nom, "Config".</li>
</ul>
<p>Il va falloir décoder ces lignes maintenant.</p>
<p>Si on continue de suivre le fil des événements réseaux, l'appli envoie des commandes "l:" qui entraînent la réémission d'une ligne "L:" qui au bout d'un certain temps peut discrètement varier. J'imagine qu'il s'agit des données "live", zou voila le nom trouvé.
La ligne M... faut voir...</p>
<p>Au final on se sent revenu au bon vieux temps où la place disque/réseau/ram était chère. On va pouvoir s'amuser ! <img src="/themes/default/smilies/smile.png" alt=":)" class="smiley" /></p>https://blog.frederic.senis.org/index.php?post/2012/01/25/75-elv-max-debut-d-exploration#comment-formhttps://blog.frederic.senis.org/index.php?feed/atom/comments/75