#include <WiFi.h>
#include <PubSubClient.h>
#include <DHTesp.h>
// ========================
// WIFI CONFIG
// ========================
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
// MQTT
WiFiClient espClient;
PubSubClient client(espClient);
// ========================
// PIN DEFINITIONS
// ========================
#define DHT_PIN 13
#define TRIG_PIN 14
#define ECHO_PIN 27
#define PIR_PIN 2
#define BTN_PIN 32
#define RELAY_LAMPU 0
#define RELAY_POMPA 25
#define RELAY_PEMANAS 4
#define RELAY_KIPAS 26
#define RELAY_ALARM 5
// ========================
// SENSOR OBJECT
// ========================
DHTesp dht;
// ========================
// STATE VARIABEL
// ========================
bool lampuState = false;
bool lampuManual = false; // manual override dari MQTT
bool pompaState = false;
bool pompaManual = false;
bool pemanasState = false;
bool pemanasManual = false;
bool kipasState = false;
bool kipasManual = false;
bool alarmState = false;
bool alarmManual = false;
float suhu = 0;
float hum = 0;
float levelAir = 0;
bool adaOrang = false;
// ========================
// TIMER
// ========================
unsigned long now;
unsigned long lastMovement = 0;
unsigned long lastPublish = 0;
unsigned long lastDHTread = 0;
unsigned long lastUltra = 0;
unsigned long lastBtn = 0;
const unsigned long PIR_TIMEOUT = 10000;
const unsigned long BTN_DEBOUNCE = 250;
const unsigned long PUB_INT = 2000;
const unsigned long DHT_INT = 3000;
const unsigned long ULTRA_INT = 500;
// ========================
// WIFI CONNECT
// ========================
void setup_wifi() {
Serial.print("Menghubungkan ke WiFi ");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(300);
}
Serial.println("\n✔ WiFi Connected");
}
// ========================
// MQTT CALLBACK
// ========================
void callback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
String cmd = String((char*)payload);
String t = String(topic);
Serial.printf("MQTT [%s] = %s\n", topic, payload);
// ==== Lampu ====
if (t == "angel/iot/lampu/cmd") {
lampuManual = true;
lampuState = (cmd == "ON");
}
// ==== Pompa ====
if (t == "angel/iot/pompa/cmd") {
pompaManual = true;
pompaState = (cmd == "ON");
}
// ==== Pemanas ====
if (t == "angel/iot/pemanas/cmd") {
pemanasManual = true;
pemanasState = (cmd == "ON");
}
// ==== Kipas ====
if (t == "angel/iot/kipas/cmd") {
kipasManual = true;
kipasState = (cmd == "ON");
}
// ==== Alarm ====
if (t == "angel/iot/alarm/cmd") {
alarmManual = true;
alarmState = (cmd == "ON");
}
}
// ========================
// MQTT CONNECT
// ========================
void connectMQTT() {
while (!client.connected()) {
Serial.print("Menghubungkan MQTT... ");
if (client.connect("angelSmartHome01")) {
Serial.println("✔");
client.subscribe("angel/iot/+/cmd");
delay(300);
} else {
Serial.println("Retry...");
delay(1000);
}
}
}
// ========================
// ULTRASONIC
// ========================
float readUltrasonic() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long dur = pulseIn(ECHO_PIN, HIGH, 30000);
if (dur == 0) return levelAir;
return dur * 0.0343 / 2;
}
// ========================
// SETUP
// ========================
void setup() {
Serial.begin(115200);
pinMode(RELAY_LAMPU, OUTPUT);
pinMode(RELAY_POMPA, OUTPUT);
pinMode(RELAY_PEMANAS, OUTPUT);
pinMode(RELAY_KIPAS, OUTPUT);
pinMode(RELAY_ALARM, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(PIR_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
dht.setup(DHT_PIN, DHTesp::DHT22);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
connectMQTT();
Serial.println("\n=== SYSTEM READY ===");
}
// ========================
// LOOP
// ========================
void loop() {
now = millis();
if (!client.connected()) connectMQTT();
client.loop();
// ========================
// BUTTON LAMPU
// ========================
if (digitalRead(BTN_PIN) == LOW && now - lastBtn > BTN_DEBOUNCE) {
lampuManual = true;
lampuState = !lampuState;
Serial.println("Tombol Lampu ditekan");
lastBtn = now;
}
// ========================
// PIR GERAKAN
// ========================
adaOrang = digitalRead(PIR_PIN);
if (adaOrang) {
lastMovement = now;
if (!lampuManual) lampuState = true; // auto lampu
}
else if (now - lastMovement > PIR_TIMEOUT && !lampuManual) {
lampuState = false;
}
// ========================
// DHT SENSOR
// ========================
if (now - lastDHTread > DHT_INT) {
lastDHTread = now;
TempAndHumidity d = dht.getTempAndHumidity();
suhu = d.temperature;
hum = d.humidity;
}
// ========================
// ULTRASONIC
// ========================
if (now - lastUltra > ULTRA_INT) {
lastUltra = now;
levelAir = readUltrasonic();
}
// ====================================================
// 🔥 LOGIC SMART HOME (DENGAN PRIORITAS MANUAL)
// ====================================================
// ---- Pompa ----
if (!pompaManual) {
if (levelAir < 40) pompaState = true;
if (levelAir >= 80) pompaState = false;
}
// ---- Kipas ----
if (!kipasManual) {
kipasState = (suhu > 32);
}
// ---- Pemanas ----
if (!pemanasManual) {
pemanasState = (suhu < 20);
}
// ---- Alarm ----
if (!alarmManual) {
alarmState = (adaOrang || (suhu > 45 && levelAir < 20));
}
// ========================
// RELAY OUTPUT
// ========================
digitalWrite(RELAY_LAMPU, lampuState);
digitalWrite(RELAY_POMPA, pompaState);
digitalWrite(RELAY_PEMANAS, pemanasState);
digitalWrite(RELAY_KIPAS, kipasState);
digitalWrite(RELAY_ALARM, alarmState);
// ========================
// MQTT PUBLISH
// ========================
if (now - lastPublish > PUB_INT) {
lastPublish = now;
client.publish("angel/iot/suhu", String(suhu, 1).c_str());
client.publish("angel/iot/kelembaban", String(hum, 0).c_str());
client.publish("angel/iot/levelair", String(levelAir, 1).c_str());
client.publish("angel/iot/gerak", adaOrang ? "Ada" : "Tidak");
client.publish("angel/iot/lampu/status", lampuState ? "ON" : "OFF");
client.publish("angel/iot/pompa/status", pompaState ? "ON" : "OFF");
client.publish("angel/iot/kipas/status", kipasState ? "ON" : "OFF");
client.publish("angel/iot/pemanas/status", pemanasState ? "ON" : "OFF");
client.publish("angel/iot/alarm/status", alarmState ? "ON" : "OFF");
}
}