Pendahuluan — Dari Database ke Dashboard
Di artikel #18, data sensor ESP32 sudah tersimpan di MySQL — bagus untuk query SQL dan ekspor. Tapi untuk grafik histori (zoom 24 jam, rata-rata per jam, alert suhu), stack industri memakai time-series database + dashboard.
Artikel Jalur B ini melengkapi pipeline: InfluxDB 2 menyimpan titik data sensor dengan timestamp akurat (#34), lalu Grafana menampilkan grafik suhu & kelembaban secara interaktif. ESP32 tetap publish ke MQTT seperti biasa — tidak perlu ubah firmware.
Prasyarat: Broker Mosquitto #16 jalan, payload JSON dengan
unix(#34), paham MQTT (#7). Disarankan sudah baca Python → MySQL (#18) untuk membandingkan dua pendekatan penyimpanan.
MySQL (#18) vs InfluxDB — Kapan Pakai Apa?
| Aspek | MySQL (#18) | InfluxDB (artikel ini) |
|---|---|---|
| Kekuatan | Relasi, JOIN, laporan SQL | Grafik time-series, retensi otomatis, downsampling |
| Query | SQL | Flux (atau SQL di InfluxDB 3) |
| Dashboard | Grafana + datasource MySQL | Grafana + datasource InfluxDB (native) |
| Produksi | Bisa keduanya paralel: MySQL arsip, InfluxDB grafik | Telegraf ringan, tanpa kode Python |
Arsitektur: MQTT → InfluxDB → Grafana
[ ESP32 + DHT22 ]
| publish JSON (suhu, kelembaban, unix)
v
[ Mosquitto #16 ] topic: kodingindonesia/esp32/dht22/data
|
+-- Opsi A: Telegraf (mqtt_consumer) --+
| v
+-- Opsi B: Python influxdb-client ----+--> [ InfluxDB 2 ] bucket: iot_sensors
|
v
[ Grafana :3000 ]
|
+-- Panel suhu / kelembaban 24 jam
Payload contoh (sama dengan #18 / #34):
{"suhu":28.5,"kelembaban":65.2,"timestamp":"2026-07-02T14:30:00","unix":1782977400}
Yang Kamu Butuhkan
- Raspberry Pi 4 / VPS — minimal 2 GB RAM (InfluxDB + Grafana + Mosquitto bisa satu mesin)
- Docker + Docker Compose
- InfluxDB 2.7, Grafana, Telegraf (opsi A)
- Atau Python 3.10+ +
influxdb-client(opsi B, mirip #18) - Broker
192.168.1.50:1883, user subscriberkindo_subscriberdari #18
Estimasi biaya: Rp 0 (open source) jika pakai Pi/VPS yang sudah ada; Grafana & InfluxDB gratis untuk self-host.
Docker Compose: InfluxDB + Grafana + Telegraf
Buat folder ~/kindo-iot-stack:
mkdir -p ~/kindo-iot-stack && cd ~/kindo-iot-stack
File docker-compose.yml:
services:
influxdb:
image: influxdb:2.7
container_name: kindo-influxdb
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- influxdb-data:/var/lib/influxdb2
environment:
DOCKER_INFLUXDB_INIT_MODE: setup
DOCKER_INFLUXDB_INIT_USERNAME: kindo_admin
DOCKER_INFLUXDB_INIT_PASSWORD: GANTI_PASSWORD_INFLUX_ADMIN
DOCKER_INFLUXDB_INIT_ORG: kindo
DOCKER_INFLUXDB_INIT_BUCKET: iot_sensors
DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: GANTI_INFLUX_TOKEN
grafana:
image: grafana/grafana:11.3.0
container_name: kindo-grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- influxdb
telegraf:
image: telegraf:1.32
container_name: kindo-telegraf
restart: unless-stopped
volumes:
- ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
depends_on:
- influxdb
volumes:
influxdb-data:
grafana-data:
docker compose up -d
docker compose ps
Pro tip: Simpan token InfluxDB di file
.env(jangan commit ke Git). Ganti semua placeholderGANTI_*sebelum production.
Telegraf: MQTT → InfluxDB (Opsi A — Tanpa Kode)
File telegraf.conf di folder yang sama:
[agent]
interval = "10s"
flush_interval = "10s"
[[outputs.influxdb_v2]]
urls = ["http://influxdb:8086"]
token = "GANTI_INFLUX_TOKEN"
organization = "kindo"
bucket = "iot_sensors"
[[inputs.mqtt_consumer]]
servers = ["tcp://192.168.1.50:1883"]
topics = ["kodingindonesia/esp32/dht22/data"]
username = "kindo_subscriber"
password = "GANTI_PASSWORD_SUBSCRIBER"
qos = 1
client_id = "kindo-telegraf"
data_format = "json"
json_time_key = "unix"
json_time_format = "unix"
name_override = "dht22"
Field suhu dan kelembaban dari JSON otomatis jadi field InfluxDB; timestamp dari unix (#34).
docker compose restart telegraf
docker logs kindo-telegraf --tail 20
Opsi B: Python → InfluxDB (Lanjutan #18)
Jika sudah nyaman dengan subscriber Python #18, tambahkan penulisan ke InfluxDB:
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS
INFLUX_URL = "http://127.0.0.1:8086"
INFLUX_TOKEN = "GANTI_INFLUX_TOKEN"
INFLUX_ORG = "kindo"
INFLUX_BUCKET = "iot_sensors"
client = InfluxDBClient(url=INFLUX_URL, token=INFLUX_TOKEN, org=INFLUX_ORG)
write_api = client.write_api(write_options=SYNCHRONOUS)
def simpan_ke_influx(payload: dict) -> None:
ts_ns = int(payload["unix"]) * 1_000_000_000
point = (
Point("dht22")
.field("suhu", float(payload.get("suhu", 0)))
.field("kelembaban", float(payload.get("kelembaban", 0)))
.time(ts_ns)
)
write_api.write(bucket=INFLUX_BUCKET, org=INFLUX_ORG, record=point)
Panggil simpan_ke_influx(data) di dalam on_message bersama atau menggantikan INSERT MySQL — terserah kebutuhan proyek.
Verifikasi Data di InfluxDB
Masuk ke UI InfluxDB: http://192.168.1.50:8086 → Data Explorer, atau CLI:
docker exec -it kindo-influxdb influx query '
from(bucket: "iot_sensors")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "dht22")
|> limit(n: 10)
' --org kindo --token GANTI_INFLUX_TOKEN
Harus muncul field suhu dan kelembaban dengan waktu yang masuk akal (bukan tahun 1970 — pastikan ESP32 sudah NTP).
Grafana: Datasource InfluxDB
- Buka
http://192.168.1.50:3000— login defaultadmin/admin(ganti password saat pertama masuk) - Connections → Data sources → Add data source → InfluxDB
- Query Language: Flux
- URL:
http://influxdb:8086(dari container Grafana) atauhttp://127.0.0.1:8086jika Grafana di host - Organization:
kindo· Bucket:iot_sensors· Token:GANTI_INFLUX_TOKEN - Save & test → harus hijau
Dashboard: Grafik Suhu & Kelembaban
Dashboard baru → Add visualization → Time series.
Query Flux untuk suhu (24 jam terakhir):
from(bucket: "iot_sensors")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "dht22")
|> filter(fn: (r) => r._field == "suhu")
|> aggregateWindow(every: 5m, fn: mean, createEmpty: false)
Duplikasi panel untuk _field == "kelembaban". Tambahkan panel Stat untuk nilai terakhir, dan Gauge opsional (0–100 % RH).
| Panel | Tipe | Field |
|---|---|---|
| Suhu 24 jam | Time series | suhu |
| Kelembaban 24 jam | Time series | kelembaban |
| Nilai sekarang | Stat | keduanya |
Pro tip: Set timezone dashboard ke Asia/Jakarta (Dashboard settings → General) agar sumbu waktu cocok dengan
timestamplokal ESP32 (#34).
Untuk variabel dashboard yang bisa dipakai ulang, simpan query Flux sebagai Dashboard variable (mis. $measurement = dht22 atau bme280 dari #13). Panel Stat bisa menampilkan Last value dengan unit °C dan % — cocok dipantau dari HP di jaringan LAN.
Uji Cepat Tanpa ESP32 (mosquitto_pub)
Sebelum firmware siap, kirim payload uji ke broker (#16) sebagai user subscriber:
mosquitto_pub -h 192.168.1.50 -p 1883 \
-u kindo_subscriber -P 'GANTI_PASSWORD_SUBSCRIBER' \
-t "kodingindonesia/esp32/dht22/data" \
-m '{"suhu":29.1,"kelembaban":62.0,"timestamp":"2026-07-02T14:30:00","unix":1782977400}'
Refresh Grafana — titik baru harus muncul dalam beberapa detik. Ulangi 3–5 kali dengan nilai berbeda untuk melihat garis naik/turun. Ini cara tercepat memastikan Telegraf, InfluxDB, dan Grafana terhubung tanpa debug firmware ESP32 sekaligus — sama seperti uji mosquitto_sub di artikel MQTT (#7).
Retensi Data & Penghematan Disk
InfluxDB 2 mengelola retensi lewat Bucket. Di UI InfluxDB: Data → Buckets → iot_sensors → Edit — set retensi misalnya 30 hari atau 90 hari tergantung kapasitas SD card Pi.
- Turunkan frekuensi publish ESP32 (mis. dari 5 detik ke 30 detik) jika grafik cukup update per menit
- Gunakan
aggregateWindowdi Grafana agar panel tetap responsif meski data mentah menumpuk - Backup bucket penting via
influx backupsebelum upgrade major version InfluxDB
MySQL dari #18 bisa tetap menyimpan arsip jangka panjang sementara InfluxDB fokus grafik operasional harian — kombinasi yang umum di proyek IoT skala kecil hingga menengah.
Alert Grafana (Opsional)
Grafana mendukung alert rules — misalnya notifikasi Telegram atau email jika suhu > 35 °C lebih dari 10 menit. Buat rule dari panel Time series → Alert → New alert rule. Query Flux sama seperti panel; set threshold dan contact point di Alerting → Contact points. Fitur ini berguna untuk greenhouse (#39) atau cold storage tanpa coding tambahan — melengkapi otomasi visual Node-RED (#23).
Auto-start Setelah Reboot Raspberry Pi
Docker Compose dengan restart: unless-stopped sudah cukup jika daemon Docker aktif saat boot. Pastikan:
sudo systemctl enable docker
cd ~/kindo-iot-stack && docker compose up -d
Setelah power cycle Pi, tunggu ~60 detik lalu buka Grafana — stack harus hidup otomatis. Telegraf akan reconnect ke MQTT broker #16 begitu jaringan siap; tidak perlu SSH manual setiap reboot kecuali ada perubahan telegraf.conf.
Opsi Bonus: Grafana + MySQL (Lanjutan #18)
Jika sudah punya data di tabel sensor_readings MySQL, Grafana juga bisa pakai MySQL datasource tanpa InfluxDB:
SELECT recorded_at AS time, suhu, kelembaban
FROM sensor_readings
WHERE recorded_at > NOW() - INTERVAL 24 HOUR
ORDER BY recorded_at;
InfluxDB lebih nyaman untuk jutaan titik data dan retensi otomatis; MySQL cukup untuk skala kecil. Banyak tim memakai keduanya: InfluxDB untuk live dashboard, MySQL untuk backup laporan bulanan.
Opsi TLS & Produksi
Deploy di internet: amankan MQTT dengan TLS #17 (port 8883). Telegraf mendukung tls_ca / tls_cert di blok mqtt_consumer. Grafana & InfluxDB sebaiknya di belakang reverse proxy HTTPS (Nginx) — jangan expose port 3000/8086 mentah ke internet tanpa auth kuat.
Penjelasan Bagian Kritis
json_time_key = "unix"— waktu titik data = waktu sensor, bukan waktu Telegraf menerima pesan.name_override = "dht22"— measurement InfluxDB konsisten untuk query Flux.- User
kindo_subscriber— sama dengan #18; jangan pakai credential publisher ESP32. - Topic — harus
kodingindonesia/esp32/dht22/data(konsisten Seri 2). - Retensi bucket — atur di InfluxDB (mis. 30 hari) agar disk Pi tidak penuh.
- Grafana vs Node-RED (#23) — Grafana fokus histori/grafik; Node-RED fokus otomasi visual.
Uji Coba (Checklist)
docker compose ps— ketiga container running- InfluxDB UI login + bucket
iot_sensorsada - ESP32 publish (atau
mosquitto_pubdengan JSON + unix) → data muncul di Data Explorer - Grafana datasource InfluxDB → test sukses
- Panel suhu menampilkan garis naik/turun (bukan flat kosong)
- Timezone dashboard Asia/Jakarta — jam cocok dengan WIB
- Restart Pi →
docker compose up -dotomatis (opsional: systemd unit)
Tips & Troubleshooting
- Grafik kosong: Cek range waktu dashboard (24h) vs data benar-benar masuk — query Flux manual di InfluxDB
- Timestamp 1970: Field
unixkosong di payload — aktifkan NTP di ESP32 (#34) - Telegraf rc=5 MQTT: User/password salah — samakan dengan
/etc/mosquitto/passwd - Grafana tidak reach InfluxDB: Pakai hostname container
http://influxdb:8086dari dalam jaringan Docker - Telegraf tidak reach Mosquitto: Dari container Docker,
localhostbukan host Pi — pakai IP LAN host (192.168.1.50) atau tambahkanextra_hosts: ["host.docker.internal:host-gateway"]lalutcp://host.docker.internal:1883 - Disk penuh: Kurangi retensi bucket atau turunkan frekuensi publish ESP32
- Port 3000 bentrok: Ubah mapping
"3001:3000"di compose - Data dobel MySQL + Influx: Normal jika jalankan #18 dan Telegraf bersamaan — atau pilih satu penyimpanan utama
Keamanan & Produksi
- Jangan commit token InfluxDB, password Grafana, atau
.envke GitHub - Ganti password default Grafana segera setelah instalasi
- Plain MQTT (1883) hanya untuk LAN — production pakai TLS #17
- Batasi akses Grafana dengan user/role — jangan publik tanpa HTTPS
Langkah Selanjutnya (Seri 2)
- REST API vs MQTT (#20) — kapan pakai HTTP polling vs push MQTT
- Python → MySQL (#18) — arsip SQL paralel dengan grafik InfluxDB
- Home Assistant (#21) — dashboard smart home alternatif
- BME280 (#13) — tambah field tekanan di measurement
bme280 - PIR (#24) — panel event gerak di Grafana
- Capstone greenhouse (#39) — sensor + pompa + dashboard Grafana
Dengan InfluxDB dan Grafana, histori sensor ESP32 akhirnya terlihat — grafik interaktif siap dipantau dari browser. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.