#include <WiFi.h>
#include <PubSubClient.h>
#include <Ultrasonic.h>
#include <ESP32Servo.h>
// Pin Definitions (tetap sama)
#define TRIG_PIN 13
#define ECHO_PIN 12
#define LED_MERAH 14
#define BUZZER_PIN 15
#define FLOW_PIN 34
#define SERVO_PIN 27
#define LED_KUNING 26
// Konfigurasi WiFi untuk Wokwi
const char* ssid = "Wokwi-GUEST";
const char* password = ""; // Tidak ada password di Wokwi
// MQTT Config
const char* mqttServer = "broker.emqx.io";
const int mqttPort = 1883;
// Topik MQTT (harus sama dengan yang di Laravel)
const char* topicKetinggian = "smartdrainage/ketinggian";
const char* topicFlow = "smartdrainage/flow";
const char* topicStatus = "smartdrainage/status";
Ultrasonic ultrasonic(TRIG_PIN, ECHO_PIN);
Servo pintuAir;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
pinMode(LED_MERAH, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_KUNING, OUTPUT);
pintuAir.attach(SERVO_PIN);
// Koneksi WiFi khusus Wokwi
Serial.print("Connecting to Wokwi WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("\nConnected to Wokwi WiFi!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Setup MQTT
client.setServer(mqttServer, mqttPort);
}
void loop() {
// Memastikan koneksi MQTT tetap aktif
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
// BAGIAN INTI PROGRAM (TIDAK BERUBAH) --------------------------
float distance = ultrasonic.read(); // cm
float ketinggianAir = distance;
int flowRaw = analogRead(FLOW_PIN);
float flowRate = (flowRaw / 4095.0) * 10.0; // Simulasi LPM
bool bahaya = (ketinggianAir < 20 && flowRate < 1.0);
bool bukaPintu = (ketinggianAir > 50);
bool flowTinggi = (flowRate > 9.0);
digitalWrite(LED_MERAH, bahaya ? HIGH : LOW);
digitalWrite(BUZZER_PIN, bahaya ? HIGH : LOW);
digitalWrite(LED_KUNING, flowTinggi ? HIGH : LOW);
pintuAir.write(bukaPintu ? 90 : 0);
// Serial Monitor Output (tidak berubah)
Serial.println("=== MONITORING SISTEM DRAINASE ===");
Serial.print("Ketinggian Air : ");
Serial.print(ketinggianAir);
Serial.println(" cm");
Serial.print("Flow Rate : ");
Serial.print(flowRate);
Serial.println(" LPM");
Serial.print("Status Peringatan: ");
if (bahaya) {
Serial.println("⚠ TERSEDIA PENYUMBATAN! (air rendah + aliran lambat)");
} else {
Serial.println("✅ Aman");
}
Serial.print("Status Pintu Air: ");
Serial.println(bukaPintu ? "🔓 TERBUKA" : "🔒 TERTUTUP");
Serial.print("Status Aliran: ");
Serial.println(flowTinggi ? "⚠ Aliran terlalu tinggi!" : "Normal");
Serial.println("----------------------------------\n");
// -------------------------------------------------------------
// Kirim data ke MQTT setiap 5 detik
static unsigned long lastSend = 0;
if (millis() - lastSend > 5000) {
publishToMQTT(ketinggianAir, flowRate, bahaya,
digitalRead(LED_MERAH),
digitalRead(LED_KUNING),
digitalRead(BUZZER_PIN),
bukaPintu,
flowTinggi);
lastSend = millis();
}
delay(100);
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
if (client.connect("ESP32_Wokwi_Client", "", "")) { // Explicit empty username/password
Serial.println("connected");
// Resubscribe jika perlu
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" retrying in 5s...");
delay(5000);
}
}
}
// Fungsi publish dengan data lengkap status sistem
void publishToMQTT(float ketinggian, float flow, bool bahaya,
bool ledMerah, bool ledKuning, bool buzzer, bool pintuAir, bool flowTinggi) {
if (!client.connected()) return;
char payload[20];
// Ketinggian air
snprintf(payload, sizeof(payload), "%.2f", ketinggian);
client.publish(topicKetinggian, payload);
// Flow rate
snprintf(payload, sizeof(payload), "%.2f", flow);
client.publish(topicFlow, payload);
// Status umum (Bahaya/Aman)
client.publish(topicStatus, bahaya ? "Bahaya" : "Aman");
// Status LED Merah
client.publish("smartdrainage/led_merah", ledMerah ? "ON" : "OFF");
// Status LED Kuning
client.publish("smartdrainage/led_kuning", ledKuning ? "ON" : "OFF");
// Status Buzzer
client.publish("smartdrainage/buzzer", buzzer ? "ON" : "OFF");
// Status Pintu Air
client.publish("smartdrainage/pintu_air", pintuAir ? "TERBUKA" : "TERTUTUP");
// Status Aliran (Normal / Tinggi)
client.publish("smartdrainage/status_aliran", flowTinggi ? "Tinggi" : "Normal");
}