Probabilmente avete letto il primo articolo che spiegava come hackerare a basso livello la vostra pompa di calore Daikin HPSU Compact grazie alla squadra formata da Raspberry Pi, PiCAN2, Python e python-CAN.
E’ venuto ora il momento di capire quali dati transitano sul bus dati CAN-Bus della pompa di calore al fine di poterli comprendere ed utilizzare. Materia ostica e noiosa ma fondamentale per poter procedere.
La doverosa premessa è che tutto quanto descritto in questo articolo è esclusivamente frutto di zanac. Che ha passato ore “sniffando” dati e determinandone empiricamente la semantica (partendo da un semilavorato trovato in un forum tedesco). Inoltre le operazioni di scrittura sul bus non sono ancora state esplorate fino in fondo.
Se pensi di aver trovato un approccio troppo complesso, ti invito a leggere in alternativa fin dove mi sono spinto in termini di ottimizzazione del riscaldamento sulla mia pompa di calore Daikin HPSU Compact con un approccio tradizionale in Pompa di calore Daikin HPSU Compact: curva climatica inversa a 4 scorrimenti.
CAN-Bus, python-CAN, Python e scheda PiCAN2
Il Controller Area Network, noto anche come CAN-Bus, è uno standard seriale per bus di campo (principalmente in ambiente automotive), di tipo multicast, introdotto negli anni ottanta dalla Bosch.
Lo standard CAN-Bus, a differenza del procollo TCP/IP utilizzato su internet, non prevede per i messaggi che transitano un indirizzo del nodo mittente e uno per il nodo destinatario, ma semplicemente l’identificativo del nodo CAN-Bus sorgente.
Un messaggio CAN-Bus transita infatti su tutto il bus e viene ricevuto da tutti i nodi collegati, è compito del singolo nodo gestire, se di interesse, il messaggio.
Questa architettura facilita di molto il lavoro di intercettazione (sniffing) dei dati che transitano: ogni periferica ha la piena visibilità di tutto quanto transita sul bus.… è per questo motivo che risulta facile sniffare comandi: ogni periferica connessa al CAN-Bus ha piena visibilità di quanto transita nel bus.
Non a caso ho riportato uno schema concettuale di un’automobile che utilizza proprio il CAN-Bus reso disponibile a chiunque tramite una presa OBD2 (On Board Diagnostic).
Suggerisco questa lettura: Cosa succede se un hacker prende il controllo di un’auto a distanza.
Sniffing messaggi CAN-Bus Daikin HPSU Compact tramite PiCAN2
La pompa di calore Daikin HPSU Compact implementa il CAN-Bus nella variante 11 bit (base format); lo standard CAN stabilisce che i device debbano tollerare anche la variante a 29 bit (extended) senza andare in errore.
Essendo un protocollo aperto abbiamo almeno un piccolo vantaggio in partenza. Ma come vedremo piccolo.
Tralasciando i campi tecnici, il formato base di un messaggio è essenzialmente composto da:
- un identificatore di dati (ID)
- un campo dati (Data) che può essere lungo sino a 8 byte
La lunghezza del campo dati del messaggio è detta DLC.
Nella pompa di calore Daikin HPSU Compact tutti i campi dati sono da 7 byte (DLC = 7) e quindi occorre tenerne assolutamente conto quando si spediscono i dati alla macchina.
All’interno della libreria python-CAN è disponibile uno script che consente di aggregare i messaggi che transitano sul CAN-Bus in base al loro identificativo ID
in modo da avere statistiche sulla loro frequenza:
python3 -m can.viewer -c can0 -i socketcan
Lasciando girare questo script per qualche minuto mentre la nostra pompa di calore aria acqua Daikin HPSU Compact si trova in modalità riscaldamento senza intervenire in alcun modo sul suo pannello di controllo troviamo ad esempio questo output con un elenco di messaggi transitati sul CAN-Bus:
Count Time dt ID DLC Data
83 1144.665077 59.979867 0x10A 7 31 00 FA C0 B4 00 00
229 1147.443998 2.7622953 0x180 7 20 0A 0C 00 45 00 00
59 844.042803 0.01214224 0x300 7 20 0A FA 01 1A 00 00
36 842.115780 0.00595495 0x500 7 20 0A 61 01 00 00 00
21 843.939823 0.01195700 0x600 7 20 0A 57 00 00 00 00
21 904.953210 0.00580325 0x780 7 B0 79 FA 01 22 1D 00
Dove:
Count
è il numero di volte che un messaggio con quell’ID
è stato ricevutoTime
è il time-stamp dell’ultimo messaggio ricevuto con quell’ID
dt
è la differenza di tempo tra gli ultimi due messaggi ricevuti con quell’ID
ID
è l’identificato del messaggio (formato esadecimale)DLC
è la lunghezza del messaggio in byteData
sono i dati contenuti nell’ultimo messaggio di quell’ID
(formato esadecimale)
Il campo dati contiene una sequenza di byte con una semantica applicativa ben precisa specifica del sistema che utilizza il bus: vediamo il caso specifico della Daikin HPSU Compact limitatamente a quello di cui è stato possibile fare reverse engineering.
Possiamo notare nel primo esempio come ci siano alcuni identificativi con una numerosità decisamente più alta degli altri: è probabile che siano i dati scambiati per aggiornare frequentemente le informazioni visualizzate sul display del pannello di controllo nella schermata correntemente selezionata.
Come primo esperimento ho lasciato il pannello di controllo controllo della macchina fermo su questa schermata per molte decine di minuti:
Il risultato è il seguente:
Count Time dt ID DLC Data
3043 2190.429196 0.005633 0x10A 7 31 00 FA C1 01 00 00
3352 2190.462394 0.005885 0x180 7 22 0A FA C1 01 03 6D
127 2178.270777 0.00625344 0x300 7 20 0A FA 01 1A 00 00
78 2176.428710 0.01096660 0x500 7 20 0A 61 01 00 00 00
45 2178.186774 0.01193118 0x600 7 20 0A 57 00 00 00 00
36 1995.233171 0.01105037 0x780 7 B0 79 FA 01 22 1D 00
Esperimento ripetuto con questa seconda schermata:
Col risultato seguente:
Count Time dt ID DLC Data
3653 2641.662374 0.005546 0x10A 7 31 00 FA C1 01 00 00
3998 2641.732388 0.014217 0x180 7 22 0A FA C1 01 03 6D
148 2524.143194 0.00625052 0x300 7 20 0A FA 01 1A 00 00
84 2522.309635 0.00598129 0x500 7 20 0A 61 01 00 00 00
51 2524.082409 0.00587598 0x600 7 20 0A 57 00 00 00 00
45 2461.075303 0.00589475 0x780 7 B0 79 FA 01 22 1D 00
Come vedete da entrambi i casi, abbiamo due evidenze:
- ci sono solamente 6 identificativi distinti, probabilmente corrispondenti ai componenti della pompa di calore che comunicano tra di loro tramite il CAN-Bus
- la stragrande maggioranza dei messaggi scambiati ha identificativo ID
0x10A
e0x180
Facciamo allora un dump dei messaggi:
python3 can_logger.py -c can0 -v -i socketcan
Fermandoci alla prima “raffica”, che compare proprio con quelle coppie di identificativi, riordinando in base ad identificativo e poi timestamp abbiamo questo:
Timestamp: 1638210695.494380 ID: 010a S DLC: 7 31 00 fa c0 fc 00 00 Channel: can0
Timestamp: 1638210695.499678 ID: 010a S DLC: 7 31 00 fa c0 fd 00 00 Channel: can0
Timestamp: 1638210695.510810 ID: 010a S DLC: 7 31 00 fa c0 fe 00 00 Channel: can0
Timestamp: 1638210695.521915 ID: 010a S DLC: 7 31 00 fa c0 ff 00 00 Channel: can0
Timestamp: 1638210695.527504 ID: 010a S DLC: 7 31 00 fa c1 00 00 00 Channel: can0
Timestamp: 1638210695.533056 ID: 010a S DLC: 7 31 00 fa c1 01 00 00 Channel: can0
Timestamp: 1638210695.505260 ID: 0180 S DLC: 7 22 0a fa c0 fc 01 23 Channel: can0
Timestamp: 1638210695.516309 ID: 0180 S DLC: 7 22 0a fa c0 fd 01 ad Channel: can0
Timestamp: 1638210695.538606 ID: 0180 S DLC: 7 22 0a fa c0 fe 01 15 Channel: can0
Timestamp: 1638210695.548981 ID: 0180 S DLC: 7 22 0a fa c0 ff 00 36 Channel: can0
Timestamp: 1638210695.554933 ID: 0180 S DLC: 7 22 0a fa c1 00 01 05 Channel: can0
Timestamp: 1638210695.560883 ID: 0180 S DLC: 7 22 0a fa c1 01 03 9a Channel: can0
Ovvero 6 messaggi con ID 010a
ed altrettanti con ID 0180
leggermente sfalsati nel tempo.
Formato messaggi CAN-Bus Daikin HPSU Compact
Direi che abbiamo fatto bingo provando ad intuire la semantica dei messaggi scambiati sul CAN-Bus della pompa di calore Daikin HPSU Compact:
- i 6 messaggi corrispondono esattamente ai 6 valori visualizzati sul display del pannello di controllo
- a 6 messaggi di richiesta (con ID
010a
) corrispondono 6 messaggi di risposta (con ID0180
) - tutti i messaggi di richiesta hanno i primi 3 byte identici (
31 00 fa
) - tutti i messaggi di richiesta hanno i primi 3 byte identici (
22 0a fa
) - il terzo e quarto byte del messaggio sono identici tra richiesta e risposta, probabilmente per indicare il parametro
- il sesto ed il settimo byte del messaggio di richiesta sono vuoti
- il sesto ed il settimo byte del messaggio di risposta hanno valori differenziati, probabilmente contengono il valore effettivo del parametro richiesto
E’ quindi presumibile che il funzionamento sia il seguente:
- il pannello di controllo della pompa di calore richiede via messaggi sul CAN-Bus i valori aggiornati dei parametri da visualizzare
- la scheda principale della pompa di calore recepisce la richiesta e pubblica i messaggi di risposta con i valori aggiornati sul CAN-Bus
- il modulo pannello di controllo della pompa di calore visualizza i dati così ricevuti
Questo si chiama reverse engineering che dobbiamo provare a sintetizzare.
Identificativo
Per quanto nello standard CAN-Bus non ci sia un concetto di indirizzo, è probabile che nell’implementazione della pompa di calore Daikin HPSU Compact corrisponda al componente che ha depositato il messaggio.
Una possibile interpretazione è la seguente:
ID Messaggio CAN-Bus | Componente Daikin HPSU Compact |
---|---|
0x10A | Pannello di controllo |
0x180 | Scheda principale pompa di calore |
0x300 | |
0x500 | |
0x600 | |
0x780 |
Ritengo che questi valori siano definiti in fase di configurazione iniziale della pompa di calore e dipendenti anche dalla presenza di accessori esterni collegati via CAN-Bus, come ad esempio il comando remoto termostato ambiente RoCon U1.
Primo byte
- Il primo semi-byte contiene il nodo CAN di destinazione (da decodificare moltiplicandolo per 0x80)
- Il secondo semi-byte indica se il messaggio e’ in lettura (1) oppure risposta / scrittura (2); la differenziazione tra risposta e scrittura viene poi fatta mediante il secondo byte
Vediamolo con un paio di esempi concreti:
- 0x31 ⇒ comando di lettura spedito al nodo CAN 0x180 (0x3 * 0x80)
- 0x22 ⇒ risposta o scrittura dal nodo CAN 0x180 (0x2 * 0x80)
Secondo byte
- Comando di lettura: è valorizzato fisso a 0x00
- Risposta a comando di lettura: vale 0x10 oppure 0x0a (non ancora chiara la differenza)
- Comando di scrittura: è valorizzato fisso a 0x00 (non ancora verificato se vale per tutti i casi)
Terzo byte
- Valorizzato a 0xfa: se il comando o la risposta è di lettura (vedi primo/secondo byte), significa che il parametro applicativo oggetto di lettura è codificato nei due byte successivi (4 e 5)
- Altro valore: il parametro applicativo è codificato direttamente nel terzo byte stesso
Prendiamo di nuovo un paio di esempi concreti:
Dati (Esadecimale) | Significato |
---|---|
31 00 FA 01 D6 00 00 | Comando lettura dal nodo 0x180 del parametro 01 D6 |
31 00 0E 00 00 00 00 | Comando lettura dal nodo 0x180 del parametro 0E |
Quarto / quinto byte
- Lettura “non 0xFA”: 0x00 0x00 (non rilevanti)
- Risposta “non 0xFA”: contengono il valore applicativo richiesto (con rappresentazione su due byte; sia valori positivi che negativi)
- Lettura / Risposta / Scrittura “0xFA”: contengono il parametro applicativo oggetto di lettura / risposta (secondo un dizionario predefinito)
Sesto / settimo byte
- Risposta / Scrittura “0xFA”: contengono il valore applicativo oggetto di risposta o di scrittura
La Stele di Rosetta grazie a PiCAN2
Nonostante tutte le meravigliose premesse ed informazioni precedenti, siamo comunque di fronte ad un flusso di informazioni binarie la cui semantica deve essere compresa.
Penso che zanac all’inizio si sia sentito come di fronte alla Stele di Rosetta (mi piace più questa metafora che parlare di reverse engineering).
La stesura del dizionario di transcodifica tra valori binari/esadecimali ed i parametri applicativi, scolpito da qualche parte nel firmware della nostra pompa di calore Daikin HPSU Compact, non è comunque tutto, occorre pure scoprire:
- codifica dei valori applicativi negativi (come la temperatura esterna ad esempio)
- codifica dei valori applicativi multi-valore (come la modalità corrente di funzionamento)
- assegnazione degli indirizzi dei nodi CAN-Bus che compongono il sistema (Unita’ interna, unita’ esterna, ecc.)
Esempi di messaggi catturati con PiCAN2
Per chiudere con la speranza in una prossima puntata di questa storia, qualche esempio completo di messaggio interpretato grazie a Raspberry Pi, PiCAN2 e tanta pazienza:
Dati | Comando | Parametro |
---|---|---|
31 00 16 00 00 00 00 | Lettura temperatura di ritorno | N/A |
32 10 16 00 DF 00 00 | Risposta temperatura di ritorno | 00 DF (223 decimale, ovvero 22,3 ºC) |
61 00 FA 0A 0C 00 00 | Lettura temperature esterna | N/A |
62 10 FA 0A 0C FF 69 | Risposta temperature esterna | FF 69 (-115 decimale, ovvero -11,5 ºC) |
Mi raccomando di continuare la lettura della puntata successiva Daikin HPSU Compact hack: terza parte.
Nel caso vi capiti con frequenza di bruciare la SD Card del vostro Raspberry Pi leggere la mia soluzione in Raspberry Pi | Collegare hard disk esterno.
Leggi tutti i miei articoli su Raspberry Pi:
Ultimo aggiornamento Amazon Affiliate 2024-12-07 at 08:42
Buonasera
Qualcuno ha testato rotex gateway rocon g1 per Hpsu 508?
Consigliate?
Grazie
Dario
Ciao Dario,
acquistato e provato. E’ una prolunga dei comandi a bordo macchina.