Introduction
Je propose ici une nouvelle version de l’article précédent car je n’utilise plus Thingsboard mais plutôt Home Assistant avec un serveur MQTT intermédiaire pour la construction d’un capteur de température et d’humidité.
Les objectifs :
- être compact,
- être relativement peu cher,
- disposer d’une historisation des données,
- avoir un impact minime sur le capteur (en l’occurrence un Raspberry Pi),
- réutiliser des briques logicielles standards et maintenues (pas envie de redévelopper ou réutiliser un vieux script),
- mettre en place des alarmes en cas de dépassement de seuil.
Les composants
Le capteur
- Un Raspberry Pi Zero WH (Wireless + Headers) (https://www.raspberrypi.com/products/raspberry-pi-zero-w/),
- Un capteur de température et d’humidité SHT-30 disposant d’un câble de 1M (https://www.adafruit.com/product/4099),
- Une alimentation USB,
- Une extension pour les headers afin de connecter plus simplement les câbles du connecteur (https://thepihut.com/products/mini-terminal-breakout-board-for-raspberry-pi),
Il pourrait être intéressant de creuser la construction d’un HAT spécifique avec les composants suivants :
- Headers femelle
- Morceau de board
- Fils
Le serveur
- Un serveur Debian avec Docker,
- Un container avec le service MQTT
- Un container avec le service Home Assistant
Installation du système
-
Installer la dernière image de Raspberry Pi OS Lite avec l’outil Raspberry Pi Imager ou manuellement (voir l’article précédent).
-
Placer la carte SD dans le RPi0 et le brancher. Patienter quelques secondes pour qu’il s’allume.
-
Se connecter en SSH
-
Vérifier la présence de mises à jour et les installer :
$ sudo apt update && sudo apt upgrade -
Installer
vim:$ sudo apt install vim
Câblage
Le schéma de câblage est le suivant :

Ce schéma utilise le capteur SHT31 (dont le SHT-30 est une variante avec câble et protections).
On retrouve les connectiques suivantes :
| Couleur | Fonction |
|---|---|
| Rouge/Marron | VCC/VIN (3-5VDC) |
| Noir | Ground |
| Jaune | Clock/SCL |
| Vert/Bleu | Data/SDA |
D’après la documentation, les câbles data et clock peuvent parfois être inversés, donc ne pas hésiter à tester les 2 si vous ne recevez aucune information.
TODO : mettre une photo du câblage réel.
Capture des données
Installation
Pour interagir avec le capteur SHT-30 nous allons utiliser les bibliothèques CircuitPython & Blinka.
-
Installation de
pipet vérification de la dernière version desetuptools:$ sudo apt-get install python3-pip $ sudo apt install --upgrade python3-setuptools -
Créer l’environement virtuel et l’activer
$ sudo apt install python3-venv $ cd ~ $ python3 -m venv env --system-site-packages $ source env/bin/activateToutes les commandes suivantes seront réalisées avec l’environnement virtuel activé.
-
Installation de CircuitPython & Blinka :
$ pip3 install --upgrade adafruit-python-shell $ wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py $ sudo -E env PATH=$PATH python3 raspi-blinka.py This script configures your Raspberry Pi and installs Blinka RASPBERRY_PI_ZERO_W detected. Updating System Packages [...] DONE. Settings take effect on next boot. REBOOT NOW? [Y/n] Y Reboot started...À la fin de l’installation (qui prend quelques minutes), il propose de redémarrer le Raspberry Pi Zero, ce qu’il faut accepter.
-
Après le redémarrage, installer la bibliothèque SHT31D (https://github.com/adafruit/Adafruit_CircuitPython_SHT31D) :
$ pip3 install adafruit-circuitpython-sht31d
Tests de capture
Afin de tester la bonne installation des bibliothèques précédentes, il est possible d’exécuter les commandes suivantes dans un shell Python :
import board
import busio
import adafruit_sht31d
i2c = busio.I2C(board.SCL, board.SDA)
sensor = adafruit_sht31d.SHT31D(i2c)
print('Humidity: {0}%'.format(sensor.relative_humidity))
print('Temperature: {0}C'.format(sensor.temperature))
Les premières lignes importent les modules nécessaires et initialisent la connexion I2C avec le capteur.
Les 2 dernières lignes lisent les valeurs et les affiches.
Voici le résultat :
Python 3.11.2 (main, May 2 2024, 11:59:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import board
>>> import busio
>>> import adafruit_sht31d
>>> i2c = busio.I2C(board.SCL, board.SDA)
>>> sensor = adafruit_sht31d.SHT31D(i2c)
>>> print('Humidity: {0}%'.format(sensor.relative_humidity))
Humidity: 54.47775997558556%
>>> print('Temperature: {0}C'.format(sensor.temperature))
Temperature: 25.336461432822162C
Un script d’exemple (pour lire et afficher les valeurs toutes les 2 sec.) est également disponible sur le repository GitHub du driver SHT31D.
$ wget https://github.com/adafruit/Adafruit_CircuitPython_SHT31D/blob/main/examples/sht31d_simpletest.py
$ python sht31d_simpletest.py
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Temperature: 18.0 C
Humidity: 67.6 %
Sensor Heater status = True
Sensor Heater status = False
Temperature: 18.7 C
Humidity: 67.6 %
Temperature: 18.1 C
Humidity: 67.1 %
...
Intégration avec MQTT
L’objectif de tout cela n’étant pas d’afficher les valeurs en continu dans un terminal, nous allons intégrer le capteur dans MQTT pour qu’il historise les données (et plein d’autres choses que nous verrons plus tard).
Sur le serveur Mosquitto
-
Si vous avez installé votre serveur Mosquitto dans un container Docker, il faudra attacher la console du container :
sudo docker exec -it mosquitto_broker sh -
Puis, ajouter un nouvel utilisateur
SHT-30:/ # mosquitto_passwd mosquitto/config/passwd SHT-30 Password: Reenter password:Renseigner un mot de passe deux fois et l’utilisateur est créé.
Vous pouvez sortir de la console du container.
/ # exit -
Il faut ensuite donner les droits à cet utilisateur au topic dans lequel il va écrire :
$ sudo vim /opt/mosquitto/config/aclEt ajouter le configuration suivante :
user SHT-30 topic sensor/SHT-30/# -
Enfin redémarrer votre container pour qu’il prenne en compte cette nouvelle configuration.
Sur le Raspberry Pi Zero
La plupart des prérequis ont déjà été installés précédemment, mais il reste à installer la bibliothèque Paho pour permettre à notre script de discuter avec le service MQTT :
$ pip3 install --upgrade paho-mqtt
Créer le repertoire scripts dans le home de l’utilisateur :
$ mkdir ~/scripts
Et enfin, créer le script sht30_mqtt.py :
import os
import time
import sys
import board
import adafruit_sht31d
import paho.mqtt.client as mqtt
import json
MQTT_HOST = '<serveur mqtt>'
MQTT_PORT = <port mqtt>
MQTT_CLIENTID = 'SHT-30'
MQTT_USERNAME = '<username>'
MQTT_PASSWORD = '<password>'
# Data capture and upload interval in seconds.
INTERVAL=15
# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C()
sensor = adafruit_sht31d.SHT31D(i2c)
sensor_data = {'temperature': 0, 'humidity': 0}
next_reading = time.time()
client = mqtt.Client()
# Set access token
client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
# Connect to MQTT using default port and 60 seconds keepalive interval
client.connect(MQTT_HOST, MQTT_PORT, 60)
client.loop_start()
try:
while True:
humidity = round(sensor.relative_humidity,2)
temperature = round(sensor.temperature,2)
print(u"Temperature: {:g}\u00b0C, Humidity: {:g}%".format(temperature, humidity))
sensor_data['temperature'] = temperature
sensor_data['humidity'] = humidity
# Sending humidity and temperature data to MQTT
client.publish('sensor/SHT-30/telemetry', json.dumps(sensor_data), 1)
next_reading += INTERVAL
sleep_time = next_reading-time.time()
if sleep_time > 0:
time.sleep(sleep_time)
except KeyboardInterrupt:
pass
client.loop_stop()
client.disconnect()
Il faudra bien évidemment penser à modifier les lignes suivantes (au début du script) pour y ajouter vos valeurs :
MQTT_HOST = '<serveur mqtt>' MQTT_PORT = <port mqtt> MQTT_CLIENTID = 'SHT-30' MQTT_USERNAME = '<username>' MQTT_PASSWORD = '<password>'Et éventuellement la fréquence de lecture (en secondes) :
INTERVAL=15
Vous pouvez désormais lancer le script manuellement pour vérifier son bon fonctionnement (toujours depuis l’environnement virtuel) :
$ python sht30_mqtt.py
Temperature: 17.97°C, Humidity: 68.13%
Temperature: 17.94°C, Humidity: 68.08%
...
Vous devriez retrouver les valeurs remontées dans la télémétrie du topic créé (accessible avec MQTT Explorer) :

Vous pouvez desormais sortir de l’environnement virtuel :
$ deactivate
Automatisation
Afin de lire en continu les données sans avoir un shell ouvert, nous allons mettre en place un service systemd (dans l’environnement utilisateur) pour le script précédent.
-
Activer les instances utilisateurs
systemdau démarrage (et non à l’ouverture de session) :$ sudo loginctl enable-linger brice -
Ajouter les lignes suivantes pour affecter les variables
XDG_RUNTIME_DIRetDBUS_SESSION_BUS_ADDRESSmanuellement dans le.bashrcde votre utilisateur (normalement elles le sont automatiquement à l’ouverture de session) :export XDG_RUNTIME_DIR="/run/user/$UID" export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus" -
Créer le répertoire pour les services
systemdutilisateur :$ mkdir -p ~/.config/systemd/user/ -
Créer le service
~/.config/systemd/user/sensor.service:[Unit] Description=Sensor service After=multi-user.target [Service] Type=simple Restart=always ExecStart=/home/brice/env/bin/python3 /home/brice/scripts/sht30_mqtt.py [Install] WantedBy=multi-user.target -
Recharger la liste des services :
$ systemctl --user daemon-reload -
Activer le service au démarrage :
$ systemctl --user enable sensor.service -
Et enfin le démarrer :
$ systemctl --user start sensor.service
Bonus
Envoi manuel de données
A des fins de tests, si vous avez besoin d’envoyer des données manuellement (unitairement) vers le serveur MQTT, il vous faudra un client MQTT (par exemple Mosquitto).
Lancer la commande suivante :
$ mosquitto_pub -d -q 1 -h "<serveur mqtt>" -p "<port mqtt>" -t "sensor/SHT-30/telemetry" -u "<username>" -P "<password>" -m {\"temperature\":20}
Sources
- https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi
- https://learn.adafruit.com/adafruit-sht31-d-temperature-and-humidity-sensor-breakout/python-circuitpython
- https://learn.adafruit.com/adafruit-sht31-d-temperature-and-humidity-sensor-breakout/overview
- https://learn.adafruit.com/circuitpython-on-raspberrypi-linux