Go Down

Topic: [résolu] Reverse engineering protocole thermopompe hayward (Read 3343 times) previous topic - next topic

plode

Juste une précision : Avec le checkSum calculé avec un modulo 256, il y a 77% des trames qui ont le checksum à 0.

atlas2003

Hoo, interessant. Merci pour l'info.


De mon coté je viens de finir mes tests, et le calcul du checksum des trames B utilise le même que celui des trames A.
J'ai juste testé 4 ou 5 frames, ca m'a donné 0 à chaque fois. A voir pour le module 256 vs 255 pour les trames B également.


J'ai donc toutes les pieces du puzzle dans les mains.

Je vais passer a un petit prototype arduino

plode


pour l'inversion : Idem, de mon côté (mais basé sur les entêtes et pas les délais entre trame) :

En inversant les trames (complement à 0xff ), quasiment toutes les trames qui n'étaient pas ok en checksum deviennent ok en checksum.

En particulier, il y a les trames qui commencent par 0x304e en non inversée et 0xcfb1 en inversé, on a l'horloge / date. sur les bytes de 2 à 9  (exemple de trame : cfb10000580202113100001e :  00005802021131 semble être un compteur de temps.

J'ai deux autres entêtes / trames qui, inversée, donnent un checksum nul :
(trame origine, trame inversée, checksum trame inversée) :

353535353535353535353551    cacacacacacacacacacacaae   0
82fffffefe7effff       7d00000101810000   0

atlas2003

Bon, j'arrête pour la journée, mais voici le debut du programme arduino qui ne fait pour le moment, seulement générer la trame dans une variable.

sketch arduino

supercc

Bonjour à tous,

par curiosité j'ai extrait les mots (suite de caractères ASCII (>=32 && <127)) des trames du post de plode #19 :

Code: [Select]

0N
Z#L
xN
yN
Pd
`rx====
Btnn
IVZ
xqt
xrt
ZPPdx


Je ne sais pas ci cela vous sera utile.

Si vous voulez je poste les 422 lignes de la représentation ASCII des trames.

plode

Bonjour à tous.

Merci @supercc
Effectivement la conversion en ascii des trames peut permettre
de décoder les trames, et c'est une bonne idée.
Surtout que le décodage que tu montre semble être porteur de sens.
Donc oui, il faut regarder ce que donne les trames en ascii.

Sinon j'ai avancé sur les checksum pour les trames issuent de ma PAC
(il peut y avoir des règles différentes pour d'autres versions de PAC Hayward ?)

J'ai 3 types de trames.

Les trames courtes de 9 bytes.
Dans ce cas, le CS est la somme des 7 bytes, du deuxième au 8ème, modulo 256 qui doit être égale au dernier et 9eme byte. Le premier byte ne participe pas au CS (ce qui est étonnant ...)

Les trames longues de 12 bytes, décodée avec la règle bit 1 si durée de HIGH = 1ms, 0 si 3ms.
Dans ce cas, le CS est la somme des 11 bits, incluant le 1er, modulo 256 qui doit être égale au dernier byte

Les trames longues de 12 bytes "inverses", ( bit 1 si 3ms, 0 si 1ms). On les obtiens en calculant
le complément à 255  (ie trame = 255-trame. Le CS se calcul comme le précédant.

Avec cette règle de checksum, quasiment toutes mes trames ( > 99,9%) sont ok. C'est rassurant.

Du coup, pour la conversion en ascii, il faut inverser certaines trames avant de faire la conversion.

A suivre...

 


supercc

#36
Aug 26, 2019, 01:09 pm Last Edit: Aug 26, 2019, 01:22 pm by supercc
Quote
Du coup, pour la conversion en ascii, il faut inverser certaines trames avant de faire la conversion.
Je n'ai pas trop compris mais ce n'est pas grave, t'embête pas à m'expliquer, reste concentré, je ne compte pas rentrer dans les subtilités du protocole ;-)

Voici le script shell utilisé : il accepte en argument le nom du ficher contenant les trames au format de ton post #19. (il commence par éliminer les lignes contenant "not a correct trame" et utilise 2 fichiers temporaires : /tmp/test-data.txt et /tmp/test-out.txt).

Code: [Select]
#!/bin/bash

toAscii() {
local l
while read l; do
set - $l
printf "      "
for i; do
d=$((16#$i))
if [ $d -ge 32 -a $d -lt 127 ]; then
printf "%b" \\x$i
else
printf " "
fi
done
echo
done
}

convert() {
local l
while read l; do
echo $l | sed -re 's/(..)/\1 /g'
done | toAscii
}

# Argument ou entrée standard ?

IN=""
[ -n "$1" ] && IN=$1;

cat $IN | grep -v "not a correct trame" > /tmp/test-data.txt

cat /tmp/test-data.txt | sed -re 's/^.* "(.*)"/\1/' | convert > /tmp/test-out.txt

paste -d '\n' /tmp/test-data.txt /tmp/test-out.txt

echo
echo Words :

cat /tmp/test-out.txt | grep -v '\[' | sed -re 's/\ /\r/g' | sort -u


 

atlas2003

Merci pour le décodage en ascii.
J'en apprend tous les jours!


Aussi, je comprend maintenant le modulo 256. Ca explique pourquoi avec mon 255, je devais rajouter -3 et que ca ne fonctionnait pas tout le temps :)

Je pense pouvoir essayer mon prototype aujourd'hui si tout va bien. Je vous donne des nouvelles.

plode

Si joint la fonction R  (a faire en C pour l'arduino) qui test les 3 cas de trames pour le checkSum
(nb, en R, les tableaux commencent à l'indice 1. Le langage est vectoriel, donc sum(bt[1:n] fait la somme des bytes de 1 à n.
%% est l'opérateur modulo, <- l'affectation.


# Renvois True si le checksum est correct.
checkSumOk <- function(bt)
{
   n <- length(bt)
   if( n == 12) { # trame longue
      cs <- sum(bt[1:(n-1)])%% 256 - bt[n];
      if(bt[1] > 0x40)  # les trames "directes" semblent commencer par un byte qui est supérieur à 0x40,
         return(cs == 0)
      else # les trames inverses.. Attention, la séparation trame directe et trame inverse basée sur 0x40 est peut être fausse.
         return( (cs + 10) %% 256 == 0)
   # en bit inverse, on ajoute 11 fois 255 et on retranche 1 fois 255,
        # soit un bilan de (11-1)*-1 en modulo 256
   # c'est à dire un cs de -10 par rapport au calcul du cs direct.
   }
   if( n == 9) {  # trame courte
      cs <- sum(bt[2:(n-1)])%% 256 - bt[n]
      return(cs == 0)
   }
   return(F)
}

Avec cette fonction, j'ai 99,95% des trames qui sont ok.
Les trames de 12 bytes directes seraient envoyées par la carte mere de la PAC ?
Les trames de 12 bytes indirectes seraient envoyées par la carte contrôleur (le clavier de contrôle) ?
Les trames de 9 bytes sont envoyées par ???
Pour savoir, il faudrait déconnecter le bus "Net" et regarder les trames ?

A bientôt ... et dans l'attente du programme de atlas2003




atlas2003

Bon, je n'ai pas terminé mais le bilan est quand même positif.

J'ai terminé toute la partie qui génère la trame de commande (les trames B)
Je n'ai pas pu la tester la sur la thermopompe directement mais j'ai pu la recapturer avec mon analyseur logic, puis la repasser la capture dans le même script.

Résultat des courses: j'ai exactement les même résultats entre les vrai captures et ma version qui génère la trame à partir de commande MQTT.

Par contre c'est instable, car je me rend compte que j'ai du reset du watchdog de manière aléatoire du fait qu'il n'y a pas assez de yield dans mon programme et que j'utilise delayMicrosecond.

Bref, ca avance :)


atlas2003

Bonjour / bonsoir à ceux qui suivent le topic.

J'ai corrigé mes bugs de wdt reset et j'ai fais mon premier essais reel ce soir.
Malheureusement, ça n'a pas fonctionné!

J'ai tenté de changer la température programmé, et la thermopompe n'a rien changé du tout :(

Évidement, je ne m'avoue pas vaincu pour autant.

Pendant mes tests, j'ai capturé les trames pour analyser le tout par la suite.
Pour le moment, j'ai 2 idées qui me viennent à l'esprit:
Je fais une pause de 2 secondes à la fin de mes 8 trames. Peut être qu'il ne faudrait pas. Peut etre que je devrais la faire plus petite, car pendant que la pause en cours (c'est une pause à l'etat HIGH), la carte pc1000 ne peut donc "pas parler" durant ce temps.

Autre théorie: J'utilise un esp8266. Du coup, ses I/O fonctionnent en 3.3v. Si mes souvenirs sont exact, j'avais mesuré du 5v sur la PC1000. Je vais essayer d'ajouter un transistor pour passer la sortie de la pin qui génère la trame en 5V.

Sinon c'est sur, il y a peut être une erreur dans le protocole... ou dans la trame, que j'aurais raté.


Mon analyser logic est 5v tolerant, alors pour lui, du 5v ou du 3.3v, c'et pareil. Mais peut être pas pour la thermopompe.

A suivre...



plode

Bonjour,

C'est sur que ce n'est pas facile. Pourtant ça doit être possible puisque c'est ce que fait le module SmartTemp de Hayward.

Pour le voltage : De mon coté, le signal sur "NET" est du 5v, et le fils d'alimentation est en 12V.

Sinon, pour essayer de comprendre le dialog entre la carte mère de la PAC et le contrôleur, et en particulier savoir qui envois telle ou telle trame, je suis en train de faire un petit programme "Man In The Middle" : J'ai "coupé" le fil NET. L'extrémité PAC est branché sur la pin D2 de l'uno , l'extrémité contrôleur (CTL) est banché sur la pin D3. Quand l'uno reçoit un signal sur une PIN (D2 ou D3), il la recopie sur l'autre PIN et l'envois à mon serveur. J'ai fait le programme mais je n'ai pas pu le tester par manque de temps. Je le joint ci-dessous, sans savoir si il marche de mon côté.

A bientôt


atlas2003

Ha! Tres bonne idées.
J'ai hâte de voir tes captures avec ça.

De mon côté également j'ai un problème de "temps" même si j'aimerais y passer des journées dessus :)

Moi ma thermopompe n'est pas ouverte. J'ai fait passer deux fils (GND et net) dans mon cabanon. Alors forcément, c'est plus dur de faire le "man in the middle" :) surtout que ces temps ci il pleut toute la journée...

J'aimerais vraiment faire fonctionner le tout bientôt car la saison est presque terminé ici au Canada.

Je pense me souvenir que j'avais acheté il y a quelques années des level shifters. Je vais regarder si j'en ai encore pour tester avec le 5v.

Quand tu auras fais ton test et tes captures, ça me permettra aussi de connaître les vrais temps de pause et savoir qui les genere.

Merci!




atlas2003

Et voila! 5 ans se sont écoulé entre aujourd'hui et le premier commentaire de ce post.

Le projet touche bientôt à sa fin ! Tout fonctionne à merveille.

C'était bien juste le problème du 3.3v. Une fois le level shifter ajouté, j'arrive a controller la thermopompe à distance et cela à l'air de fonctionner dans 100% des cas.

Demain, je prendrais le temps de mettre le repo GIT à jour avec la nouvelle version de mon programme.

Un GROS merci a la communauté Arduino et à toutes les personnes qui ont participé à ce post, en particulier Plode!




Go Up