De la donnée au graphique : créer un tableau de bord IoT Flask‑SQLite avec Raspberry Pi
1. Introduction
Dans notre tutoriel précédent, Serveur Web Python avec Flask et Raspberry Pi, nous avons appris à exposer des données capteur via une interface web. L'étape logique suivante est de persister ces relevés pour les analyser ultérieurement.
2. Liste du matériel
- Raspberry Pi 3 – 32,00 €
- Capteur DHT22 Température & Humidité relative – 9,95 €
- Résistance de tirage 4,7 kΩ
3. Installation de SQLite
SQLite est le moteur de base de données idéal pour un monocarte : sans serveur, léger et entièrement open‑source. Installez‑le :
sudo apt-get install sqlite3
Puis créez un répertoire de travail et un fichier de base :
mkdir Sensors_Database
cd Sensors_Database
sqlite3 sensorsData.db
À l'invite SQLite, quittez avec .quit pour revenir au shell.
4. Création de la table DHT
La table DHT_data stocke un horodatage, la température et l'humidité.
sqlite3 sensorsData.db
BEGIN;
CREATE TABLE DHT_data (timestamp DATETIME, temp NUMERIC, hum NUMERIC);
COMMIT;
Alternativement, en Python :
import sqlite3
con = sqlite3.connect('sensorsData.db')
with con:
cur = con.cursor()
cur.execute('DROP TABLE IF EXISTS DHT_data')
cur.execute('CREATE TABLE DHT_data(timestamp DATETIME, temp NUMERIC, hum NUMERIC)')
5. Insertion de lignes d'exemple
Insertion manuelle via SQLite :
INSERT INTO DHT_data VALUES(datetime('now'), 20.5, 30);
Ou insertion groupée en Python :
with con:
cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), 20.5, 30)")
cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), 25.8, 40)")
cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), 30.3, 50)")
6. Câblage du DHT22
Connectez VCC au 3,3 V, Data au GPIO 16, GND à la masse, et placez une résistance de 4,7 kΩ entre VCC et Data.
7. Installation de la bibliothèque Adafruit DHT
Téléchargez depuis GitHub et installez :
sudo python3 setup.py install
8. Lecture et journalisation des données
Script minimal qui lit le capteur, arrondit les valeurs et les écrit en base :
import time
import sqlite3
import Adafruit_DHT
DB_NAME = 'sensorsData.db'
SAMPLE_FREQ = 120 # secondes
DHT_SENSOR = Adafruit_DHT.DHT22
DHT_PIN = 16
def read_and_log():
humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
if humidity is not None and temperature is not None:
humidity = round(humidity)
temperature = round(temperature, 1)
conn = sqlite3.connect(DB_NAME)
cur = conn.cursor()
cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), ?, ?)", (temperature, humidity))
conn.commit()
conn.close()
for _ in range(3):
read_and_log()
time.sleep(SAMPLE_FREQ)
9. Journalisation continue
Pour un logger temps réel, lancez le script suivant dans un terminal dédié. Il capture un échantillon par minute :
import time, sqlite3, Adafruit_DHT
DB = 'sensorsData.db'
SAMPLE_FREQ = 60
while True:
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 16)
if humidity is not None and temperature is not None:
conn = sqlite3.connect(DB)
cur = conn.cursor()
cur.execute("INSERT INTO DHT_data VALUES(datetime('now'), ?, ?)", (round(temperature,1), round(humidity)))
conn.commit()
conn.close()
time.sleep(SAMPLE_FREQ)
10. Interrogation de la base
Requêtes typiques :
- Toutes les lignes :
SELECT * FROM DHT_data - Dernière entrée :
SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1 - Température > 30 °C :
SELECT * FROM DHT_data WHERE temp > 30 - Humidité = 29 % :
SELECT * FROM DHT_data WHERE hum = 29
11. Serveur web Flask
Installez Flask : sudo apt-get install python3-flask. Créez la structure :
mkdir dhtWebServer
cd dhtWebServer
mkdir templates static
Dans appDhtWebServer.py :
from flask import Flask, render_template
import sqlite3
app = Flask(__name__)
def fetch_latest():
conn = sqlite3.connect('../sensorsData.db')
cur = conn.cursor()
cur.execute('SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1')
row = cur.fetchone()
conn.close()
return row
@app.route('/')
def index():
time, temp, hum = fetch_latest()
return render_template('index.html', time=time, temp=temp, hum=hum)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=False)
Template templates/index.html :
<!DOCTYPE html>
<html>
<head>
<title>Tableau de bord capteur DHT</title>
<link rel='stylesheet' href='../static/style.css'>
</head>
<body>
<h1>Données capteur DHT</h1>
<p>Température : {{ temp }} °C</p>
<p>Humidité : {{ hum }} %</p>
<p>Dernier relevé : {{ time }}</p>
<a href='/' class='button'>Rafraîchir</a>
</body>
</html>
12. Améliorer l'interface avec des jauges
Téléchargez JustGage et placez justgage.js et raphael-2.1.4.min.js dans static. Mettez à jour le template pour afficher des jauges animées :
<div id='g1'></div>
<div id='g2'></div>
<script src='../static/raphael-2.1.4.min.js'></script>
<script src='../static/justgage.js'></script>
<script>
new JustGage({id:'g1', value:{{ temp }}, min:-10, max:50, title:'Température', label:'°C'});
new JustGage({id:'g2', value:{{ hum }}, min:0, max:100, title:'Humidité', label:'%'});
</script>
13. Graphiques historiques avec Matplotlib
Installez Matplotlib : sudo apt-get install python3-matplotlib. Créez une nouvelle appli Flask appDhtWebHist.py qui sert des images PNG générées à la volée.
from flask import Flask, render_template, make_response
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
import sqlite3, io
app = Flask(__name__)
DB = '../sensorsData.db'
def get_latest():
conn = sqlite3.connect(DB)
cur = conn.cursor()
cur.execute('SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1')
row = cur.fetchone()
conn.close()
return row
def get_history(samples):
conn = sqlite3.connect(DB)
cur = conn.cursor()
cur.execute('SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT ?', (samples,))
rows = cur.fetchall()
conn.close()
rows.reverse() # ordre chronologique
times, temps, hums = zip(*rows)
return times, temps, hums
@app.route('/')
def index():
time, temp, hum = get_latest()
return render_template('index.html', time=time, temp=temp, hum=hum, samples=100)
@app.route('/plot/temp')
def plot_temp():
times, temps, _ = get_history(100)
fig = Figure()
ax = fig.add_subplot(1,1,1)
ax.plot(range(len(temps)), temps)
ax.set_title('Température (°C)')
canvas = FigureCanvas(fig)
output = io.BytesIO()
canvas.print_png(output)
return make_response(output.getvalue(), 200, {'Content-Type':'image/png'})
@app.route('/plot/hum')
def plot_hum():
_, _, hums = get_history(100)
fig = Figure()
ax = fig.add_subplot(1,1,1)
ax.plot(range(len(hums)), hums)
ax.set_title('Humidité (%)')
canvas = FigureCanvas(fig)
output = io.BytesIO()
canvas.print_png(output)
return make_response(output.getvalue(), 200, {'Content-Type':'image/png'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=False)
Le template templates/index.html inclut deux balises <img> qui requièrent les routes PNG.
14. Conclusion
Ce projet de bout en bout montre comment transformer un capteur bon marché en plateforme de journalisation et de surveillance : capture, persistance, interrogation et visualisation via un serveur web Flask local. Tout le code source est sur GitHub et d'autres exemples sur MJRoBot.org.
Processus de fabrication
- Microchip introduit ADCs Delta-Sigma 24-bit & 16-bit avec taux données 153,6 kSPS
- Moniteur température et humidité domestique avec Raspberry Pi et tableau de bord web — Suivi à distance en temps réel
- Construire un robot avec Raspberry Pi et Python : Guide complet
- Accélérer la transformation numérique : La plateforme IdO Edge-to-Cloud de Cisco & IBM
- De l'Edge au Cloud : maîtriser les pipelines de données IoT
- Télémétrie à distance : la fondation d'un déploiement IIoT réussi
- Donner vie à l'IoT avec IBM et Tech Data – Partie 2
- Transformer l'IoT en réalité : insights Tech Data et IBM – Partie 1
- Maximiser la valeur business grâce à l'intégration Big Data et IA