Select Page
CANBus logo

Nous allons nous pencher ici sur un challenge que nous a posé un client. Il s’agissait de reprendre un système domotique propriétaire et totalement fermé, pour l’interfacer avec une domotique ouverte: Home-Assistant. Le but était d’en faire un système intuitif, facilement modifiable par le client et bien plus évolutif sans contrainte, et sans changer tout le matériel. A la fin de cet article, vous saurez comment vous interfacez facilement avec une domotique CANBus type Spline / Innoxel en utilisant Home-Assistant et prendre la main sur le système.

Je commencerais par une présentation de l’existant et des informations que l’on a pu récolter, pour passer ensuite à l’étape pratique d’arriver à s’interfacer avec le système, pour finir avec le résultat obtenu dans Home-Assistant.

Le système existant, installé il y a une dizaine d’années, est assez inhabituel et pas des plus simples. La plateforme utilisée est une centrale AMX classique (NI-2100) qui pilote une passerelle CAN

Le CAN est un bus de terrain à faible débit sur une paire, ou un seul conducteur parfois, très utilisé dans le monde automobile et l’industriel, très similaire dans le principe au KNX. Il a été développé par Bosch dans les années 80).

CAN List

L’ensemble des interfaces entrées et sorties du système sont sur ce bus CAN, ce qui est très original pour de la domotique. La partie logicielle est faite d’après nos investigations avec une partie de code probablement générique installé dans le contrôleur AMX, et une partie personnalisée faite via un logiciel propriétaire (Smart-Control) de la société Spline qui vient en surcouche. Heureusement le client a eu lors de l’installation une copie du logiciel et du fichier du projet. Cela a permis de voir que le système fonctionne de façon assez similaire au KNX avec un ensemble d’interfaces d’entrées (contacts secs des boutons muraux, radars, sondes de température) et sortie de gradation de lumières, contrôle de stores et relais pour le chauffage. Chaque module est numéroté physiquement et dans le programme, cela devrait se retrouver dans les commandes CAN ensuite.

Un peu de recherche sur Internet nous a permis de découvrir que les interfaces CAN sont fabriquées par une boite Suisse Innoxel et utilisent le protocole non documenté Noxnet. Il va donc falloir « sniffer » le bus CAN pour voir si on peut arriver à décoder le protocole.

Modules CAN
Modules CAN
ESP-CAN Interface

Pour cela, on va utiliser ESPHome qui supporte le CAN nativement avec une interface standard pour le CAN à base de TJA1050 qui est une des puces les plus utilisées pour l’interfaçage CAN. Un simple petit assemblage rapide comme sur la photo ci-dessous (un ESP32-C3 de SeeedStudio et une interface CAN) et un petit bout de code ESPHome devrait nous permettre de facilement écouter ce qui se passe sur le bus. Attention le CAN n’est supporté que sur les ESP32, pas d’ESP8266 ou 8285.

canbus:
  - platform: esp32_can
    tx_pin: GPIO3
    rx_pin: GPIO33
    can_id: 4
    bit_rate: 100kbps
    use_extended_id: false
    on_frame:   
    - can_id: 0x000
      can_id_mask: 0x000
      then:
      - lambda: |-
          std::string b(x.begin(), x.end());
          ESP_LOGD("can id 0x42B ", "%s", &b[0] );

4 points importants pour le sketch ESPHome:

  • le can_id est l’adresse utilisée par ESPHome pour les messages envoyés sur le bus CAN. Pour le moment cela n’a aucune importance.
  • le bit_rate est la vitesse du bus, vous devez être à la bonne vitesse pour arriver à communiquer correctement. Ici on a trouvé la bonne vitesse dans le logiciel Spline.
  • le use_extended_id est parfois utilisé en CAN pour permettre la connexion d’un plus grand nombre d’équipements sur le bus CAN. Si vous êtes dans le mauvais mode, cela sera visible dans les logs d’ESPHome qui vous le dira.
  • on active les options de débuggage avancé pour voir tout le détail des messages CAN.

Une fois terminé le montage de l’ESP avec l’interface CAN et le flashage de l’ESP, il ne reste plus qu’à brancher les 2 fils de la sortie CAN au bus CAN de l’installation en respectant bien la polarité. On découvre alors que ça cause beaucoup sur le bus CAN de l’installation. En effet, même sans aucune activité dans la maison, une grande quantité de messages CAN passent en permanence (à un tel point que l’ESP nous dit que certains messages ont été tronqués/perdus car beaucoup trop de traffic).

 

 

La première idée est d’isoler la passerelle CAN du contrôleur AMX mais cela n’a pas grand effet, le traffic est toujours aussi important. On pense alors que cela pourrait être les sondes de température qui pourraient remonter en permanence des états. On décide donc pour commencer de se concentrer sur un appareil simple comme un interrupteur. On va donc surveiller le traffic CAN en manipulant frénétiquement un bouton pendant une trentaine de secondes pour arriver à trouver comment il émet les appuis/relachés.

[08:32:05][D][canbus:072]: received can message (#1) std can_id=0x41e size=2
[08:32:05][V][canbus:079]: can_message.data[0]=74
[08:32:06][V][canbus:079]: can_message.data[1]=33
[08:32:06][D][can id 41E:115]: t3
[08:32:08][D][canbus:072]: received can message (#1) std can_id=0x41e size=2
[08:32:08][V][canbus:079]: can_message.data[0]=54
[08:32:08][V][canbus:079]: can_message.data[1]=33
[08:32:08][D][can id 41E:115]: T3
[08:32:09][D][canbus:072]: received can message (#1) std can_id=0x223 size=2
[08:32:09][V][canbus:079]: can_message.data[0]=50
[08:32:09][V][canbus:079]: can_message.data[1]=46
[08:32:09][D][canbus:072]: received can message (#2) std can_id=0x42d size=2
[08:32:09][V][canbus:079]: can_message.data[0]=50
[08:32:09][V][canbus:079]: can_message.data[1]=46
[08:32:09][D][canbus:072]: received can message (#5) std can_id=0x41e size=2
[08:32:09][V][canbus:079]: can_message.data[0]=74
[08:32:09][V][canbus:079]: can_message.data[1]=33
[08:32:09][D][can id 41E:115]: t3
[08:32:09][D][canbus:072]: received can message (#6) std can_id=0x465 size=2
[08:32:09][V][canbus:079]: can_message.data[0]=6c
[08:32:09][V][canbus:079]: can_message.data[1]=3

Et là oh surprise, on remarque des messages sous la forme T ou t avec un chiffre. Quelques tests supplémentaires sur les boutons nous confirment effectivement qu’ils émettent tout simplement le message T pour l’appui et t pour le relâcher suivi du numéro de bouton appuyé (les boutons sont numérotés à l’envers de la position des boutons physiques donc le bouton 8 sur le clavier porte le numéro 0 et le bouton 1 le numéro 7 en CAN).  Si on simule par ESPHome l’envoi du même message sur le bus avec l’adresse qui apparaît dans les logs, le système Spline réagit bien et provoque la commande des lumières correspondantes à ce bouton. On est donc déjà en mesure de récupérer les états des boutons et par extension des radars des circulations qui fonctionnent selon le même principe.

Cela nous permet également maintenant de faire le lien entre les adresses des boîtiers CAN dans le logiciel Spline et celles des interfaces sur le bus. En effet, on peut rapprocher l’adresse CAN du message reçu de l’adresse que porte ce clavier dans le Spline. En jouant avec quelques autres claviers, la correspondance est vite trouvée:

L’étape suivante va maintenant consister à trouver comment se font les commandes de lumière et de relais. Pour cela on va utiliser les bargraphs de commande de la lumière qui sont présents sur l’écran tactile de l’installation. De cette façon on va mitrailler de commandes les gradateurs permettant de retrouver plus facilement les commandes correspondantes.

[19:44:36][D][canbus:078]: received can message (#1) std can_id=0x614 size=8
[19:44:36][D][can id 0x42B :103]: W2000004
[19:44:36][D][canbus:078]: received can message (#2) std can_id=0x614 size=8
[19:44:36][D][can id 0x42B :103]: W3100004
[19:44:36][D][canbus:078]: received can message (#3) std can_id=0x610 size=6
[19:44:36][D][canbus:078]: received can message (#4) std can_id=0x614 size=8
[19:44:36][D][can id 0x42B :103]: W1000004
[19:44:36][D][canbus:078]: received can message (#5) std can_id=0x610 size=6
[19:44:36][D][canbus:078]: received can message (#6) std can_id=0x62c size=8
[19:44:36][D][can id 0x42B :103]: W1000004

Cette fois-ci la syntaxe est un peu plus compliquée mais guère plus. En effet, le W indique une commande de gradation, puis un chiffre pour indiquer le numéro de circuit du boîtier CAN concernée, ensuite on a un niveau en pourcentage sur 3 caractères et pour finir un temps de rampe pour la gradation en secondes sur 3 caractères. Par exemple, W2000004 veut dire que l’on grade le circuit 6 (comme pour les boutons les circuits sont numérotés à l’envers), les 000 indiquent que l’on veut éteindre le circuit et 004 pour faire cela en 4 secondes. Quelques tests ont permis de déterminer que la gradation qui se fait vraiment en marche d’escalier est dû à la mauvaise qualité des gradateurs eux-même. On gérera donc la rampe de gradation par Home-Assistant et non via la fonction intégrée des gradateurs.

[19:44:02][D][canbus:078]: received can message (#1) std can_id=0x21b size=2
[19:44:02][D][can id 0x42B :103]: C0
[19:45:02][D][canbus:078]: received can message (#1) std can_id=0x21d size=2
[19:45:02][D][can id 0x42B :103]: C1

Pour les sorties tout ou rien type relais, la syntaxe est très proche des entrées tout ou rien avec cette fois-ci la lettre C pour indiquer un contacteur avec le numéro du circuit concerné comme précédemment. On va également retrouver la même logique pour les commandes de store qui utilisent U pour monter, D pour descendre et H pour l’arrêt suivi du numéro de circuit. Le système ne gère visiblement pas de position de stores et effectivement les commandes de stores présentes dans lo domotique ne font qu’ouvrir ou fermer en entier les stores sans position intermédiaire possible !
On a désormais tout ce qu’il faut pour pouvoir implémenter le CAN dans Home-Assistant avec des entités correspondants à chaque appareil ou circuit commandé. Cela permettra ensuite de nativement contrôler toutes les interfaces Spline directement depuis Home-Assistant et de pouvoir enlever le contrôleur AMX et le logiciel qui va avec. On disposera alors d’une domotique ouverte et totalement personnalisable selon les volontés du client voire par le client lui-même vu la simplicité de prise en main de HA.

  • Retour des boutons et autres entrées contact sec (Radar par exemple):
canbus:
  - platform: esp32_can
    tx_pin: GPIO3
    rx_pin: GPIO33
    can_id: 4
    bit_rate: 100kbps
    use_extended_id: false
    on_frame:   
    - can_id: 0x450  # ID du device CAN à écouter
      then:
        - lambda: |-
            std::string message(x.begin(), x.end());  
            if (message == "T3") {
              id(can_bus_button_state).publish_state(true);  // Bouton appuyé
            } else if (message == "t3") {
                id(can_bus_button_state).publish_state(false);  // Bouton relâché
            }

binary_sensor:
  - platform: template
    name: "bouton lumiere"
    id: can_bus_button_state

Ici on gère le bouton poussoir à l’adresse CAN 0x450 et câblé sur l’entrée 5 du module CAN. Désormais le bouton apparaîtra nativement dans HA et on pourra donc déclencher des automations ou autres en fonction de l’état du bouton.

  • Contrôle des circuits en tout ou rien (typiquement tout ce qui est relayage):
switch:
  - platform: template
    name: "Pompe piscine"
    optimistic: True
    turn_on_action: 
      - canbus.send: 
          data: "S6"
          can_id: 0x21D
    turn_off_action: 
      - canbus.send:
          data: "C6"
          can_id: 0x21D

On pilote dans cet exemple une pompe via un relais qui se trouve sur le 3ième relais de l’interface CAN qui est à l’adresse 0x21D. Cela remontera comme un simple bouton on/off automatiquement dans HA.

  • Contrôles des stores et volets roulants:
cover:
  - platform: time_based
    name: Canbus Test Cover
    id: TestCover
    device_class: shutter
    has_built_in_endstop: true
    open_action:
      - canbus.send:
          data: "U0"
          can_id: 0x211
    open_duration: 39s
    close_action:
      - canbus.send:
          data: "D0"
          can_id: 0x211
    close_duration: 36s
    stop_action:
      - canbus.send:
          data: "H0"
          can_id: 0x211

Pour les stores, on aura 3 commandes au lieu de 2 avec le U pour la montée, le D pour la descente et le H pour le stop. HA permettant de gérer les stores avec une tempo, on saura maintenant faire des presets pour par exemple ouvrir le volet ou le store à 50% (moitié ouvert…).

  • Contrôle des lumières en gradation (les circuits en on/off sont commandés comme des relais):
light:
  - platform: monochromatic
    name: "light1"
    id: light1
    output: output1
    default_transition_length: 3s

output:
  - platform: template
    id: output1
    type: float
    write_action:
      then:
        - if:
            condition:
              - light.is_off: light1
            then:
              - canbus.send:
                  can_id: 0x67C
                  data: "W2000000"  
        - if:
            condition:
              - light.is_on: light1
            then:
              - canbus.send:
                  can_id: 0x67C
                  data: !lambda |
                    char buf[128];
                    int brightness = static_cast<int>(id(light1).current_values.get_brightness ()* 100);
                    brightness = (brightness > 100) ? 100 : brightness;
                    int transfer_time = 0; # temps de transfert du can
                    sprintf(buf, "W2%03d%03d", brightness, transfer_time);
                    std::string s = buf;
                    return std::vector<unsigned char>(s.begin(), s.end());

La chaine à envoyer étant plus complexe ici, on doit passer par des Lambda dans ESPHome mais cela permet au circuit de lumère d’apparaitre de façon native dans HA. Comme on a vu précédemment que les effets de rampe sont très mal gérés par les gradateurs CAN, on garde le temps de gradation à 0 et cela sera géré par HA lui-même (c’est pas parfait mais malgré tout nettement mieux que gérer par le gradateur).

On dispose désormais de tous les outils pour rendre l’installation CAN totalement gérable par HA et de façon native car toutes les interfaces CAN vont désormais apparaître comme des entités natives dans Home-Assistant.
Cela permettra également une plus grande évolutivité du système car on peut désormais intégrer tout ce que permet Home-Assistant et de façon bien plus simple que le système Spline.

 

Ce travail d’investigation a été possible grâce à un de nos clients qui a accepté de payer le travail de recherche sans aucune garantie que cela soit concluant. Grâce à lui, les autres utilisateurs du système Spline peuvent ouvrir facilement leur système et le rendre bien plus interopérable et évolutif, et le tout à bien moindre coût.

Vous avez un système Spline ou Innoxel et vous souhaitez le faire évoluer vers un système bien plus évolutif et ouvert. N’hésitez pas à nous contacter.