#include <WiFi.h>
#include <MQTT.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Library LCD I2C
#define LED_PIN 14
#define BUZZER_PIN 19
#define BUTTON_PIN 12
// Konfigurasi WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Konfigurasi MQTT
const char* broker = "broker.emqx.io";
int port = 1883;
const char* topic_pb = "testing/bsc/pb";
const char* topic_alert = "testing/bsc/alert";
const char* topic_wl = "testing/bsc/wl";
WiFiClient net;
MQTTClient client;
// LCD I2C (alamat 0x27 bisa berbeda tergantung modulnya)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Data statis
String serial_number = "ESP32-001";
String site_id = "site-a";
// Variabel untuk kirim data hanya jika ada perubahan
bool lastButtonState = HIGH;
// Variabel tampungan nilai untuk LCD
String waterLevel = "";
void updateLCDStatus() {
lcd.clear();
lcd.setCursor(0, 0);
if (WiFi.status() == WL_CONNECTED) {
lcd.print("WiFi:OK ");
} else {
lcd.print("WiFi:-- ");
}
if (client.connected()) {
lcd.print("MQTT:OK");
} else {
lcd.print("MQTT:--");
}
lcd.setCursor(0, 1);
if (waterLevel != "") {
lcd.print("WL:" + waterLevel + "%");
} else {
lcd.print("WL:--%");
}
}
void connectWiFi() {
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Menghubungkan ke WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" Terhubung!");
}
}
void connectMQTT() {
Serial.print("Menghubungkan ke MQTT...");
while (!client.connect("unknown_client")) {
Serial.print(".");
delay(1000);
}
Serial.println(" Terhubung ke broker MQTT!");
client.subscribe(topic_alert);
client.subscribe(topic_wl);
}
void messageReceived(String &topic, String &payload) {
Serial.println("Pesan masuk di topik: " + topic);
Serial.println("Payload: " + payload);
if (topic == topic_alert) {
// Parsing JSON untuk kontrol LED & buzzer
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
String recv_site_id = doc["site_id"] | "";
bool alert = doc["alert"] | false;
if (recv_site_id == site_id && alert) {
Serial.println("ALERT diterima! Menyalakan LED dan Buzzer selama 5 detik...");
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000); // 1 kHz
delay(5000);
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN);
}
} else {
Serial.println("Gagal parsing JSON");
}
}
else if (topic == topic_wl) {
// Simpan nilai water level untuk ditampilkan
waterLevel = payload;
}
updateLCDStatus();
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Inisialisasi LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Init...");
connectWiFi();
client.begin(broker, port, net);
client.onMessage(messageReceived);
connectMQTT();
updateLCDStatus();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
connectWiFi();
}
if (!client.connected()) {
connectMQTT();
}
client.loop();
int buttonState = digitalRead(BUTTON_PIN);
bool buttonPressed = (buttonState == LOW);
if (buttonState != lastButtonState) {
if (buttonPressed) {
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000);
} else {
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN);
}
// Buat JSON untuk publish tombol
String jsonPayload = "{";
jsonPayload += "\"serial_number\":\"" + serial_number + "\",";
jsonPayload += "\"site_id\":\"" + site_id + "\",";
jsonPayload += "\"button\":" + String(buttonPressed ? "true" : "false");
jsonPayload += "}";
client.publish(topic_pb, jsonPayload);
Serial.println("Kirim: " + jsonPayload);
lastButtonState = buttonState;
}
// Update LCD status secara periodik
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate > 2000) { // update tiap 2 detik
updateLCDStatus();
lastUpdate = millis();
}
}