De datos a gráficos: Construcción de un panel IoT Flask‑SQLite con Raspberry Pi
Captura de datos reales de un sensor DHT22, almacenamiento en una ligera base de datos SQLite y visualización de resultados en un panel web construido con Flask.
1. Introducción
En nuestro tutorial anterior, Python WebServer With Flask and Raspberry Pi, aprendimos a exponer datos de sensores mediante un front‑end web. El siguiente paso lógico es persistir esas lecturas para analizarlas luego.
2. Lista de materiales
- Raspberry Pi 3 – $32.00
- Sensor DHT22 de temperatura y humedad relativa – $9.95
- Resistencia pull‑up de 4.7 kΩ
3. Instalación de SQLite
SQLite es el motor de base de datos ideal para un ordenador de placa única: no requiere servidor, es ligero y totalmente open‑source. Instálalo con:
sudo apt-get install sqlite3
Luego crea un directorio de trabajo y un archivo de base de datos:
mkdir Sensors_Database cd Sensors_Database sqlite3 sensorsData.db
Cuando aparezca el prompt de SQLite, sal con .quit y volverás al shell.
4. Creación de la tabla DHT
La tabla DHT_data almacena marca de tiempo, temperatura y humedad.
sqlite3 sensorsData.db BEGIN; CREATE TABLE DHT_data (timestamp DATETIME, temp NUMERIC, hum NUMERIC); COMMIT;
Alternativamente, usa 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. Inserción de filas de ejemplo
Inserción manual vía SQLite:
INSERT INTO DHT_data VALUES(datetime('now'), 20.5, 30);
O inserción masiva 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. Cableado del DHT22
Conecta VCC a 3.3 V, Data a GPIO 16, GND a tierra, y coloca una resistencia pull‑up de 4.7 kΩ entre VCC y Data.
7. Instalación de la librería Adafruit DHT
Descarga desde GitHub e instala:
sudo python3 setup.py install
8. Lectura y registro de datos
Script mínimo que lee el sensor, redondea valores y los escribe en la base de datos:
import time import sqlite3 import Adafruit_DHT DB_NAME = 'sensorsData.db' SAMPLE_FREQ = 120 # segundos 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. Registro continuo
Para un logger en tiempo real, ejecuta lo siguiente en una terminal dedicada. Captura una muestra cada minuto:
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. Consultas a la base de datos
Consultas típicas:
- Todas las filas:
SELECT * FROM DHT_data - Última entrada:
SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1 - Temperatura > 30 °C:
SELECT * FROM DHT_data WHERE temp > 30 - Humedad = 29 %:
SELECT * FROM DHT_data WHERE hum = 29
11. Servidor web Flask
Instala Flask: sudo apt-get install python3-flask. Crea la estructura del proyecto:
mkdir dhtWebServer cd dhtWebServer mkdir templates static
En 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)
Plantilla templates/index.html:
<!DOCTYPE html> <html> <head> <title>DHT Sensor Dashboard</title> <link rel='stylesheet' href='../static/style.css'> </head> <body> <h1>DHT Sensor Data</h1> <p>Temperature: {{ temp }} °C</p> <p>Humidity: {{ hum }} %</p> <p>Last reading: {{ time }}</p> <a href='/' class='button'>Refresh</a> </body> </html>
12. Mejora del front‑end con medidores (Gauges)
Descarga JustGage y coloca justgage.js y raphael-2.1.4.min.js en static. Actualiza la plantilla para renderizar medidores animados:
<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:'Temperature', label:'°C'}); new JustGage({id:'g2', value:{{ hum }}, min:0, max:100, title:'Humidity', label:'%'}); </script>
13. Gráficos históricos con Matplotlib
Instala Matplotlib: sudo apt-get install python3-matplotlib. Crea una nueva app Flask appDhtWebHist.py que sirva imágenes PNG generadas al vuelo.
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() # orden cronológico 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('Temperature (°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('Humidity (%)') 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)
La plantilla templates/index.html incluye dos etiquetas <img> que solicitan las rutas PNG.
14. Conclusión
Este proyecto de extremo a extremo demuestra cómo convertir un sensor barato en una plataforma de registro y monitorización: captura, persistencia, consulta y visualización todo a través de un servidor web Flask local. Todo el código fuente está disponible en GitHub y más ejemplos en MJRoBot.org.
Proceso de manufactura
- Monitor de temperatura y humedad en casa con Raspberry Pi y panel web – Seguimiento remoto en tiempo real
- Construya un robot con Raspberry Pi y Python: Guía completa
- Maximizar el valor empresarial mediante la integración de Big Data e IA
- Microchip introduce ADCs Delta‑Sigma 24‑bit y 16‑bit con data rates 153,6 kSPS
- Almacene y gestione datos sensibles de forma segura con Google Cloud Secret Manager
- Acelerando la Transformación Digital: La Plataforma IoT Edge-to-Cloud de Cisco e IBM
- Del Edge al Cloud: Dominando pipelines de datos IoT
- Telemetría remota: La base para un despliegue IIoT exitoso
- Dando Vida a IoT con IBM y Tech Data – Parte 2
- Convirtiendo IoT en Realidad: Insights de Tech Data e IBM – Parte 1
- Acelerando el Éxito Empresarial: IA y ML Resuelven Desafíos de Datos en Tiempo Real