My Own Memory Hole
Blog♯WeeWX

Mosquitto, un broker MQTT

J'ai découvert le protocole MQTT (Message Queuing Telemetry Transport) lors de l'interfaçage de ma station météo Netatmo et du logiciel WeeWX sur mon Raspberry Pi ; il s'agit d'un protocole de messagerie de type publication-abonnement, extrêmement rapide et léger, utilisé notamment dans l'internet des objets.

Nous allons ici voir comment installer et configurer un broker, un agent MQTT, en l'occurrence Mosquitto, en nous appuyant très largement sur l'article « How to setup your own MQTT Broker » de Pat O'Brien.

Installation et premiers tests

On commence par l'installer :

sudo apt install mosquitto mosquitto-clients

Nous pouvons dès lors « jouer » un peu...
On peut commencer par vérifier la version de notre agent ou le temps écoulé depuis son lancement :

mosquitto_sub -t \$SYS/broker/version
mosquitto_sub -t \$SYS/broker/uptime

Puis commencez par ouvrir deux sessions dans votre terminal (on ne saurait trop vous conseiller d'utiliser tmux, présenté dans cet article)–: dans la première, on lance la commande mosquitto_sub -t test/# puis dans la seconde on lance mosquitto_pub -t test/test -m "Test message"...

premiers pas avec mosquitto

Configuration, accès, SSL

Il convient de préciser d'emblée que Mosquitto est très regardant sur le formatage de ses fichiers de configuration et qu'il n'accepte pas d'espace en fin de ligne.

On commence par éditer un fichier /etc/mosquitto/conf.f/conf.d/myconfig.conf :

persistence false

# mqtt
listener 1883
protocol mqtt

# websockets
listener 9001
protocol websockets

On redémarre alors Mosquitto :

sudo service mosquitto restart

Gestion des accès

Mosquitto permet de gérer topic par topic les droits de publication et d'abonnement.

On commence par générer un couple identifiant / mot de passe, ainsi :

sudo mosquitto_passwd -c /etc/mosquitto/passwd USER

puis on édite un fichier /etc/mosquitto/acl

# Autoriser l'abonnement anonyme à $SYS
topic read $SYS/#

# Autoriser l'abonnement et la publication anonymes à test 
topic test/#

# Autoriser le seul abonnement anonyme à testlecture
topic read testlecture/#

# Accès limité pour l'écriture sur testlecture
# Abonnement et publication sur secret pour USER seulement
user USER
topic write testlecture
topic secret/#

on édite ensuite le fichier /etc/mosquitto/conf.d/myconfig.conf pour qu'il ressemble à cela :

persistence false
allow_anonymous true
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl

# mqtt
listener 1883
protocol mqtt

# websockets
listener 9001
protocol websockets

On redémarre le service avant de vérifier avec la commande netstat que les ports déclarés sont bien ouverts :

$ sudo service mosquitto restart
$ sudo netstat -tulpn | grep 1883
tcp        0      0 0.0.0.0:1883            0.0.0.0:*               LISTEN      142015/mosquitto
tcp6       0      0 :::1883                 :::*                    LISTEN      142015/mosquitto
$ sudo netstat -tulpn | grep 9001
tcp6       0      0 :::9001                 :::*                    LISTEN      142015/mosquitto

Pour le canal test, accessible sans authentification ni pour l'abonnement ni pour la publication, on vérifie avec cette commande dans notre première session :

mosquitto_sub -h localhost -p 1883 -t test/#

et dans la seconde nous lançons :

mosquitto_pub -h localhost -p 1883 -t test/1 -m "Hello topic test/1"

Le canal testlecture ne devrait être accessible anonymement qu'en lecture :

mosquitto_sub -h localhost -p 1883 -t testlecture/#

La première des deux commandes suivantes ne devrait rien renvoyer dans notre première session ; il convient en effet de s'authentifier pour publier dans ce canal :

mosquitto_pub -t testlecture/test -m "test"
mosquitto_pub -u USER -P PASSWORD -t testlecture/test -m "test"

Enfin, le canal secret nécessite de s'authentifier aussi bien pour l'abonnement que pour la publication :

mosquitto_sub -u USER -P PASSWORD -t secret/#
mosquitto_pub -u USER -P PASSWORD -t secret/test -m "test"

Certificat SSL

Il est bien évidemment possible de rendre cet agent MQTT accessible sur Internet et de le configurer pour qu'il utilise une connexion sécurisée grâce à un certificat comme ceux proposés par Let's Encrypt. Nous allons considérer ici que vous avez déjà configuré votre nom de domaine et généré le certificat, comme évoqué ici.

Ainsi, dans mon cas, vous devriez pouvoir vous abonner au canal weather produit par WeeWX et son plugin weewx-mqtt avec la commande suivante :

mosquitto_sub -h meteo.momh.fr -p 8883 --capath /etc/ssl/certs/ -t weather/#

Il convient, après avoir généré son certificat, d'éditer le fichier /etc/mosquitto/conf.d/myconfig.conf de la sorte :

# Insecure mqtt to localhost only, and secure mqtt
listener 1883 localhost
listener 8883
certfile /etc/letsencrypt/live/DOMAINE/cert.pem
cafile /etc/letsencrypt/live/DOMAINE/chain.pem
keyfile /etc/letsencrypt/live/DOMAINE/privkey.pem
protocol mqtt

# websockets
listener 9001
certfile /etc/letsencrypt/live/DOMAINE/cert.pem
cafile /etc/letsencrypt/live/DOMAINE/chain.pem
keyfile /etc/letsencrypt/live/DOMAINE/privkey.pem
protocol websockets

Après avoir redémarré le service

sudo service mosquitto restart

on peut tester ainsi, avec pour chacune de nos deux sessions, les commandes :

mosquitto_sub -h DOMAINE -p 8883 --capath /etc/ssl/certs/ -u USER -P PASSWORD -t secret/#
mosquitto_pub -h DOMAINE -p 8883 -u USER -P PASSWORD -t secret/test -m "Test message dans le canal secret"

Nous pouvons désormais utiliser notre agent MQTT avec WeeWX !

Station météo Netatmo & WeeWX [bis]

Suite à mon premier post sur le sujet, je me suis attelé plus longuement à la compatibilité du plugin weewx-netatmo de Matthew Wall avec les versions 4 de WeeWX sous Python 3.

Installation

De ce fait, on n'a plus besoin d'installer une ancienne version de WeeWX et l'on peut se reporter sur la version disponible dans les dépôts :

sudo apt install weewx

Désormais, la configuration et autres skins ne se trouvent plus dans /home/weewx mais dans /etc/weewx. L'installation du plugin weewx-netatmo peut se faire depuis mon fork du plugin :

wget -O weewx-netatmo.zip https://github.com/bricebou/weewx-netatmo/archive/master.zip
sudo wee_extension --install weewx-netatmo.zip
sudo wee_config --reconfigure

On ouvre ensuite le fichier de configuration /etc/weewx/weewx.conf pour vérifier que nos identifiants Netatmo soient bien pris en compte. Ensuite, on redémarre WeeWX :

sudo service weewx restart

Modifications apportées

Pour ce faire, on utilise l'outil 2to3 :

sudo pip3 install 2to3

puis on lance la commande :

2to3 -w netatmo.py

Une erreur subsistait mais le problème avait déjà été résolu par kwalker05 ; il suffit, à la ligne 521, de remplacer :

params = urlencode(params)

par

params = urlencode(params).encode("utf-8")

Station météo Netatmo & WeeWX

Dans le cadre de la «digitalisation» de La Sculpture : les Pluies de Patrick Dubrac, nous cherchons à aller au-delà de ce que nous avons mis en place avec Le Calendrier des pluies, mis à jour mensuellement à partir des données météorologiques quotidiennes. D'où l'idée de développer un prototype associant une station météo Netatmo à un Raspberry Pi sur lequel serait installé WeeWX, un petit programme en Python qui permet d'interagir avec de multiples modèles de stations météo, de publier les données sur de multiples sites, de conserver les données dans des bases de données...

Cependant, le pilote pour les stations Netatmo (https://github.com/matthewwall/weewx-netatmo) n'est pas compatible avec la version 4 de WeeWX...

[EDIT : depuis, je suis parvenu à rendre compatible le plugin avec les versions 4 de WeeWX tel que présenté dans cet article ; certains éléments de cet article sont toujours valables, tels ceux consacrés à la base de données.]

On bascule donc sur la dernière des versions 3 de WeeWX disponibles, la 3.9.2 :

wget http://weewx.com/downloads/released_versions/weewx-3.9.2.tar.gz

On installe les dépendances nécessaires :

sudo apt install python-configobj python-pil python-serial python-usb python-pip python-cheetah python-ephem mariadb-client python-mysqldb

Puis on lance l'installation :

tar xvfz weewx-3.9.2.tar.gz
cd weewx-3.9.2
python2 setup.py build
sudo python setup.py install

L'ensemble des exécutables se trouve dans /home/weewx/bin/ ; le fichier de configuration est à l'emplacement /home/weewx/weewx.conf

On installe ensuite le pilote weewx-netatmo (https://github.com/matthewwall/weewx-netatmo) :

wget -O weewx-netatmo.zip https://github.com/matthewwall/weewx-netatmo/archive/master.zip
sudo /home/weewx/bin/wee_extension --install weewx-netatmo.zip

Puis on configure weewx :

sudo /home/weewx/bin/wee_config --reconfigure

On édite ensuite le fichier de configuration à la main  :

sudo nano /home/weewx/weewx.conf

On s'assure que nos identifiants Netatmo sont bien pris en compte et on bascule, dans la sous-section [[wx_binding]] de la section [DataBindings] sur une base de données MySQL :

database = archive_mysql

On crée une base de données avec les mêmes identifiants que ceux que nous avons indiqués dans la sous-section [[archive_mysql]] de la secion [Databases], par défaut :

    # MySQL
    [[archive_mysql]]
        database_name = weewx
        database_type = MySQL
sudo mysql -u root -p
MariaDB [(none)]> CREATE DATABASE weewx;
MariaDB [(none)]> CREATE USER 'weewx'@localhost IDENTIFIED BY 'weewx';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON weewx.* TO 'weewx'@localhost;
MariaDB [(none)]> FLUSH PRIVILEGES;

Enfin, on fait en sorte que WeeWX soit lancé au démarrage comme un service :

cd /home/weewx
sudo cp util/init.d/weewx.debian /etc/init.d/weewx
sudo chmod +x /etc/init.d/weewx
sudo update-rc.d weewx defaults 98
sudo /etc/init.d/weewx start