Projet VanLife — Récupération des données de températures et enregistrement en base
Introduction
Cet article est le troisième article d’une série concernant la mise en place d’un ensemble des capteurs dans un van, liés à un Raspberry Pi et connecté à une app.
Introduction : Projet Van Life — Introduction — Une semaine de « hackaton » pour OnTheBeach.dev
Article 2 : Projet VanLife — Local First — Sécurisation de l’API et gestion des utilisateurs
Ces développements ont été fait lors d’un “hackaton/road trip” par OnTheBeach.dev.
Récupération et exploitation de données
Maintenant que nous disposons d’une API sécurisée, nous allons pouvoir commencer à alimenter notre base de données avec des informations sur la vie dans le van, afin qu’elle puisse être exploitée par notre application mobile.
Les premières données que nous allons récupérer sont la température et le taux d’humidité à l’intérieur du van.
Récupération de la température
Le premier capteur que je vais connecter au RP3 sera un capteur de température et de taux d’humidité de l’air. Je me suis procuré un capteur DHT11 de AZDelivery.
Après l’avoir connecté aux broches GPIO du RP3, j’ai récupéré une library créée par Adafruit et les exemples qu’ils ont édités, puis en python j’ai créé le bout de code qui récupèrera toutes les minutes la température et le taux d’humidité mesuré dans le van car le capteur DHT11.
import Adafruit_DHT
import logging
import time
logging.basicConfig(level=logging.DEBUG)
try:
logging.info("Temp Demo")
while (True):
humidity, temperature = Adafruit_DHT.read_retry(11, 4)
jsonData = {
"humidity": humidity,
"temperature": temperature,
"time": time.strftime('%H:%M:%S')
}
logging.info(jsonData)
time.sleep(60)
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
logging.info("ctrl + c:")
exit()
Et voilà le résultat d’un lancement de ce code.
INFO:root:Temp Demo
INFO:root:{'humidity': 54.0, 'temperature': 25.0, 'time': '16:09:58'}
INFO:root:{'humidity': 54.0, 'temperature': 25.0, 'time': '16:10:59'}
Il ne me reste plus qu’à le transmettre à mon back end local, afin que celui-ci puisse les restituer au front (dans notre cas l’app mobile).
Dans la théorie, je souhaitais configurer le RPZ avec le back end. Comme expliqué dans les premiers articles, je ne suis parti qu’avec un seul Raspberry. Les fonctions ont été malgré tout codé en partant du principe d’avoir un RP en tant que back end et les autres en tant que client. Durant mes tests, un seul RP jouait les 2 rôles.
Les API sont sécurisées pour que chaque utilisateur récupère un token à la connexion qui expire après X minutes. Or pour que les RP clients communiquent avec le RP Back end, j’ai besoin d’une connexion permanente. J’ai donc créé un utilisateur admin, et je lui ai créé un token d’une durée de vie de 99 ans. Si besoin je pourrai le révoquer. Je peux ainsi appeler le endpoint “temperature” en POST de mon API pour ajouter des données dans mon back end.
Pour envoyer des données, nous allons installer la library Python requests. Puis nous allons mettre à jour notre code.
import Adafruit_DHT
import requests
import logging
import time
import json
REQUEST_HEADERS = {"Content-Type":"application/json", "Authorization":"Bearer XXXXXXXXXXX"}
logging.basicConfig(level=logging.DEBUG)
try:
logging.info("Temp Demo")
while (True):
humidity, temperature = Adafruit_DHT.read_retry(11, 4)
jsonData = json.dumps({"id":"", "humidity": humidity, "temperature": temperature, "ts": int(time.time()*1000)})
logging.info(jsonData)
add_response = requests.request("POST", "http://vanzero:8000/temperature", headers=REQUEST_HEADERS, data=jsonData)
logging.info(add_response.text)
time.sleep(60)
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
logging.info("ctrl + c:")
exit()
En exécutant mon code, voilà les logs que j’obtiens
INFO:root:Temp Demo
INFO:root:{"id": "", "humidity": 53.0, "temperature": 26.0, "ts": 1720797344111}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): vanzero:8000
DEBUG:urllib3.connectionpool:http://vanzero:8000 "POST /temperature HTTP/1.1" 201 16
INFO:root:{"success":true}
INFO:root:{"id": "", "humidity": 53.0, "temperature": 26.0, "ts": 1720797404893}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): vanzero:8000
DEBUG:urllib3.connectionpool:http://vanzero:8000 "POST /temperature HTTP/1.1" 201 16
INFO:root:{"success":true}
Si je teste la récupération des températures enregistrées en appelant l’endpoint temperature, j’obtiens bien les données que j’ai postées avec le RP3.
Pour mes tests, j’ai mis une récupération des données toutes les minutes. Je vais maintenant configurer la méthode pour la récupérer toutes les 15 minutes, ce qui sera largement suffisant.
Il faut maintenant configurer le RPZ et le RP3 pour qu’ils lancent ces services quand ils démarrent. Pour cela, nous allons utiliser les services de systemd.
Sur le RP Back End, nous allons créer un service “fastapi”.
sudo nano /etc/systemd/system/fastapi.service
Nous allons configurer ce service ainsi.
[Service]
ExecStart=python3 -m uvicorn api:app --host 0.0.0.0 --port 8000
WorkingDirectory=/home/pi/Documents/VanLife/
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=vanlife
User=pi
Group=pi
[Install]
WantedBy=multi-user.target
Mon fichier api.py est stocker dans le dossier /Documents/VanLife/. Ne pas oublier d’adapter le chemin en fonction de la structure du projet.
Ensuite exécuter la commande suivante
sudo systemctl enable fastapi.service
Pour le tester immédiatement sans attendre le prochain reboot
sudo systemctl start fastapi.service
Je fais de même sur mon RP client, pour mon fichier python contenant le code de récupération des températures.
Et voilà, j’ai un système qui tourne et qui récupère toutes les 15 minutes la température et le taux d’humidité de mon van.
Une amélioration de ce code — en lieu est place d’une boucle permanente — serait de configurer un CRON sur le RP Client, qui lancerait le code de récupération des données toutes les 15 minutes.