Mon périple dans l'univers du 433Mhz

Pour écouter les ondes, il faut du matériel. Tu bluffes ? Non.

La première étape sera donc de trouver un matériel plutôt décent pour rendre notre voyage aux pays des ondes le plus confortable possible.

Où acheter un dongle SDR qui marche ?

En suivant les conseils (qui sont toujours très bons) de mon ami toujours habillé en noir (il se reconnaîtra), j'ai acheté mon dongle sur RTL SDR.

Le kit est arrivé rapidement et fonctionnel. Rien à signaler.

A ma surprise, il chauffe parfois un peu (voire beaucoup en été) mais ne m'a jamais lâché.

Mise à jour un an plus tard: Toujours pas cassé ... Vous pouvez y aller les yeux fermés sur un achat compulsif c'est du béton le machin).

Pour tester rapidement le matériel, il suffit d'installer gqrx et le pointer sur une radio FM de son choix. Si la musique est pourrie change de fréquence, mais le SDR est probablement fonctionnel !

Pour les curieux et autres petits malins qui voudraient écouter des ondes plus sensibles, régler votre panier d'achat à 2, 3 ou 4 items ... Cela en prend plusieurs pour décoder ce genre de chose.

Bref.

De mon côté, je veux juste décoder les paquets transmis sur les ondes par les divers appareils que je dispose à la maison. A savoir, une station météo, des sondes de température Canadian Tire et des capteurs de portes cheap ...

Le logiciel idéal pour ça est de loin rtl_433. Les autres sont de bonnes références pour apprendre à décoder les protocoles radio (lire l'article au complet si t'es motivé, tu vas voir c'est cool) ... Mais rtl_433 est de loin le plus complet en ce moment.

Pour commencer mes tests, j'ai installé rtl_433 sur mon laptop Fedora (De loin la meilleure distribution Linux). Non je déconne. Enfin presque pas en fait ...

Évidemment, l’outil n'est pas packagé dans l'OS de base, alors je me suis résolu à faire une contribution copr pour simplifier la job des suivants ... Peut-être toi ?

Pour info, copr c'est l'équivalent des ppa sur Ubuntu. Un dépôt dnf ou yum que tu ajoutes a ton système pour obtenir le fruit de mon travail.

$ sudo dnf copr enable tvass/rtl_433
$ sudo dnf install rtl_433

Le tour est joué.

La prise en main est assez simple, tu peux même le lancer sans argument et voir de suite dans ton terminal de hacker tout ce qui passe dans les ondes. Et effectivement, si tu n'habites pas sur une île déserte, il s'en passe pas mal normalement ... Et surtout beaucoup de voitures.

Dans mon setup de prod (tu peux rire camarade, ici c'est du serieux), j'ai prévu de dédier un Raspberry Pi 3 (qui dormait) sur lequel est branché le dongle usb SDR. Ce dernier décode tout ce qui lui passe sous le nez et l'injecte directement dans le message bus MQTT de la maison.

Du côté de Home Assistant, il suffira (je suis résolument optimiste) de configurer un sensor de type MQTT.

La boucle est bouclée.

Une fois de plus, rtl_433 n'est pas disponible dans les dépôts de base. Il faut l'installer à la main sur le Pi.

Étant moins à l'aise pour faire une contribution de package sur Raspi OS, je l'ai fait en Ansible ... (oui je gère tous les rpi en Ansible; Note pour plus tard, faire un article la-dessus.).

tl;dr Ansible se lance tous les jours, met à jour le dépôt Git, recompile rtl_433 et relance le service ...

J'utilise supervisord pour gérer le démarrage automatique de rtl_433. À toi de voir si ça te convient ...

#
# Deploy pi3sdr
#
- hosts: sdr
  gather_facts: no
  become_user: root
  tasks:
    - name: Creates log directory
      file:
        path: /home/pi/log/
        state: directory
        owner: pi
        group: pi
        mode: 0775  
    - name: Install packages with apt
      apt:
        name: "{{ item }}"
        state: present
        force_apt_get: true
      loop:
        - supervisor
        - git
        - libtool
        - libusb-1.0-0-dev
        - librtlsdr-dev
        - rtl-sdr
        - build-essential
        - autoconf
        - cmake
        - pkg-config
      become: yes
      tags: apt
    - git:
        repo: 'https://github.com/merbanan/rtl_433/'
        dest: /home/pi/work/rtl433
        update: true
    - file:
        path: /home/pi/work/rtl433/build
        state: directory
    - name: cmake
      shell: cmake ..
      args:
        chdir: /home/pi/work/rtl433/build/
    - name: make
      shell: make
      args:
        chdir: /home/pi/work/rtl433/build/        
    - name: Create supervisor configuration (rtl_433)
      template:
        src: templates/rtl433.conf.j2
        dest: /etc/supervisor/conf.d/rtl433.conf
        owner: root
        group: root
        mode: '0644'
      register: rtl433_supervisor
      become: yes
    - name: Restart supervisor
      service:
         name: supervisor
         state: restarted
      when: rtl433_supervisor.changed
      become: yes

Dans l'idée, on lance rtl_433 en lui indiquant le backend MQTT et le format/hiérarchie des messages souhaités.

templates/rtl433.conf.j2

[program:rtl433]
command=/home/pi/work/rtl433/build/src/rtl_433 -F "mqtt://192.168.1.3:1883,retain=0,devices=rtl433[/id]" -M newmodel -M protocol -M time:iso -l 0 -f 433920000
directory=/home/pi/work/rtl433/build/src/
stderr_logfile = /var/log/rtl433-err.log
stdout_logfile = /var/log/rtl433-stdout.log

Dans mon cas, je m'attends donc à recevoir des messages sur le bus MQTT de la forme rtl433/[id]/*.

Connecter rtl_433 et Home Assistant

Comme je le disais plus haut, la suite est plutôt simple. Home Assistant a cette fonctionnalité géniale de pouvoir gérer des sondes (éventuellement binaires) ou l`état est lu directement dans le bus de message.

  - platform: mqtt
    name: "Front Door Sensor"
    state_topic: "rtl433/12072/cmd"
    payload_on: "10"
    payload_off: "14"
    qos: 0
    device_class: opening

Je te laisse aller fouiner les docs de H-A, si certains champs ne te sont pas familiers, mais la partie intéressante c'est l'identifiant 12072, puis payload_on et payload_off. Oui ... device_class: c'est juste une icône.

La matériel radio génère habituellement un identifiant au hasard (?) à la mise sous tension et le garde jusqu’à la fin de sa vie (quand tu changes les piles).

Donc oui, quand tu vas changer les piles, tu vas aller mettre le nouvel identifiant dans la configuration de Home Assistant. Vu que c'est bien fait, H-A utilise des identifiants uniques (NON basées sur l'ID radio), tu ne perdra donc pas l'historique du bidule quand cela arrive.

Les payload sont donc les valeurs transmises par le capteur quand la porte s'ouvre ou quand elle se ferme. Cela ne bouge pas. C'est simple, tu filtres la-dessus pour déterminer l'état.

Maintenant que cela marche avec le capteur de la porte d'entrée, passons donc à la station météo. Mon modèle mesure la température, l'humidité et la vitesse du vent.

Fier de moi, après avoir fini de l'installer sur mon beau balcon Montréalais, c'est quand même la douche froide ...

Le modèle Lacrosse TX141W n'est pas inclus dans rtl_433 et le logiciel n'est donc pas capable de décoder les paquets radio transmis de la sonde vers l'afficheur ...

F*ck !

En plus je ne sais pas pourquoi, mais au Québec, on a tous les mêmes balais rouge.

Ajouter un protocole dans rtl_433 (sans coder !)

Loin de moi l'idée d'écrire un article sur les différents types de modulation de signal et comment les décoder .... Pas la peine.

Les protocoles de modulation radios sont standards et rtl_433 arrive donc a le déterminer. La seule chose qu'il ne peut pas faire c'est de comprendre le contenu des paquets (en gros comment sont encodées et disposées chaque valeur dans la trame envoyée de la station vers l'afficheur).

Le jeu consiste donc a (essayer de) décoder le protocole (reverse engineering) pour que un des volontaires qui contribue a ce magnifique projet l'ajoute ensuite dans le logiciel.

L'idée de départ est donc de capturer (et isoler) les trames de la station météo (comme tu le ferais avec un sniffer réseau) et surtout de noter au même moment les valeurs de la température, l'humidité et du vent sur l'afficheur pour faire la correspondance.

Pour se donner plus de chance de comprendre comment elles sont encodées, Il faut répéter l'opération dans plusieurs cas de figure (et notamment avec une température négative). Pour se faire, pas la peine d'attendre qu'il neige, tu peux juste la mettre au congélateur.

Généralement c'est la que ta blonde commence a péter les plombs et que tes enfants te regardent bizarre.

Après quelques expérimentations, on arrive vers un résultat où je comprends que chaque 2 minutes la sonde envoie 12 paquets radio de données (2x 6 fois la même chose) qui commencent tous par f6 a9 be.

Tu sens que ça progresse ? Oui moi aussi, j'étais comme un fou. Il en faut peu pour être heureux.

$ rtl_433 -X 'n=lacrosse-tx141w,m=OOK_PWM,s=256,l=500,r=1888,g=0,t=0,y=748' old/g001_433.92M_250k.cu8

time      : @0.068508s
model     : lacrosse-tx141w                         count     : 13            num_rows  : 13            rows      : 
len       : 1            data      : 8, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befedc8faeb78, 
len       : 65           data      : f6a9befdfd6fff2d8, 
len       : 65           data      : f6a9befdfd6fff2d8, 
len       : 65           data      : f6a9befdfd6fff2d0, 
len       : 65           data      : f6a9befdfd6fff2d8, 
len       : 65           data      : f6a9befdfd6fff2d8

Ayant les valeurs de chaque capteur (température, humidité, vent) sous la main, il suffit donc maintenant de faire la correspondance avec le contenu du paquet (f6a9befedc8faeb78, f6a9befdfd6fff2d8).

Pas la peine de sortir un tableau blanc et la calculatrice. Ils ont aussi fait un super outils dédié bitbench où tu vas pouvoir travailler et partager le fruit de tes recherches simplement.

L'idée est de trouver combien de bits composent le header, l'identifiant, chaques valeurs de la sonde, puis un checksum à la fin.

Cela va assez vite pour les premiers octets car généralement l'en-tête est souvent la même par constructeur puis tu fais varier l'identifiant de la sonde en enlevant les piles une paire de fois.

Pour le reste, Il faut faire varier une donnée à la fois et identifier ce qui change dans le payload. Bref, t'as compris la démarche je pense !

Dans mon cas (et avec l'aide de quelques furieux) la concordance exacte été vite trouvée.

Je réalise que le premier type de paquet contient la température et l'humidité (offset 500 et scale 10) et que le deuxième paquets contient juste la vitesse du vent.

Le deuxième paquet radio changeait uniquement quand le capteur vent avait une valeur.

Concernant l 'indicateur “pile faible” (petite cerise sur le gâteau n'est-ce pas ?), il suffit de brancher la station météo sur une alimentation réglable (de type workbench) ou tu peux te mettre juste en dessous de ce qui est prévu.

Bingo. L'alarme pile faible se déclenche sur l'afficheur et quelques bits viennent de switcher de 00 à 10 dans le paquet radio.

Pour accélérer tes recherches, tu peux aussi ouvrir une issue Github sur le projet (en joignant tes captures et surtout les valeurs associés), le modèle et la doc éventuellement, etc ...

Les fabricants utilisent souvent les mêmes protocoles sur plusieurs produits et ils se ressemblent pratiquement tous entre eux.

En utilisant la même démarche j'ai pu faire ajouter le support pour le modèle Lacrosse TX141W et Lacrosse TX141TH-BV3 ... que tu trouveras dans les meilleurs Canadian Tire proche de chez toi.

Quelques jours plus tard, le code est mergé et donc officiellement ajouté dans la liste du matériel supporté ... (enfin décodé) ...

C'est beau, rtl_433 reconnaît donc maintenant les paquets radios de ma station et les injectent dans MQTT !

Finalement !

De retour dans la configuration de Home Assistant, je vais pouvoir donc ajouter la sonde (toujours de type MQTT):

  - platform: mqtt
    name: "Wind speed"
    state_topic: "rtl433/118729/wind_avg_km_h"
    unit_of_measurement: 'km/h'
  - platform: mqtt
    name: "External Temp"
    state_topic: "rtl433/118729/temperature_C"
    unit_of_measurement: '°C'
  - platform: mqtt
    name: "External Humidity"
    state_topic: "rtl433/118729/humidity"
    unit_of_measurement: '%'
    force_update: true

Pour info, j'utilise le module Influx DB pour conserver les données et avoir des graphes plus sympathiques dans Grafana.

Récemment, l'afficheur s'est brisé en tombant de la commode où il prenait la poussière (Alice je sais que c'est toi). Je suis bien content d'avoir fait cette job du coup ... Il ne sert plus mais la station elle, reste utilisable.

Voilà pour ce périple. A bientôt.

^EOF

#rtl433 #homeassistant