" /> Informatique - février 2012 - Mon para-monde
Flux RSS

lundi 13 février 2012

ELV Max! commande "s:" syntaxe générale et commande de réglage des températures par défaut (0x11)

La commande "s:" sert à envoyer une commande (send en anglais quoi).

Le format général est s:<chaine en base64>

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.

s:AAARAAAAAPttACoiPQkJGAM=

Le décodage ramène une chaine binaire (ici en hexa) :

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

Si on décortique, en premier lieu, on trouve tout de suite à partir de #6 une adresse de périphérique.

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.

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 .

Au final voici le payload de la fonction 11(hex) :

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

Le retour de l'envoi d'une telle commande est une ligne "S:"

Celle-ci contient 3 champs séparés par des virgules :

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).

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.

dimanche 5 février 2012

ELV Max! Contenu de la ligne L:ive

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.

Par ailleurs il n'y a pas d'information sur le cube dans la ligne L:

Interogation du cube

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.

Structure générale d'une ligne L:

La ligne L: ne possède qu'un champ encodé en Base64

par exemple :
L:CwD7bQASGEcpAAAA

Contenu du champ

L'exemple ci-dessus se décode en :

0b 00 fb 6d 00 12 18 47 29 00 00 00

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.

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 :) .

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

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)

Date et heure ne sont valides que lorsqu'on est en mode "temporaire".

ELV Max! Contenu de la config (ligne C:)

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.

C:007ead,7QB+rQAJAQBJRVEwMTEyMjQwAAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly93d3cubWF4LXBvcnRhbC5lbHYuZGU6ODAvY3ViZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwAAAAAcIA==

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) :

ED 007EAD 00 09 01 00 IEQ0112240 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 http://www.max-portal.elv.de:80/cube 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 CET 00 00 0A 00 03 00 00 0E 10 CEST 00 03 00 00 00 00 1C 20

On y découvre entre autre l'URL du backend du portail web (l'adresse du frontend est à http://www.max-portal.elv.de/ ).

Intéressons-nous plutôt aux thermostats.

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 :

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

Les températures sont exprimées en multiples de 0,5° (Température = Valeur/2)

La liste des jours commence le Samedi(=0 ???) jusqu'au Vendredi (=7)

Le décalage de température est exprimé en multiples de 0,5° à ajouter à -3,5° (Décalage = Valeur/2 - 3.5)

La durée du boost se calcule donc par Durée = (Valeur & 0xE0)>>5 et la valeur de valve par Valve = (Valeur & 0x1F)

Idem pour le détartrage : Jour = (Valeur & 0xE0)>>5 et Heure = (Valeur & 0x1F)

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.

0TTTTTTH.HHHHHHHH

La Température est à nouveau exprimée en multiple de 0,5 tandis que l'heure est exprimée en multiple de 5 minutes

Donc partant du principe qu'on lit les octets un par un, on a :

Température = ((MSB & 0x7E)>>1)/2
Heure de fin = ((MSB & 0x01)*256+LSB)*0.5

Il me reste donc 2 champs dont je n'arrive pas à comprendre la signification (0 et 5).

Demander une ligne de C:onfig

Il est possible de demander la ligne de configuration d'un périphérique spécifique si on connait son adresse.

Pour cela il faut envoyer la commande "c:" suivie de l'adresse en hexadécimal par exemple (terminer par CR+LF) :

c:007ead
C:007ead,<........................>

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.

Méthodologie

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.

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