Cara Menggabungkan Web Server dan MQTT di ESP32 — Simulasi Online
IoT Combo adalah proyek ESP32 paling lengkap di Noviot: web server dan MQTT berjalan bersamaan dalam satu sketch. Suhu diterbitkan ke MQTT setiap 2 detik, halaman web menampilkan status terakhir, dan lampu di GPIO2 bisa dikendalikan dari dua arah.
Komponen yang dipakai
- ESP32
- Breadboard (setengah)
- LED
- Resistor
Cara kerja
- ESP32 terhubung ke WiFi, menjalankan WebServer di port 80, dan terhubung ke broker MQTT virtual.
- Halaman utama menampilkan suhu terakhir dan tombol untuk menyalakan atau mematikan lampu.
- Route /toggle dan pesan MQTT ON/OFF pada topik noviot/lampu sama-sama mengubah keadaan LED GPIO2.
- Di loop(), server.handleClient() dan client.loop() dipanggil bergantian agar kedua layanan tetap responsif.
Konsep yang dipelajari
Kode program
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <uri/UriBraces.h>
#include <PubSubClient.h>
#define WIFI_SSID "NOVIOT"
#define WIFI_PASSWORD "12345678"
const char* MQTT_SERVER = "broker.noviot.local";
const int MQTT_PORT = 1883;
const char* TOPIK_SUHU = "noviot/suhu";
const char* TOPIK_LAMPU = "noviot/lampu";
const int LED_LAMPU = 2;
bool lampuNyala = false;
int suhu = 29;
unsigned long terakhirKirim = 0;
WebServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);
void kirimHalaman() {
String halaman = R"(
<!DOCTYPE html><html>
<head>
<title>IoT Combo ESP32</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="5">
<style>
body { font-family: sans-serif; text-align: center; }
.btn { background-color: #5B5; border: none; color: #fff; padding: 0.5em 1em;
font-size: 1.5em; text-decoration: none }
.btn.OFF { background-color: #333; }
</style>
</head>
<body>
<h1>IoT Combo</h1>
<p>Suhu terakhir (dari MQTT): SUHU_TEXT °C</p>
<p><a href="/toggle" class="btn LAMPU_CLASS">LAMPU_TEXT</a></p>
<p>Lampu juga bisa dikendalikan dari tab MQTT (topik noviot/lampu, pesan ON/OFF).</p>
</body>
</html>
)";
halaman.replace("SUHU_TEXT", String(suhu));
halaman.replace("LAMPU_CLASS", lampuNyala ? "" : "OFF");
halaman.replace("LAMPU_TEXT", lampuNyala ? "MATIKAN LAMPU" : "NYALAKAN LAMPU");
server.send(200, "text/html", halaman);
}
void callback(char* topic, byte* payload, unsigned int length) {
String pesan;
for (unsigned int i = 0; i < length; i++) {
pesan += (char)payload[i];
}
if (String(topic) == TOPIK_LAMPU) {
if (pesan == "ON") {
lampuNyala = true;
} else if (pesan == "OFF") {
lampuNyala = false;
}
digitalWrite(LED_LAMPU, lampuNyala ? HIGH : LOW);
Serial.print("Lampu dari MQTT: ");
Serial.println(lampuNyala ? "NYALA" : "MATI");
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_LAMPU, OUTPUT);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Menghubungkan ke WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Terhubung!");
server.on("/", kirimHalaman);
server.on("/toggle", []() {
lampuNyala = !lampuNyala;
digitalWrite(LED_LAMPU, lampuNyala ? HIGH : LOW);
Serial.print("Lampu dari web: ");
Serial.println(lampuNyala ? "NYALA" : "MATI");
kirimHalaman();
});
server.begin();
client.setServer(MQTT_SERVER, MQTT_PORT);
client.setCallback(callback);
Serial.println("Web server + MQTT siap");
}
void loop() {
server.handleClient();
if (!client.connected()) {
if (client.connect("noviot-combo")) {
client.subscribe(TOPIK_LAMPU);
Serial.println("MQTT terhubung, subscribe noviot/lampu");
} else {
delay(1000);
return;
}
}
client.loop();
if (millis() - terakhirKirim >= 2000) {
terakhirKirim = millis();
suhu += 1;
if (suhu > 34) suhu = 28;
client.publish(TOPIK_SUHU, String(suhu).c_str());
Serial.print("Publish suhu: ");
Serial.println(suhu);
}
delay(2);
}