Pendahuluan

Di Seri 1 dan awal Seri 2, ESP32 kamu mengirim data sensor ke test.mosquitto.org — broker MQTT publik tanpa password. Itu bagus untuk belajar, tapi tidak layak produksi: siapa saja bisa subscribe topic kamu, data bisa dibaca orang lain, dan broker publik bisa down tanpa pemberitahuan.

Di artikel NVS + WiFiManager (#12) kita sudah menyiapkan firmware tanpa hardcode WiFi. Artikel ini melengkapi langkah berikutnya: broker MQTT pribadi dengan autentikasi username/password, lalu hubungkan ESP32 dengan pola NVS yang sama.

Ini adalah artikel pembuka Jalur B (infrastruktur & data) di Seri 2 — fondasi sebelum Python subscriber (#18), Grafana (#19), dan Home Assistant (#21).

Prasyarat: Paham dasar MQTT & publish ESP32 (#7). Familiar dengan NVS + WiFiManager (#12) sangat membantu untuk bagian firmware. Wiring DHT22 mengikuti Seri 1 (GPIO 4).

Yang Kamu Butuhkan

  • Server broker: Raspberry Pi (LAN) atau VPS Ubuntu/Debian dengan SSH
  • Laptop/PC untuk install Mosquitto dan uji mosquitto_sub
  • ESP32 DevKit + DHT22 (opsional tapi disarankan untuk uji end-to-end)
  • Akun SSH dengan sudo di mesin broker
  • Opsional: MQTT Explorer di laptop untuk inspeksi topic visual

Di artikel MQTT (#7) kita menjanjikan broker Mosquitto sendiri untuk production — artikel ini memenuhi janji itu. Di artikel #12 kamu sudah disarankan pindah dari test.mosquitto.org; sekarang kita pasang brokernya.

Broker Publik vs Broker Pribadi

Aspektest.mosquitto.orgMosquitto pribadi
AutentikasiTidak adaUsername + password wajib
Privasi dataTopic bisa dibaca siapa sajaHanya user yang diizinkan
KontrolTerbatasFull control config & ACL
BiayaGratisGratis (Pi di rumah) atau VPS ~50rb/bln
Cocok untukBelajar, uji cobaProduksi, smart home, klien

Dari artikel ini ke depan (roadmap Seri 2), proyek production disarankan memakai broker sendiri. Artikel #11–#15 masih boleh pakai broker publik saat belajar hardware.

Arsitektur Sistem

KomponenPeranKoneksi
ESP32Publisher (kirim data sensor)WiFi/LAN → MQTT :1883 + auth
MosquittoBroker pusatRaspberry Pi (LAN) atau VPS
mosquitto_subSubscriber CLILaptop → broker (uji coba)
MQTT ExplorerSubscriber GUILaptop / HP → broker
Python (#18)Subscriber + simpan dataLanjutan Jalur B → MySQL

Alur data secara singkat:

  [ ESP32 ]
      |
      |  WiFi/LAN  ·  MQTT :1883  ·  username + password
      v
  [ Mosquitto @ Pi / VPS ]
      |
      +-- mosquitto_sub  (laptop)
      +-- MQTT Explorer  (HP)
      +-- Python → MySQL (artikel #18, nanti)

Topic sensor tetap mengikuti konvensi Seri 1: kodingindonesia/esp32/dht22/data dengan payload JSON {"suhu":28.5,"kelembaban":65.2}.

Pilih Platform: Raspberry Pi vs VPS

OpsiKelebihanKekurangan
Raspberry Pi di rumahGratis setelah beli hardware; latency rendah di LANButuh IP statis/DDNS jika diakses dari luar; listrik 24/7
VPS (Ubuntu)IP publik tetap; akses dari mana sajaBiaya bulanan; latency lebih tinggi dari LAN

Perintah di bawah memakai Ubuntu / Debian (cocok untuk VPS dan Raspberry Pi OS). Login via SSH sebagai user dengan akses sudo.

Contoh IP di artikel ini: 192.168.1.50 = Mosquitto di jaringan lokal (Pi). Ganti dengan IP VPS atau hostname kamu, misalnya mqtt.rumahku.ddns.net.

Install Mosquitto

Update paket dan install Mosquitto broker + client tools:

sudo apt update
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable mosquitto
sudo systemctl start mosquitto
sudo systemctl status mosquitto --no-pager

Pastikan status active (running). Versi Mosquitto 2.x default di Ubuntu 22.04+ sudah cukup untuk tutorial ini.

Konfigurasi & Autentikasi

Buat file password untuk user MQTT (contoh user kindo_esp32):

sudo mosquitto_passwd -c /etc/mosquitto/passwd kindo_esp32
# masukkan password kuat, misalnya: KindoMQTT2026!

Edit konfigurasi utama:

sudo nano /etc/mosquitto/mosquitto.conf

Tambahkan (atau pastikan ada) baris berikut:

per_listener_settings true

listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice

Restart broker:

sudo systemctl restart mosquitto
sudo systemctl status mosquitto --no-pager

Mosquitto 2.x — konflik config: Ubuntu sering punya file default di /etc/mosquitto/conf.d/ (misalnya mosquitto.conf atau default.conf) yang masih allow_anonymous true. Jika auth tidak jalan, rename file tersebut (sudo mv ... ...bak) lalu restart — atau pastikan hanya satu listener 1883 aktif dengan allow_anonymous false.

User MQTT tambahan: Untuk user kedua, jangan pakai flag -c (itu menghapus file lama). Gunakan: sudo mosquitto_passwd /etc/mosquitto/passwd kindo_laptop

Broker bukan website: IP broker tidak dibuka di browser Chrome. MQTT berjalan di port 1883. Sama seperti penjelasan di artikel MQTT.

Firewall & Akses Jaringan

Di LAN (Raspberry Pi): ESP32 dan laptop harus satu jaringan WiFi dengan Pi. Tidak perlu buka port ke internet jika hanya dipakai di rumah.

Di VPS (akses dari internet): buka port 1883 — tapi ingat artikel ini belum pakai TLS (plain MQTT). Untuk production internet, lanjut ke artikel #17 (MQTT + TLS).

# VPS dengan UFW (opsional, hati-hati di production)
sudo ufw allow 1883/tcp
sudo ufw status
  • Pastikan ESP32 bisa ping IP broker (LAN) atau resolve hostname (VPS)
  • Router rumah: port forwarding 1883 hanya jika benar-benar perlu akses luar — prefer VPN atau TLS (#17)

Uji Coba dari Laptop

Terminal 1 — subscribe (ganti IP, user, password):

mosquitto_sub -h 192.168.1.50 -p 1883 \
  -u kindo_esp32 -P 'KindoMQTT2026!' \
  -t "kodingindonesia/esp32/dht22/data" -v

Terminal 2 — publish manual:

mosquitto_pub -h 192.168.1.50 -p 1883 \
  -u kindo_esp32 -P 'KindoMQTT2026!' \
  -t "kodingindonesia/esp32/dht22/data" \
  -m '{"suhu":25.0,"kelembaban":60.0}'

Jika Terminal 1 menampilkan payload, broker + autentikasi sudah benar. Alternatif GUI: buka MQTT Explorer, connect ke IP broker dengan username/password yang sama, subscribe topic di atas.

Pro tip: Buat user MQTT terpisah per perangkat (kindo_esp32_ruangtamu, kindo_esp32_kebun) agar lebih mudah audit dan revoke.

ESP32: Koneksi ke Broker + Auth (NVS)

Perluas pola WiFiManager + NVS (#12): simpan mqtt_host, mqtt_user, mqtt_pass di flash — tidak di sketch. Field custom di portal WiFiManager mengisi nilai awal saat provisioning.

Library (sama #12): WiFiManager (tzapu), PubSubClient (Nick O'Leary), DHT Adafruit + Unified Sensor. Board esp32 v3.x.

Sketch ringkas (DHT22 GPIO 4, topic Seri 1, AP portal KindoESP32-Setup):

#include <WiFi.h>
#include <WiFiManager.h>
#include <Preferences.h>
#include <PubSubClient.h>
#include <DHT.h>

#define DHT_PIN  4
#define DHT_TYPE DHT22
const char* NS_KINDO = "kindo";
const int MQTT_PORT = 1883;

DHT dht(DHT_PIN, DHT_TYPE);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
Preferences prefs;

String mqttHost, mqttUser, mqttPass, topicSensor;

WiFiManagerParameter pHost("mqtt_host", "MQTT broker IP/hostname", "192.168.1.50", 64);
WiFiManagerParameter pUser("mqtt_user", "MQTT username", "kindo_esp32", 32);
WiFiManagerParameter pPass("mqtt_pass", "MQTT password", "", 48);
WiFiManagerParameter pTopic("mqtt_topic", "MQTT topic", "kodingindonesia/esp32/dht22/data", 64);

void muatMqttDariNvs() {
  prefs.begin(NS_KINDO, true);
  mqttHost   = prefs.getString("mqtt_host", "192.168.1.50");
  mqttUser   = prefs.getString("mqtt_user", "kindo_esp32");
  mqttPass   = prefs.getString("mqtt_pass", "");
  topicSensor = prefs.getString("mqtt_topic", "kodingindonesia/esp32/dht22/data");
  prefs.end();
}

void simpanMqttKeNvs() {
  prefs.begin(NS_KINDO, false);
  prefs.putString("mqtt_host", pHost.getValue());
  prefs.putString("mqtt_user", pUser.getValue());
  prefs.putString("mqtt_pass", pPass.getValue());
  prefs.putString("mqtt_topic", pTopic.getValue());
  prefs.end();
}

bool setupWiFiManager() {
  WiFiManager wm;
  wm.setConfigPortalTimeout(180);
  wm.addParameter(&pHost);
  wm.addParameter(&pUser);
  wm.addParameter(&pPass);
  wm.addParameter(&pTopic);

  muatMqttDariNvs();
  pHost.setValue(mqttHost.c_str(), 64);
  pUser.setValue(mqttUser.c_str(), 32);
  pPass.setValue(mqttPass.c_str(), 48);
  pTopic.setValue(topicSensor.c_str(), 64);

  if (!wm.autoConnect("KindoESP32-Setup")) return false;
  simpanMqttKeNvs();
  return true;
}

bool koneksiMQTT() {
  mqttClient.setServer(mqttHost.c_str(), MQTT_PORT);
  mqttClient.setBufferSize(512);
  String clientId = "ESP32-MQTT-" + String(random(0xffff), HEX);
  if (mqttClient.connect(clientId.c_str(), mqttUser.c_str(), mqttPass.c_str())) {
    Serial.println("MQTT terhubung (auth)");
    return true;
  }
  Serial.print("MQTT gagal, rc=");
  Serial.println(mqttClient.state());
  return false;
}

void publishDHT() {
  float suhu = dht.readTemperature();
  float kelembaban = dht.readHumidity();
  if (isnan(suhu) || isnan(kelembaban)) return;

  char payload[96];
  snprintf(payload, sizeof(payload), "{\"suhu\":%.1f,\"kelembaban\":%.1f}", suhu, kelembaban);
  mqttClient.loop();
  if (mqttClient.publish(topicSensor.c_str(), payload, false)) {
    Serial.print("Publish OK → ");
    Serial.println(payload);
  } else {
    Serial.println("Publish gagal");
  }
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  delay(2000);
  if (!setupWiFiManager()) ESP.restart();
  if (!koneksiMQTT()) ESP.restart();
  publishDHT();
}

void loop() {
  mqttClient.loop();
  delay(10000);
  publishDHT();
}

Uji Coba ESP32 (End-to-End)

  1. Upload sketch, buka Serial Monitor 115200
  2. Portal KindoESP32-Setup — isi WiFi rumah + MQTT broker IP, username, password (sama seperti di mosquitto_passwd)
  3. Serial: MQTT terhubung (auth)Publish OK dengan JSON suhu/kelembaban
  4. Di laptop, jalankan mosquitto_sub ke broker yang sama — harus muncul payload dari ESP32
  5. Reboot ESP32 — harus connect tanpa portal (kredensial WiFi + MQTT sudah di NVS)

Pro tip topic: Gunakan topic unik per perangkat, misalnya kodingindonesia/anton/esp32/dht22/data, agar tidak bentrok jika banyak unit di satu broker.

Penjelasan Bagian Kritis

  • allow_anonymous false — broker menolak koneksi tanpa user/password
  • mqttClient.connect(..., user, pass) — overload PubSubClient dengan autentikasi
  • WiFiManagerParameter — provisioning host/user/pass lewat portal HP, lalu disimpan NVS
  • mqttClient.loop() — wajib sebelum publish() (konsisten Seri 1)
  • Port 1883 — plain MQTT; untuk internet publik gunakan TLS port 8883 di artikel #17

Tips & Troubleshooting

  • Connection refused (rc=-2): Mosquitto tidak jalan — cek systemctl status mosquitto
  • Not authorized (rc=5): Username/password salah — ulangi mosquitto_passwd
  • ESP32 tidak connect ke Pi: Pastikan satu subnet WiFi 2.4 GHz; cek IP Pi dengan hostname -I
  • VPS tidak bisa diakses: Cek firewall cloud provider + UFW; port 1883 harus terbuka
  • Config error saat restart: Cek log sudo tail -20 /var/log/mosquitto/mosquitto.log
  • Publish OK di laptop, ESP32 gagal: Cek field portal — password MQTT kosong di NVS
  • DHT22 NaN: delay(2000) setelah dht.begin(); GPIO 4 + pull-up — sama seperti tutorial DHT22
  • Auth gagal setelah edit config: Cek konflik file di /etc/mosquitto/conf.d/ (lihat catatan Mosquitto 2.x di atas)

Keamanan & Produksi

  • Jangan commit password MQTT ke GitHub — simpan di NVS / portal seperti WiFi
  • Plain MQTT (port 1883) di internet = password terkirim tanpa enkripsi → wajib TLS (#17) untuk deploy luar LAN
  • Pertimbangkan ACL Mosquitto agar user ESP32 hanya bisa publish ke topic tertentu
  • Backup file /etc/mosquitto/passwd secara aman

Langkah Selanjutnya (Seri 2)

  • Artikel #17: MQTT TLS, QoS, LWT & retained messages — amankan broker di internet
  • Artikel #18: Subscriber Python → simpan data MQTT ke MySQL
  • Artikel #21: Home Assistant — integrasi ESP32 via broker pribadi
  • Sensor BME280 via I2C — publish suhu, kelembaban & tekanan ke broker pribadi kamu
  • Kembali ke node deep sleep (#11) + NVS (#12) untuk stack lapangan lengkap

Dengan broker Mosquitto pribadi, kamu punya fondasi infrastruktur IoT sendiri — tidak lagi bergantung pada broker publik. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.