1. Mengapa Grafana + InfluxDB?
Ketika kamu membangun sistem IoT, perangkat seperti ESP32, Arduino, atau Raspberry Pi akan menghasilkan data secara terus-menerus β suhu setiap detik, kelembaban setiap menit, tekanan atmosfer setiap jam. Data yang berubah seiring waktu ini disebut time-series data (data deret waktu).
Menyimpan dan memvisualisasikan data time-series membutuhkan tools khusus. Di sinilah InfluxDB dan Grafana hadir sebagai kombinasi terbaik yang banyak digunakan di industri IoT.
Apa Itu InfluxDB?
InfluxDB adalah Time-Series Database (TSDB) yang dirancang khusus untuk menyimpan data berbasis waktu. Berbeda dengan database relasional seperti MySQL atau PostgreSQL, InfluxDB dioptimalkan untuk:
- Penulisan tinggi β menerima ribuan data per detik dari ribuan sensor
- Kompresi otomatis β data lama dikompres secara otomatis sehingga hemat ruang
- Query time-series β operasi statistik rata-rata, minimum, maksimum berdasarkan rentang waktu
- Retention Policy β penghapusan data lama secara otomatis
Apa Itu Grafana?
Grafana adalah platform visualisasi data dan monitoring open-source. Grafana tidak menyimpan data β ia membaca data dari berbagai sumber (InfluxDB, PostgreSQL, Prometheus, dll.) dan menampilkannya dalam bentuk grafik, gauge, table, dan panel interaktif lainnya.
Kombinasi Sempurna untuk IoT
| Fitur | InfluxDB | Grafana |
|---|---|---|
| Fungsi Utama | Menyimpan data time-series | Memvisualisasikan data |
| Jenis Software | Database | Dashboard & Monitoring |
| Bahasa Query | InfluxQL / Flux | Membaca dari data source |
| Protokol Masuk Data | HTTP, MQTT, UDP, Telegraf | Read-only dari data source |
| Alerting | Checks & Notifications | Alert Rules & Contact Points |
| Dashboard | Tidak ada | Panel interaktif lengkap |
| License | Open Source (MIT) | Open Source (AGPL) |
Monitoring Suhu Server Room: Sensor DHT22 di ruang server mengirim data suhu ke InfluxDB setiap 5 detik. Grafana menampilkan grafik real-time, gauge suhu, dan alert jika suhu melebihi 35Β°C. Teknisi dapat melihat dashboard dari HP di mana saja.
Use case lain yang cocok dengan kombinasi ini:
- Monitoring Energi β konsumsi listrik per ruangan per jam
- Smart Agriculture β kelembaban tanah, curah hujan, intensitas cahaya
- Industrial IoT β getaran mesin, suhu furnace, tekanan pipa
- Smart Home β konsumsi air, listrik, gas secara real-time
- Network Monitoring β throughput, latency, packet loss
2. Instalasi InfluxDB 2.x
InfluxDB tersedia dalam beberapa metode instalasi. Untuk proyek IoT, kami merekomendasikan menggunakan Docker karena paling cepat dan mudah dikelola. Namun, kami juga akan membahas instalasi manual untuk server produksi.
Metode 1: Instalasi dengan Docker (Direkomendasikan)
Docker memungkinkan menjalankan InfluxDB tanpa perlu menginstal dependencies ke sistem. Cukup jalankan satu perintah:
docker run -d \ --name influxdb \ -p 8086:8086 \ -v influxdb-data:/var/lib/influxdb2 \ -v influxdb-config:/etc/influxdb2 \ -e DOCKER_INFLUXDB_INIT_MODE=setup \ -e DOCKER_INFLUXDB_INIT_USERNAME=admin \ -e DOCKER_INFLUXDB_INIT_PASSWORD=influxdb12345 \ -e DOCKER_INFLUXDB_INIT_ORG=my-org \ -e DOCKER_INFLUXDB_INIT_BUCKET=iot-data \ -e DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my-super-secret-token \ influxdb:2.7
Penjelasan parameter penting:
-p 8086:8086β Membuka port web interface InfluxDB-v influxdb-data:/var/lib/influxdb2β Persistent volume untuk data-e DOCKER_INFLUXDB_INIT_BUCKET=iot-dataβ Bucket awal bernama "iot-data"-e DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=...β Token API untuk autentikasi
Setelah container berjalan, akses InfluxDB UI di http://localhost:8086.
# Cek log InfluxDB docker logs influxdb # Cek status container docker ps | grep influxdb # Output yang diharapkan: # CONTAINER ID IMAGE STATUS PORTS # a1b2c3d4e5f6 influxdb:2.7 Up 2 minutes 0.0.0.0:8086->8086/tcp
Metode 2: Instalasi Manual di Ubuntu/Debian
# 1. Tambah repository InfluxDB curl --silent --location -O https://repos.influxdata.com/influxdata-archive.key echo "943666881a1b8d9b849b74caebf02d3465d6beb716510d86a39f6c8dc8267464 influxdata-archive.key" | sha256sum --check - && cat influxdata-archive.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive.gpg > /dev/null echo "deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main" | sudo tee /etc/apt/sources.list.d/influxdata.list # 2. Instalasi sudo apt-get update && sudo apt-get install influxdb2 # 3. Jalankan service sudo systemctl enable influxdb sudo systemctl start influxdb # 4. Setup awal via CLI influx setup \ --username admin \ --password influxdb12345 \ --org my-org \ --bucket iot-data \ --retention 0 \ --force
Token API yang dibuat saat setup awal bersifat admin full-access. Di lingkungan produksi, buat token terpisah dengan permission spesifik (read/write bucket tertentu) melalui UI InfluxDB β API Tokens β Generate API Token. Jangan pernah commit token ke repository Git!
Konsep Dasar InfluxDB
Penting untuk memahami struktur data InfluxDB sebelum mulai:
Measurement: suhu_ruang ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Tag: location=server-room-1 β β Fields: suhu=28.5, kelembaban=72.0 β β Timestamp: 2026-06-20T10:30:00Z β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β Tag: location=server-room-2 β β Fields: suhu=26.3, kelembaban=65.0 β β Timestamp: 2026-06-20T10:30:05Z β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β Tag: location=server-room-1 β β Fields: suhu=28.7, kelembaban=71.5 β β Timestamp: 2026-06-20T10:30:10Z β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Struktur: measurement,tag=value,tag=value field=value timestamp Bucket = Kumpulan data dengan retention policy Organization = Namespace untuk multi-tenant Token = Kunci akses API
Measurement sama dengan tabel di database relasional. Tag adalah metadata berbasis string yang diindeks untuk query cepat (contoh: lokasi sensor). Fields adalah data numerik atau string yang tidak diindeks (contoh: nilai suhu). Timestamp adalah kapan data direkam β ini yang membuat data "time-series".
3. Instalasi Grafana
Grafana tersedia dalam dua edisi utama: Grafana OSS (Open Source) dan Grafana Cloud (managed service). Untuk tutorial ini, kita menggunakan Grafana OSS yang dijalankan sendiri.
Metode 1: Instalasi dengan Docker (Direkomendasikan)
docker run -d \ --name grafana \ -p 3000:3000 \ -v grafana-data:/var/lib/grafana \ -e "GF_SECURITY_ADMIN_USER=admin" \ -e "GF_SECURITY_ADMIN_PASSWORD=grafana12345" \ -e "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-piechart-panel" \ grafana/grafana:latest
Setelah container berjalan, akses Grafana di http://localhost:3000 dengan username admin dan password grafana12345.
Metode 2: Instalasi Manual di Ubuntu/Debian
# 1. Tambah GPG key dan repository curl -fsSL https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list # 2. Instalasi sudo apt-get update sudo apt-get install -y grafana # 3. Jalankan service sudo systemctl enable grafana-server sudo systemctl start grafana-server # 4. Cek status sudo systemctl status grafana-server
File konfigurasi utama Grafana berada di /etc/grafana/grafana.ini. Beberapa pengaturan penting yang perlu dikonfigurasi untuk produksi:
[server] http_port = 3000 root_url = https://monitoring.example.com [security] admin_user = admin admin_password = ganti_dengan_password_kuat [auth.anonymous] enabled = false
Docker Compose: InfluxDB + Grafana Sekaligus
Untuk menjalankan InfluxDB dan Grafana bersamaan secara otomatis, gunakan Docker Compose:
version: "3.8"
services:
influxdb:
image: influxdb:2.7
container_name: influxdb
ports:
- "8086:8086"
volumes:
- influxdb-data:/var/lib/influxdb2
- influxdb-config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=influxdb12345
- DOCKER_INFLUXDB_INIT_ORG=my-org
- DOCKER_INFLUXDB_INIT_BUCKET=iot-data
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=my-super-secret-token
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=grafana12345
- GF_INSTALL_PLUGINS=grafana-clock-panel
depends_on:
- influxdb
restart: unless-stopped
volumes:
influxdb-data:
influxdb-config:
grafana-data:
networks:
default:
name: iot-monitoring
# Jalankan semua service docker compose up -d # Cek status docker compose ps # Output: # NAME IMAGE STATUS PORTS # grafana grafana/grafana:latest Up 5 seconds 0.0.0.0:3000->3000/tcp # influxdb influxdb:2.7 Up 5 seconds 0.0.0.0:8086->8086/tcp
4. Setup Data Source InfluxDB di Grafana
Grafana membutuhkan Data Source (sumber data) untuk mengetahui dari mana membaca data. Kita perlu menghubungkan Grafana ke InfluxDB agar dashboard dapat menampilkan data time-series.
Langkah-langkah Setup
- Buka Grafana di http://localhost:3000
- Login dengan username
admindan password yang sudah diatur - Klik menu βοΈ Settings β Data Sources (atau
βοΈ β Connections β Data sourcesdi Grafana versi baru) - Klik tombol "Add data source"
- Ketik "InfluxDB" pada kolom pencarian, lalu pilih
- Pilih Query Language: Flux (bukan InfluxQL)
- Isi konfigurasi berikut:
| Field | Nilai | Keterangan |
|---|---|---|
| HTTP URL | http://influxdb:8086 | Gunakan influxdb jika pakai Docker Compose (sesuai nama service). Gunakan localhost jika pakai instalasi manual. |
| Organization | my-org | Organization yang dibuat saat setup InfluxDB |
| Token | my-super-secret-token | API Token yang dibuat saat setup awal |
| Default Bucket | iot-data | Bucket default untuk query |
| HTTP Method | POST | Gunakan POST untuk query Flux |
Setelah mengisi semua field, scroll ke bawah dan klik tombol "Save & test". Jika konfigurasi benar, akan muncul pesan hijau "Data source is working". Jika merah, periksa URL, token, dan pastikan container InfluxDB berjalan.
Jika Menggunakan Docker Network Terpisah
Jika InfluxDB dan Grafana berjalan di container terpisah (bukan dalam satu docker-compose), pastikan mereka berada di jaringan Docker yang sama:
# Buat jaringan bersama docker network create iot-monitoring # Hubungkan container ke jaringan yang sama docker network connect iot-monitoring influxdb docker network connect iot-monitoring grafana
5. Membuat Dashboard: Panel, Graph, Gauge, Table
Setelah data source terkonfigurasi, saatnya membuat dashboard pertama. Dashboard di Grafana terdiri dari panel-panel β masing-masing menampilkan data dalam format berbeda.
Jenis Panel di Grafana
| Jenis Panel | Fungsi | Cocok Untuk |
|---|---|---|
| Time Series | Grafik garis berbasis waktu | Monitor tren suhu, kelembaban, tekanan dari waktu ke waktu |
| Gauge | Indikator analog seperti speedometer | Menampilkan nilai saat ini (suhu, voltage, persentase) |
| Stat | Angka besar satu nilai | Koneksi aktif, total energi, suhu rata-rata |
| Table | Data dalam format baris & kolom | Daftar sensor, log kejadian, data perangkat |
| Bar Gauge | Progress bar horizontal/vertikal | Kapasitas storage, utilisasi CPU, level baterai |
| Pie Chart | Grafik lingkaran proporsi | Distribusi error, kategori kejadian |
Membuat Panel Pertama: Grafik Suhu Real-Time
- Di halaman Grafana, klik β (Create) β New Dashboard β Add visualization
- Pilih Data Source InfluxDB
- Pada editor panel, tulis query Flux berikut:
from(bucket: "iot-data") |> range(start: -1h) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> aggregateWindow(every: 1m, fn: mean, createEmpty: false) |> yield(name: "suhu_realtime")
- Panel akan menampilkan grafik garis suhu dari 1 jam terakhir
- Klik "Apply" di pojok kanan atas
- Klik "Save Dashboard" (πΎ ikon simpan)
- Beri nama "IoT Monitoring Dashboard"
Menambahkan Panel Gauge
- Klik tombol "Add panel" (β) di dashboard
- Ubah tipe panel dari dropdown menjadi "Gauge"
- Tulis query untuk suhu terkini:
from(bucket: "iot-data") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> last() |> yield(name: "suhu_sekarang")
Pengaturan Panel Gauge
Setelah query berjalan, konfigurasi tampilan Gauge di panel sebelah kanan:
- Min:
0β batas bawah skala - Max:
50β batas atas skala (dalam Β°C) - Thresholds:
- Green: 0 β 30 (normal)
- Yellow: 30 β 35 (warning)
- Red: 35 β 50 (critical)
- Unit: Celsius (Β°C)
- Decimals: 1 (satu angka desimal)
Klik dan drag panel untuk mengatur ukuran dan posisi. Gunakan fitur Row untuk mengelompokkan panel (misal: "Suhu Ruangan", "Kelembaban", "Status Perangkat"). Klik ikon βοΈ pada panel untuk edit, atau ikon ποΈ untuk menghapus.
6. Query Flux untuk InfluxDB
Flux adalah bahasa query functional yang digunakan di InfluxDB 2.x. Flux jauh lebih fleksibel dibanding InfluxQL (bahasa query versi lama) karena mendukung operasi multi-measurement, transformasi data, dan join antar dataset.
Sintaks Dasar Flux
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β from() βββββΈβ range() βββββΈβ filter() βββββΈβ aggregateβββββΈ yield() β Pilih β β Rentang β β Saring β β Agregasi β Output β bucket β β waktu β β data β β window β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ Pipe operator (|>) mengalirkan data dari satu fungsi ke fungsi berikutnya Seperti unix pipe (|) di terminal bash
Contoh Query Penting
// 1. Rata-rata suhu per jam
from(bucket: "iot-data")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> aggregateWindow(every: 1h, fn: mean)
|> yield(name: "rata_rata_per_jam")
// 2. Suhu maksimum hari ini
from(bucket: "iot-data")
|> range(start: today())
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> max()
|> yield(name: "suhu_maks_hari_ini")
// 3. Nilai terakhir dari semua field
from(bucket: "iot-data")
|> range(start: -5m)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> last()
|> yield(name: "nilai_terakhir")
// 4. Suhu rata-rata per lokasi
from(bucket: "iot-data")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> group(columns: ["location"])
|> mean()
|> yield(name: "rata_rata_per_lokasi")
// 5. Batasi jumlah hasil (top 10)
from(bucket: "iot-data")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> sort(columns: ["_value"], desc: true)
|> limit(n: 10)
|> yield(name: "top_10_suhu")
// 6. Agregasi bergerak (moving average 5 data terakhir)
from(bucket: "iot-data")
|> range(start: -6h)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> movingAverage(n: 5)
|> yield(name: "moving_average")
// 7. Transformasi ke Fahrenheit
from(bucket: "iot-data")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "suhu_ruang")
|> filter(fn: (r) => r._field == "suhu")
|> map(fn: (r) => ({ r with _value: r._value * 1.8 + 32.0 }))
|> yield(name: "suhu_fahrenheit")
Fungsi Agregasi yang Sering Digunakan
| Fungsi | Fungsi | Contoh Penggunaan |
|---|---|---|
mean() | Rata-rata | Suhu rata-rata per jam |
min() | Minimum | Suhu terendah hari ini |
max() | Maksimum | Suhu tertinggi hari ini |
sum() | jumlah total | Total energi terkonsumsi |
count() | Jumlah data point | Jumlah pembacaan sensor |
stddev() | Standar deviasi | Stabilitas pembacaan sensor |
percentile() | Persentil | P99 latency |
Fungsi Window (aggregateWindow)
Fungsi aggregateWindow() membagi data ke dalam jendela waktu sebelum mengagregasi. Parameter every menentukan ukuran jendela:
|> aggregateWindow(every: 1m, fn: mean) // Rata-rata per menit |> aggregateWindow(every: 5m, fn: mean) // Rata-rata per 5 menit |> aggregateWindow(every: 1h, fn: mean) // Rata-rata per jam |> aggregateWindow(every: 1d, fn: mean) // Rata-rata per hari
7. Alerting di Grafana
Alerting adalah fitur kritis untuk sistem monitoring IoT. Grafana memungkinkan kamu membuat aturan alert yang akan mengirim notifikasi ke email, Telegram, Slack, atau webhook saat nilai data melewati threshold tertentu.
Konsep Alerting di Grafana
ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ β Data βββββΈβ Alert βββββΈβ Contact βββββΈβ Kirim β β Source β β Rule β β Point β β Notif β β (Query) β β (Threshold)β β (Email, β β (HP, β β β β β β TG, WA) β β Slack) β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββ Evaluasi berulang setiap interval tertentu (contoh: setiap 1 menit)
Langkah 1: Buat Contact Point (Kanal Notifikasi)
- Buka menu Alerting β Contact points
- Klik "Add contact point"
- Beri nama (misal:
"Admin Telegram") - Pilih tipe integrasi (Telegram, Email, Webhook, dll.)
Konfigurasi Notifikasi Email
[smtp] enabled = true host = smtp.gmail.com:587 user = alert@kamu.com password = app-password-gmail from_address = alert@kamu.com from_name = IoT Monitoring
Konfigurasi Notifikasi Telegram
Untuk Telegram, buat bot via @BotFather, dapatkan token, lalu konfigurasikan di Contact Point:
Integration: Telegram Bot Token: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz Chat ID: 123456789
Langkah 2: Buat Alert Rule (Aturan Alert)
- Buka menu Alerting β Alert rules
- Klik "New alert rule"
- Pilih Data Source InfluxDB
- Tulis query untuk data yang ingin dimonitor:
from(bucket: "iot-data") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> last()
Langkah 3: Atur Threshold & Label
| Pengaturan | Nilai | Keterangan |
|---|---|---|
| Evaluate every | 1m | Evaluasi alert setiap 1 menit |
| Evaluate for | 5m | Alert aktif jika kondisi terpenuhi selama 5 menit |
| Threshold | > 35 | Alert jika suhu melebihi 35Β°C |
| Severity | Critical | Tingkat keparahan: Warning, Critical |
| Summary | "Suhu melebihi 35Β°C!" | Pesan ringkas yang ditampilkan di notifikasi |
Langkah 4: Pilih Contact Point
Setelah alert rule tersimpan, pilih contact point yang ingin menerima notifikasi (misal: "Admin Telegram"). Alert akan dikirim ketika query menghasilkan nilai > 35.
- Jangan terlalu sensitif β atur Evaluate for minimal 5 menit untuk menghindari false alarm
- Gunakan severity levels: Warning untuk threshold awal, Critical untuk batas atas
- Gunakan grouping untuk menggabungkan notifikasi serupa dalam satu pesan
- Siapkan silence rules untuk maintenance window agar alert tidak mengganggu
8. Proyek: Dashboard Monitoring Suhu IoT Lengkap
Sekarang kita akan menggabungkan semua yang telah dipelajari ke dalam proyek lengkap. Kita akan membangun sistem monitoring suhu menggunakan ESP32 + DHT22 yang mengirim data ke InfluxDB, kemudian divisualisasikan di Grafana.
Arsitektur Sistem
ββββββββββββββ WiFi/HTTP βββββββββββββββ
β ESP32 β ββββββββββββββββββΈ β InfluxDB β
β + DHT22 β POST /api/v2/ β 2.7 β
β Sensor β write β :8086 β
β :3000 β β β
ββββββββββββββ ββββββββ¬βββββββ
β
β Flux Query
βΌ
βββββββββββββββ
β Grafana β
β Dashboard β
β :3000 β
β β
β π Grafik β
β π― Gauge β
β π Table β
β π Alert β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββ
β Notifikasi β
β Telegram / β
β Email β
βββββββββββββββ
Bagian 1: Kode ESP32 Mengirim Data ke InfluxDB
Kode ini membuat ESP32 membaca sensor DHT22 dan mengirim data ke InfluxDB melalui HTTP API setiap 30 detik:
// IoT Temperature Monitor - ESP32 + DHT22 + InfluxDB
// BeebaneLabs - https://beebanelabs.pages.dev
#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>
// === KONFIGURASI WIFI ===
const char* WIFI_SSID = "NamaWiFi";
const char* WIFI_PASS = "PasswordWiFi";
// === KONFIGURASI INFLUXDB ===
const char* INFLUXDB_URL = "http://192.168.1.100:8086/api/v2/write";
const char* INFLUXDB_ORG = "my-org";
const char* INFLUXDB_BUCKET = "iot-data";
const char* INFLUXDB_TOKEN = "my-super-secret-token";
// === KONFIGURASI SENSOR ===
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define SENSOR_LOCATION "server-room-1"
#define DEVICE_ID "esp32-001"
DHT dht(DHT_PIN, DHT_TYPE);
// Setup WiFi
void connectWiFi() {
Serial.print("Menghubungkan WiFi: ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("WiFi terhubung! IP: ");
Serial.println(WiFi.localIP());
}
// Kirim data ke InfluxDB
void kirimKeInfluxDB(float suhu, float kelembaban) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("[ERROR] WiFi terputus, mencoba reconnect...");
connectWiFi();
return;
}
HTTPClient http;
String url = String(INFLUXDB_URL) + "?org=" + INFLUXDB_ORG
+ "&bucket=" + INFLUXDB_BUCKET + "&precision=s";
http.begin(url);
http.addHeader("Authorization", "Token " + String(INFLUXDB_TOKEN));
http.addHeader("Content-Type", "text/plain");
// Format InfluxDB Line Protocol
// measurement,tag=value field=value timestamp
String payload = "suhu_ruang,location=" + String(SENSOR_LOCATION)
+ ",device=" + String(DEVICE_ID)
+ " suhu=" + String(suhu, 1)
+ ",kelembaban=" + String(kelembaban, 1)
+ " " + String(millis());
int httpCode = http.POST(payload);
if (httpCode == 204 || httpCode == 200) {
Serial.print("[OK] Data terkirim: suhu=");
Serial.print(suhu);
Serial.print("Β°C, kelembaban=");
Serial.print(kelembaban);
Serial.println("%");
} else {
Serial.print("[ERROR] HTTP ");
Serial.println(httpCode);
Serial.println(http.getString());
}
http.end();
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("=== IoT Temp Monitor ===");
dht.begin();
connectWiFi();
Serial.println("Siap mengirim data setiap 30 detik!");
}
void loop() {
float suhu = dht.readTemperature();
float kelembaban = dht.readHumidity();
if (isnan(suhu) || isnan(kelembaban)) {
Serial.println("[ERROR] Gagal membaca sensor!");
delay(5000);
return;
}
kirimKeInfluxDB(suhu, kelembaban);
delay(30000); // Kirim setiap 30 detik
}
Bagian 2: Membuat Dashboard Lengkap di Grafana
Berikut adalah layout dashboard yang akan kita buat dengan 6 panel:
| Panel | Tipe | Fungsi |
|---|---|---|
| Suhu Saat Ini | Gauge | Menampilkan suhu terkini dengan threshold warna |
| Kelembaban Saat Ini | Gauge | Menampilkan kelembaban terkini |
| Tren Suhu 24 Jam | Time Series | Grafik garis suhu per menit selama 24 jam |
| Tren Kelembaban 24 Jam | Time Series | Grafik garis kelembaban per menit |
| Statistik Harian | Stat | Min, Max, rata-rata suhu hari ini |
| Log Data Terbaru | Table | 10 data terakhir dengan timestamp |
Query Flux untuk setiap panel:
// === PANEL 1: Suhu Saat Ini (Gauge) === from(bucket: "iot-data") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> last() // === PANEL 2: Kelembaban Saat Ini (Gauge) === from(bucket: "iot-data") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "kelembaban") |> last() // === PANEL 3: Tren Suhu 24 Jam (Time Series) === from(bucket: "iot-data") |> range(start: -24h) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> aggregateWindow(every: 5m, fn: mean, createEmpty: false) |> yield(name: "tren_suhu") // === PANEL 4: Tren Kelembaban 24 Jam (Time Series) === from(bucket: "iot-data") |> range(start: -24h) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "kelembaban") |> aggregateWindow(every: 5m, fn: mean, createEmpty: false) |> yield(name: "tren_kelembaban") // === PANEL 5: Statistik Harian (Stat) === // Gunakan 3 query terpisah: // Query A (min): from(bucket: "iot-data") |> range(start: today()) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> min() |> yield(name: "min_suhu") // Query B (max): from(bucket: "iot-data") |> range(start: today()) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> max() |> yield(name: "max_suhu") // Query C (mean): from(bucket: "iot-data") |> range(start: today()) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> mean() |> yield(name: "mean_suhu") // === PANEL 6: Log Data Terbaru (Table) === from(bucket: "iot-data") |> range(start: -1h) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu" or r._field == "kelembaban") |> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value") |> sort(columns: ["_time"], desc: true) |> limit(n: 10) |> yield(name: "log_terbaru")
Bagian 3: Setup Alert di Proyek
Buat alert rule di Grafana dengan query berikut:
from(bucket: "iot-data") |> range(start: -5m) |> filter(fn: (r) => r._measurement == "suhu_ruang") |> filter(fn: (r) => r._field == "suhu") |> aggregateWindow(every: 1m, fn: mean) |> last()
Pengaturan alert:
- Evaluate every: 1 menit
- Evaluate for: 3 menit
- Threshold Warning: suhu > 32Β°C
- Threshold Critical: suhu > 35Β°C
- Contact Point: Telegram bot + Email admin
Pastikan semuanya berjalan:
- β ESP32 terhubung WiFi dan mengirim data ke InfluxDB
- β
Data muncul di InfluxDB UI (
localhost:8086 β Data Explorer) - β Grafana dashboard menampilkan 6 panel dengan data real-time
- β Alert dikirim ke Telegram/email saat suhu > 35Β°C
- β Dashboard bisa diakses dari browser HP di jaringan yang sama
9. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Grafana dan InfluxDB: