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?

AspekMySQL (#18)InfluxDB (artikel ini)
KekuatanRelasi, JOIN, laporan SQLGrafik time-series, retensi otomatis, downsampling
QuerySQLFlux (atau SQL di InfluxDB 3)
DashboardGrafana + datasource MySQLGrafana + datasource InfluxDB (native)
ProduksiBisa keduanya paralel: MySQL arsip, InfluxDB grafikTelegraf 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 subscriber kindo_subscriber dari #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 placeholder GANTI_* 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

  1. Buka http://192.168.1.50:3000 — login default admin / admin (ganti password saat pertama masuk)
  2. Connections → Data sources → Add data source → InfluxDB
  3. Query Language: Flux
  4. URL: http://influxdb:8086 (dari container Grafana) atau http://127.0.0.1:8086 jika Grafana di host
  5. Organization: kindo · Bucket: iot_sensors · Token: GANTI_INFLUX_TOKEN
  6. 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).

PanelTipeField
Suhu 24 jamTime seriessuhu
Kelembaban 24 jamTime serieskelembaban
Nilai sekarangStatkeduanya

Pro tip: Set timezone dashboard ke Asia/Jakarta (Dashboard settings → General) agar sumbu waktu cocok dengan timestamp lokal 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 aggregateWindow di Grafana agar panel tetap responsif meski data mentah menumpuk
  • Backup bucket penting via influx backup sebelum 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

  1. json_time_key = "unix" — waktu titik data = waktu sensor, bukan waktu Telegraf menerima pesan.
  2. name_override = "dht22" — measurement InfluxDB konsisten untuk query Flux.
  3. User kindo_subscriber — sama dengan #18; jangan pakai credential publisher ESP32.
  4. Topic — harus kodingindonesia/esp32/dht22/data (konsisten Seri 2).
  5. Retensi bucket — atur di InfluxDB (mis. 30 hari) agar disk Pi tidak penuh.
  6. Grafana vs Node-RED (#23) — Grafana fokus histori/grafik; Node-RED fokus otomasi visual.

Uji Coba (Checklist)

  1. docker compose ps — ketiga container running
  2. InfluxDB UI login + bucket iot_sensors ada
  3. ESP32 publish (atau mosquitto_pub dengan JSON + unix) → data muncul di Data Explorer
  4. Grafana datasource InfluxDB → test sukses
  5. Panel suhu menampilkan garis naik/turun (bukan flat kosong)
  6. Timezone dashboard Asia/Jakarta — jam cocok dengan WIB
  7. Restart Pi → docker compose up -d otomatis (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 unix kosong 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:8086 dari dalam jaringan Docker
  • Telegraf tidak reach Mosquitto: Dari container Docker, localhost bukan host Pi — pakai IP LAN host (192.168.1.50) atau tambahkan extra_hosts: ["host.docker.internal:host-gateway"] lalu tcp://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 .env ke 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)

Dengan InfluxDB dan Grafana, histori sensor ESP32 akhirnya terlihat — grafik interaktif siap dipantau dari browser. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.