Pendahuluan
Selamat datang di artikel penutup seri ESP32 IoT Koding Indonesia! Sejauh ini kamu sudah belajar:
- Dashboard lokal lewat Web Server (artikel web server (#6))
- Telemetri remote lewat MQTT (artikel MQTT (#7))
- Proyek gabungan sensor + aktuator (artikel DHT22 + relay (#9))
- Kontrol lampu via MQTT (artikel relay (#8))
Kali ini kita satukan dua saluran monitoring dalam satu firmware:
- Lokal — buka IP ESP32 di browser rumah (cepat, tanpa internet)
- Remote — publish suhu ke broker MQTT (bisa dipantau dari mana saja lewat MQTT Explorer)
Ini pola nyata di IoT: edge device punya UI lokal untuk teknisi di lapangan, sekaligus mengirim data ke sistem pusat.
Yang Kamu Butuhkan
- ESP32 DevKit + sensor DHT22 (GPIO 4, pull-up 10kΩ)
- Kabel jumper
- Library: DHT sensor library, PubSubClient (WebServer & WiFi built-in)
- HP/laptop di WiFi yang sama + MQTT Explorer
Prasyarat: Sudah pernah membuat Web Server ESP32 (#6) dan publish MQTT (#7). Paham juga koneksi WiFi ESP32 (#4) dan wiring DHT22 (#5).
Arsitektur Proyek
| Saluran | Cara akses | Fungsi |
|---|---|---|
| Web Server (lokal) | http://IP_ESP32/ di WiFi rumah | Dashboard HTML + API /api/data |
| MQTT (remote) | test.mosquitto.org:1883 | Publish JSON ke kodingindonesia/esp32/dht22/data tiap 10 detik |
Topic MQTT sama dengan proyek gabungan (#9) agar konsisten di seluruh seri.
Catatan topik: Di artikel MQTT (#7) kita pakai kodingindonesia/esp32/dht22 (payload teks). Dari artikel gabungan ke dashboard ini kita pakai subtopic .../dht22/data dengan payload JSON — pola yang sama dengan artikel #9.
Broker bukan website —
test.mosquitto.orgtidak dibuka di browser. Gunakan MQTT Explorer atau ESP32.
Keamanan: Web server hanya untuk jaringan lokal — jangan expose ke internet tanpa autentikasi. Broker publik hanya untuk belajar; pakai topic unik dan jangan kirim data sensitif.
Kode Lengkap: Web Server + MQTT Publish
Ganti placeholder GANTI_SSID_WIFI / GANTI_PASSWORD_WIFI, lalu upload. Untuk produksi tanpa hardcode, lihat NVS + WiFiManager (#12).
#include <WiFi.h>
#include <WebServer.h>
#include <PubSubClient.h>
#include <DHT.h>
const char* ssid = "GANTI_SSID_WIFI";
const char* password = "GANTI_PASSWORD_WIFI";
const char* mqttServer = "test.mosquitto.org";
const int mqttPort = 1883;
const char* topicSensor = "kodingindonesia/esp32/dht22/data";
#define DHT_PIN 4
#define DHT_TYPE DHT22
DHT dht(DHT_PIN, DHT_TYPE);
WebServer server(80);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
float suhuTerakhir = 0;
float kelembabanTerakhir = 0;
unsigned long waktuBacaTerakhir = 0;
unsigned long terakhirPublish = 0;
const unsigned long intervalBaca = 2000;
const unsigned long intervalPublish = 10000;
String halamanDashboard() {
String html = "<!DOCTYPE html><html lang='id'><head><meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
html += "<title>ESP32 IoT Dashboard</title><style>";
html += "body{font-family:system-ui,sans-serif;max-width:480px;margin:40px auto;padding:20px;background:#f0f4f8;}";
html += "h1{color:#2979FF;font-size:1.4rem;} .card{background:#fff;border:3px solid #000;";
html += "box-shadow:4px 4px 0 #000;padding:20px;margin:12px 0;}";
html += ".nilai{font-size:2.2rem;font-weight:800;} .label{color:#666;font-size:0.85rem;text-transform:uppercase;}";
html += "</style></head><body><h1>ESP32 IoT Dashboard</h1>";
html += "<div class='card'><div class='label'>Suhu</div><div class='nilai'>";
html += String(suhuTerakhir, 1) + " °C</div></div>";
html += "<div class='card'><div class='label'>Kelembaban</div><div class='nilai'>";
html += String(kelembabanTerakhir, 1) + " %</div></div>";
html += "<p style='font-size:0.8rem;color:#888;'>Lokal · Koding Indonesia</p>";
html += "</body></html>";
return html;
}
void handleAPI() {
String json = "{\"suhu\":" + String(suhuTerakhir, 1);
json += ",\"kelembaban\":" + String(kelembabanTerakhir, 1) + "}";
server.send(200, "application/json", json);
}
void bacaSensor() {
if (millis() - waktuBacaTerakhir < intervalBaca) return;
waktuBacaTerakhir = millis();
float h = dht.readHumidity();
float t = dht.readTemperature();
if (!isnan(h) && !isnan(t)) {
kelembabanTerakhir = h;
suhuTerakhir = t;
}
}
void koneksiWiFi() {
Serial.print("Menghubungkan ke WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi terhubung!");
Serial.print("Dashboard lokal: http://");
Serial.println(WiFi.localIP());
}
void koneksiMQTT() {
mqttClient.setServer(mqttServer, mqttPort);
mqttClient.setBufferSize(512);
while (!mqttClient.connected()) {
Serial.print("MQTT connect...");
String clientId = "ESP32-Dash-" + String(random(0xffff), HEX);
if (mqttClient.connect(clientId.c_str())) {
Serial.println(" OK");
} else {
Serial.print(" gagal rc=");
Serial.println(mqttClient.state());
delay(5000);
}
}
}
void publishMQTT() {
if (waktuBacaTerakhir == 0) return;
if (isnan(suhuTerakhir) || isnan(kelembabanTerakhir)) return;
String payload = "{\"suhu\":" + String(suhuTerakhir, 1);
payload += ",\"kelembaban\":" + String(kelembabanTerakhir, 1) + "}";
if (mqttClient.publish(topicSensor, payload.c_str())) {
Serial.print("MQTT publish: ");
Serial.println(payload);
}
}
void setup() {
Serial.begin(115200);
randomSeed(micros());
dht.begin();
delay(2000);
koneksiWiFi();
server.on("/", []() { server.send(200, "text/html", halamanDashboard()); });
server.on("/api/data", handleAPI);
server.onNotFound([]() { server.send(404, "text/plain", "404"); });
server.begin();
Serial.println("Web Server aktif port 80");
koneksiMQTT();
delay(2000);
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
koneksiWiFi();
}
server.handleClient();
bacaSensor();
if (!mqttClient.connected()) {
koneksiMQTT();
}
mqttClient.loop();
unsigned long sekarang = millis();
if (sekarang - terakhirPublish >= intervalPublish) {
terakhirPublish = sekarang;
publishMQTT();
}
}
Uji Coba
1. Dashboard lokal
- Upload kode, buka Serial Monitor (115200 baud)
- Catat IP, misalnya
192.168.1.100 - Buka
http://192.168.1.100di browser (WiFi sama) - Cek API:
http://192.168.1.100/api/data - Refresh browser untuk nilai terbaru (dashboard statis per request — auto-refresh bisa ditambah dengan JavaScript)
2. Saluran MQTT (remote)
- Buka MQTT Explorer →
test.mosquitto.org:1883 - Cari topic
kodingindonesia/esp32/dht22/data - Pastikan JSON suhu/kelembaban masuk setiap ~10 detik
Alternatif: mosquitto_sub (Terminal)
mosquitto_sub -h test.mosquitto.org -t "kodingindonesia/esp32/dht22/data" -v
Tool CLI dari paket Mosquitto — Linux, Mac, dan Windows setelah install Mosquitto.
Alur Program
bacaSensor()— baca DHT22 tiap 2 detik, simpan ke variabel globalserver.handleClient()— layani dashboard & API saat ada request HTTPmqttClient.loop()— jaga koneksi MQTT tetap hiduppublishMQTT()— kirim JSON ke broker tiap 10 detik
Kedua saluran membaca variabel sensor yang sama — tidak ada pembacaan ganda yang bentrok.
Tips & Troubleshooting
- Browser tidak bisa buka IP ESP32: Pastikan HP/laptop satu WiFi dengan ESP32. Cek IP di Serial Monitor.
- MQTT publish gagal tapi web OK: Cek internet router.
mqttClient.loop()harus dipanggil diloop(). - rc=-2 / rc=4 MQTT: Broker tidak terjangkau atau masalah auth —
test.mosquitto.org:1883tanpa password. - Nilai suhu NaN di dashboard: Cek wiring DHT22, pull-up 10kΩ, dan
delay(2000)setelahdht.begin(). - Web lambat saat MQTT reconnect: Normal di jaringan WiFi rumah — reconnect MQTT pakai
delay(5000)di dalam blocking loop; untuk produksi pertimbangkan non-blocking reconnect. - Topic tidak muncul: Case-sensitive. Coba subscribe wildcard
kodingindonesia/esp32/#.
Indeks Seri ESP32 IoT (10 Artikel)
- Mengenal ESP32 (#1)
- Install Arduino IDE & ESP32 Board (#2)
- Blink LED — Tutorial Pertama (#3)
- ESP32 ke WiFi & Kirim Data (#4)
- Baca Sensor DHT22 (#5)
- Web Server Monitoring DHT22 (#6)
- MQTT — Kirim Data ke Broker (#7)
- Kontrol Lampu via MQTT & Relay (#8)
- Gabungan DHT22 + Relay MQTT (#9)
- Dashboard Web Server + MQTT (#10) — artikel ini (capstone)
Roadmap Belajar Selanjutnya — Seri 2
Seri 10 artikel ini adalah fondasi capstone. Seri 2 ESP32/IoT Lanjutan sudah lengkap — dua puluh sembilan artikel (urutan publish):
- Deep sleep ESP32 + DHT22 hemat baterai (#11)
- NVS + WiFiManager (#12) — konfigurasi tanpa hardcode
- Broker Mosquitto pribadi + autentikasi (#16)
- I2C + sensor BME280 (#13) — suhu, kelembaban & tekanan
- OLED SSD1306 (#14) — tampilkan data di layar I2C
- OTA update firmware ESP32 (#15) — update tanpa kabel USB
- Home Assistant + ESP32 MQTT (#21) — dashboard smart home
- ESPHome flash ESP32 tanpa Arduino (#22) — YAML + OTA
- Node-RED dashboard IoT MQTT (#23) — otomasi visual
- Sensor gerak PIR + lampu MQTT (#24) — automasi koridor dengan debounce
- MQTT TLS + QoS + LWT (#17) — amankan broker Mosquitto
- NTP & timestamp ESP32 (#34) — waktu akurat untuk log sensor MQTT
- Subscriber Python → MySQL (#18) — histori sensor MQTT ke database
- InfluxDB + Grafana (#19) — dashboard grafik histori sensor
- REST API vs MQTT (#20) — kapan pakai HTTP vs push MQTT
- ESP-NOW antar ESP32 tanpa router WiFi (#25) — peer-to-peer tanpa router
- LoRa ESP32 + SX1278 jarak jauh (#26) — sensor kilometer tanpa WiFi
- ESP32-CAM MJPEG streaming (#27) — live video & capture foto via WiFi
- Gateway LoRa → MQTT (#28) — sensor jarak jauh ke dashboard Grafana
- Migrasi ke PlatformIO di VS Code (#29) — project ESP32 lebih rapi dengan platformio.ini
- ESP32 + Firebase Realtime Database (#30) — sensor ke cloud tanpa server sendiri
- FreeRTOS multi-task Sensor + WiFi + MQTT (#31) — pecah firmware jadi task paralel
- Bluetooth BLE kirim data sensor ke smartphone (#32) — GATT server tanpa WiFi
- Kontrol Servo & PWM gerakan presisi via MQTT (#33) — SG90 sudut 0–180°
- ADC ESP32: Soil Moisture & LDR via MQTT (#35) — sensor analog tanah & cahaya
- ESP8266 / NodeMCU vs ESP32 (#36) — kapan pakai board murah vs upgrade
- SD Card & SPI logging offline (#37) — backup data sensor di lapangan
- HTTPS & sertifikat ESP32 (WiFiClientSecure) (#38) — REST API aman ke cloud
- Capstone Smart Greenhouse (#39) — multi-sensor + aktuator + dashboard MQTT
Seri 2 resmi selesai (29/29) — indeks lengkap juga ada di capstone #39.
Terima kasih sudah mengikuti seri ini! Kamu sekarang punya fondasi solid: sensor → WiFi → web lokal → MQTT → aktuator → dashboard hybrid. Share proyek kamu dan pantau terus artikel baru di Koding Indonesia.