#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
const char* WIFI_SSID = "Wokwi-GUEST";
const char* WIFI_PASSWORD = "";
const char* MQTT_SERVER = "broker.hivemq.com";
const int MQTT_PORT = 1883;
const char* MQTT_CLIENT_ID = "LANTABURA_LED_CTRL";
// Topic Publish
const char* TOPIC_STATUS_ALL = "Lanta/status";
const char* TOPIC_STATUS_BUTTON = "Lanta/button/status";
// Topic Subscribe
const char* TOPIC_LED1_ON = "Lanta/led1/on";
const char* TOPIC_LED1_OFF = "Lanta/led1/off";
const char* TOPIC_LED2_ON = "Lanta/led2/on";
const char* TOPIC_LED2_OFF = "Lanta/led2/off";
const char* TOPIC_ALT_ON = "Lanta/alternating/on";
const char* TOPIC_ALT_OFF = "Lanta/alternating/off";
// PIN
const int PIN_BUTTON = 4;
const int PIN_LED1 = 26;
const int PIN_LED2 = 27;
// Variabel
WiFiClient espClient;
PubSubClient mqttClient(espClient);
bool led1State = false;
bool led2State = false;
bool alternatingMode = false;
String buttonStatus = "RELEASED";
int lastButtonReading = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long DEBOUNCE_DELAY = 50;
bool alternateToggle = false;
unsigned long lastAlternateTime = 0;
const unsigned long ALTERNATE_INTERVAL = 500;
void applyLedOutputs() {
digitalWrite(PIN_LED1, led1State ? HIGH : LOW);
digitalWrite(PIN_LED2, led2State ? HIGH : LOW);
}
void publishStatusJSON() {
StaticJsonDocument<128> doc;
doc["led1"] = led1State ? "ON" : "OFF";
doc["led2"] = led2State ? "ON" : "OFF";
doc["alternating"] = alternatingMode ? "ON" : "OFF";
doc["button"] = buttonStatus; // Tambahkan baris ini
char buffer[128];
serializeJson(doc, buffer);
mqttClient.publish(TOPIC_STATUS_ALL, buffer, true);
Serial.print("[MQTT] Publish JSON: ");
Serial.println(buffer);
}
void led1On() {
if (alternatingMode) return;
led1State = true;
applyLedOutputs();
publishStatusJSON();
}
void led1Off() {
if (alternatingMode) return;
led1State = false;
applyLedOutputs();
publishStatusJSON();
}
void led2On() {
if (alternatingMode) return;
led2State = true;
applyLedOutputs();
publishStatusJSON();
}
void led2Off() {
if (alternatingMode) return;
led2State = false;
applyLedOutputs();
publishStatusJSON();
}
void alternatingOn() {
if (alternatingMode) return;
alternatingMode = true;
alternateToggle = true;
lastAlternateTime = millis();
publishStatusJSON();
Serial.println("[ALT] Mode alternating ON");
}
void alternatingOff() {
if (!alternatingMode) return;
alternatingMode = false;
led1State = false;
led2State = false;
applyLedOutputs();
publishStatusJSON();
Serial.println("[ALT] Mode alternating OFF");
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
String topicStr = String(topic);
String msg = "";
for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];
Serial.printf("[MQTT IN] Topic: %s | Payload: %s\n", topic, msg.c_str());
if (topicStr == TOPIC_LED1_ON) led1On();
else if (topicStr == TOPIC_LED1_OFF) led1Off();
else if (topicStr == TOPIC_LED2_ON) led2On();
else if (topicStr == TOPIC_LED2_OFF) led2Off();
else if (topicStr == TOPIC_ALT_ON) alternatingOn();
else if (topicStr == TOPIC_ALT_OFF) alternatingOff();
}
void connectWiFi() {
Serial.print("Menghubungkan ke WiFi");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi terhubung. IP: " + WiFi.localIP().toString());
}
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.print("Menghubungkan ke MQTT broker...");
if (mqttClient.connect(MQTT_CLIENT_ID)) {
Serial.println("Terhubung!");
mqttClient.subscribe(TOPIC_LED1_ON);
mqttClient.subscribe(TOPIC_LED1_OFF);
mqttClient.subscribe(TOPIC_LED2_ON);
mqttClient.subscribe(TOPIC_LED2_OFF);
mqttClient.subscribe(TOPIC_ALT_ON);
mqttClient.subscribe(TOPIC_ALT_OFF);
publishStatusJSON(); // Kirim status awal
} else {
Serial.printf("Gagal, rc=%d. Coba lagi 3 detik...\n", mqttClient.state());
delay(3000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(PIN_BUTTON, INPUT_PULLUP);
pinMode(PIN_LED1, OUTPUT);
pinMode(PIN_LED2, OUTPUT);
digitalWrite(PIN_LED1, LOW);
digitalWrite(PIN_LED2, LOW);
connectWiFi();
mqttClient.setServer(MQTT_SERVER, MQTT_PORT);
mqttClient.setCallback(mqttCallback);
}
void loop() {
if (!mqttClient.connected()) reconnectMQTT();
mqttClient.loop();
int reading = digitalRead(PIN_BUTTON);
if (reading != lastButtonReading) lastDebounceTime = millis();
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
if (reading != lastButtonState) {
lastButtonState = reading;
if (lastButtonState == LOW) {
Serial.println("[BUTTON] Ditekan");
buttonStatus = "PRESSED";
publishStatusJSON();
alternatingMode ? alternatingOff() : alternatingOn();
} else {
buttonStatus = "RELEASED";
publishStatusJSON();
}
}
}
lastButtonReading = reading;
if (alternatingMode) {
unsigned long now = millis();
if (now - lastAlternateTime >= ALTERNATE_INTERVAL) {
lastAlternateTime = now;
alternateToggle = !alternateToggle;
led1State = alternateToggle;
led2State = !alternateToggle;
applyLedOutputs();
publishStatusJSON();
}
}
}