Dari Data ke Grafik: Membangun Dasbor IoT Flask‑SQLite dengan Raspberry Pi
Menangkap data nyata dari sensor DHT22, menyimpannya dalam basis data SQLite ringan, dan memvisualisasikan hasilnya pada dasbor web yang dibangun dengan Flask.
1. Pendahuluan
Dalam tutorial sebelumnya kami, Python WebServer With Flask and Raspberry Pi, kami mempelajari cara mengekspos data sensor melalui antarmuka web. Langkah logis berikutnya adalah menyimpan bacaan tersebut sehingga dapat dianalisis nanti.
2. Daftar Bahan
- Raspberry Pi 3 – $32.00
- Sensor Suhu & Kelembaban Relatif DHT22 – $9.95
- Resistor pull‑up 4.7 kΩ
3. Menginstal SQLite
SQLite adalah mesin basis data ideal untuk komputer papan tunggal: tanpa server, ringan, dan sepenuhnya open source. Instal dengan:
sudo apt-get install sqlite3
Lalu buat direktori kerja dan file basis data:
mkdir Sensors_Database cd Sensors_Database sqlite3 sensorsData.db
Saat prompt SQLite muncul, keluar dengan .quit dan Anda akan kembali ke shell.
4. Membuat Tabel DHT
Tabel DHT_data menyimpan stempel waktu, suhu, dan kelembaban.
sqlite3 sensorsData.db BEGIN; CREATE TABLE DHT_data (timestamp DATETIME, temp NUMERIC, hum NUMERIC); COMMIT;
Atau, gunakan 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. Memasukkan Baris Contoh
Penyisipan manual melalui SQLite:
INSERT INTO DHT_data VALUES(datetime('now'), 20.5, 30);
Atau penyisipan massal dalam 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. Merangkaikan DHT22
Sambungkan VCC ke 3.3 V, Data ke GPIO 16, GND ke ground, dan tempatkan resistor pull‑up 4.7 kΩ antara VCC dan Data.
7. Menginstal Pustaka Adafruit DHT
Unduh dari GitHub dan instal:
sudo python3 setup.py install
8. Membaca dan Mencatat Data
Di bawah ini adalah skrip minimal yang membaca sensor, membulatkan nilai, dan menulisnya ke basis data:
import time import sqlite3 import Adafruit_DHT DB_NAME = 'sensorsData.db' SAMPLE_FREQ = 120 # detik 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. Pencatatan Berkelanjutan
Untuk logger waktu nyata, jalankan berikut ini di terminal terpadu. Ini menangkap sampel setiap menit:
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. Mengkueri Basis Data
Kueri umum:
- Semua baris:
SELECT * FROM DHT_data - Entri terakhir:
SELECT * FROM DHT_data ORDER BY timestamp DESC LIMIT 1 - Suhu > 30 °C:
SELECT * FROM DHT_data WHERE temp > 30 - Kelembaban = 29 %:
SELECT * FROM DHT_data WHERE hum = 29
11. Web Server Flask
Instal Flask: sudo apt-get install python3-flask. Buat struktur proyek:
mkdir dhtWebServer cd dhtWebServer mkdir templates static
Dalam 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>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. Meningkatkan Antarmuka Depan dengan Gage
Unduh JustGage dan tempatkan justgage.js dan raphael-2.1.4.min.js di static. Perbarui template untuk merender gage animasi:
<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. Grafik Sejarah dengan Matplotlib
Instal Matplotlib: sudo apt-get install python3-matplotlib. Buat aplikasi Flask baru appDhtWebHist.py yang menyajikan gambar PNG yang dihasilkan saat itu juga.
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() # urutan kronologis 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)
Template templates/index.html mencakup dua tag <img> yang meminta rute PNG.
14. Kesimpulan
Proyek ujung ke ujung ini menunjukkan cara mengubah sensor murah menjadi platform pencatatan dan pemantauan data: tangkap, simpan, kueri, dan visualisasikan semuanya melalui web server Flask lokal. Semua kode sumber tersedia di GitHub dan contoh lebih lanjut dapat ditemukan di MJRoBot.org.