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.

Board: ESP323 komponen

Komponen yang dipakai

  • ESP32
  • Breadboard (setengah)
  • LED
  • Resistor

Cara kerja

  1. ESP32 terhubung ke WiFi, menjalankan WebServer di port 80, dan terhubung ke broker MQTT virtual.
  2. Halaman utama menampilkan suhu terakhir dan tombol untuk menyalakan atau mematikan lampu.
  3. Route /toggle dan pesan MQTT ON/OFF pada topik noviot/lampu sama-sama mengubah keadaan LED GPIO2.
  4. Di loop(), server.handleClient() dan client.loop() dipanggil bergantian agar kedua layanan tetap responsif.

Konsep yang dipelajari

Dua layanan dalam satu sketchKendali dua arah (web dan MQTT)server.handleClient() dan client.loop()

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 &deg;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);
}

Template ESP32 lainnya