#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ESP32Servo.h>
// ========== WIFI & MQTT ==========
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "pings-112.cloud.shiftr.io";
const int mqtt_port = 1883;
const char* mqtt_user = "pings-112";
const char* mqtt_pass = "pinsss";
WiFiClient espClient;
PubSubClient client(espClient);
// ========== PIN ==========
const int lampPins[4] = {23, 22, 21, 19};
const int doorPin = 5;
const int servoPin = 18;
const int DHT_PIN = 15;
// ========== OBJEK ==========
#define DHTTYPE DHT22
DHT dht(DHT_PIN, DHTTYPE);
Servo fanServo;
bool lampState[4] = {false, false, false, false};
bool doorLocked = true;
int fanAngle = 0;
// ========== WIFI CONNECT ==========
void setup_wifi() {
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
}
// ========== CALLBACK MQTT ==========
void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
String message = String((char*)payload);
String t = String(topic);
Serial.println("Topic: " + t + " | Message: " + message);
// Lampu
for (int i = 0; i < 4; i++) {
if (t == "iot/lamp/" + String(i+1)) {
lampState[i] = (message == "ON");
digitalWrite(lampPins[i], lampState[i] ? HIGH : LOW);
client.publish(("iot/status/lamp" + String(i+1)).c_str(), lampState[i] ? "ON" : "OFF");
}
}
// Fan (manual kontrol via MQTT)
if (t == "iot/fan") {
if (message == "ON") {
fanAngle = 90;
fanServo.write(fanAngle);
client.publish("iot/status/fan", "ON");
} else {
fanAngle = 0;
fanServo.write(fanAngle);
client.publish("iot/status/fan", "OFF");
}
}
// Door
if (t == "iot/door") {
doorLocked = (message == "LOCKED");
digitalWrite(doorPin, doorLocked ? HIGH : LOW);
client.publish("iot/status/door", doorLocked ? "LOCKED" : "UNLOCKED");
}
}
// ========== MQTT RECONNECT ==========
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP32Client", mqtt_user, mqtt_pass)) {
Serial.println("connected");
client.subscribe("iot/#"); // subscribe semua kontrol
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
delay(5000);
}
}
}
// ========== SETUP ==========
void setup() {
Serial.begin(115200);
// Pin lampu & door
for (int i = 0; i < 4; i++) pinMode(lampPins[i], OUTPUT);
pinMode(doorPin, OUTPUT);
// Servo
fanServo.attach(servoPin);
fanServo.write(0);
// DHT
dht.begin();
// WiFi & MQTT
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
// ========== LOOP ==========
void loop() {
if (!client.connected()) reconnect();
client.loop();
// Publish suhu & kelembaban tiap 5 detik
static unsigned long lastDHT = 0;
if (millis() - lastDHT > 3000) {
lastDHT = millis();
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (!isnan(temp) && !isnan(hum)) {
client.publish("iot/subscribe/suhu", String(temp,1).c_str());
client.publish("iot/subscribe/kelembaban", String(hum,1).c_str());
Serial.println("Temp: " + String(temp,1) + " °C | Hum: " + String(hum,1) + " %");
// ========== LOGIKA KIPAS BERDASARKAN SUHU ==========
if (temp >= 30.0) {
if (fanAngle != 90) { // hanya update jika beda
fanAngle = 90;
fanServo.write(fanAngle);
client.publish("iot/status/fan", "ON");
Serial.println("Fan otomatis ON (karena suhu >= 30°C)");
}
} else {
if (fanAngle != 0) {
fanAngle = 0;
fanServo.write(fanAngle);
client.publish("iot/status/fan", "OFF");
Serial.println("Fan otomatis OFF (karena suhu < 30°C)");
}
}
}
}
}