#include <WiFi.h>
#include <PubSubClient.h>
#include <DHTesp.h>
// ========================
// WIFI CONFIG
// ========================
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
// MQTT
WiFiClient espClient;
PubSubClient client(espClient);
// ========================
// PIN DEFINITIONS
// ========================
#define DHT_PIN 13
#define TRIG_PIN 4
#define ECHO_PIN 5
#define PIR_PIN 21
#define BTN_PIN 27
#define RELAY_LAMPU 32
#define RELAY_POMPA 25
#define RELAY_PEMANAS 14
#define RELAY_KIPAS 12
#define RELAY_ALARM 2
// ========================
// SENSOR OBJECT
// ========================
DHTesp dht;
// ========================
// STATE VARIABLES
// ========================
bool lampuState = false;
bool pompaState = false;
bool pemanasState = false;
bool kipasState = false;
bool alarmState = false;
float suhu = 0;
float hum = 0;
float levelAir = 0;
bool adaOrang = false;
// ========================
// TIMERS
// ========================
unsigned long now;
unsigned long lastMovement = 0;
unsigned long lastPublish = 0;
unsigned long lastDHTread = 0;
unsigned long lastUltra = 0;
unsigned long lastBtn = 0;
unsigned long lastSerial = 0;
// intervals
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;
const unsigned long SERIAL_INT = 10000;
// ========================
// WIFI CONNECT
// ========================
void setup_wifi() {
Serial.print("Connecting 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 top = String(topic);
Serial.printf("MQTT Received: [%s] %s\n", topic, payload);
if (top == "sabet/iot/lampu/cmd") lampuState = (cmd == "ON");
if (top == "sabet/iot/pompa/cmd") pompaState = (cmd == "ON");
if (top == "sabet/iot/pemanas/cmd") pemanasState = (cmd == "ON");
if (top == "sabet/iot/kipas/cmd") kipasState = (cmd == "ON");
if (top == "sabet/iot/alarm/cmd") alarmState = (cmd == "ON");
}
// ========================
// MQTT CONNECT
// ========================
void connectMQTT() {
while (!client.connected()) {
Serial.print("Menghubungkan MQTT...");
if (client.connect("rumahPintarMonitor01")) {
Serial.println(" ✔");
client.subscribe("sabet/iot/+/cmd");
} else {
Serial.println(" Gagal, retry...");
delay(1500);
}
}
}
// ========================
// 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);
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);
digitalWrite(RELAY_LAMPU, LOW);
digitalWrite(RELAY_POMPA, LOW);
digitalWrite(RELAY_PEMANAS, LOW);
digitalWrite(RELAY_KIPAS, LOW);
digitalWrite(RELAY_ALARM, LOW);
pinMode(PIR_PIN, INPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
dht.setup(DHT_PIN, DHTesp::DHT22);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
connectMQTT();
Serial.println("=== SYSTEM READY ===");
}
// ========================
// LOOP
// ========================
void loop() {
now = millis();
if (!client.connected()) connectMQTT();
client.loop();
// BUTTON
if (digitalRead(BTN_PIN) == LOW && now - lastBtn > BTN_DEBOUNCE) {
lampuState = !lampuState;
lastBtn = now;
}
// PIR
bool pir = digitalRead(PIR_PIN);
static unsigned long lastDetected = 0;
if (pir) {
lastDetected = now;
adaOrang = true;
} else if (now - lastDetected > 4000) {
adaOrang = false;
}
// DHT
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();
}
// ========================
// LOGIKA AKTUATOR
// ========================
// ✨ Lampu Otomatis
lampuState = adaOrang ? true : false;
// ✨ Pompa air
if (levelAir > 80) {
pompaState = LOW;
} else if (levelAir < 40) {
pompaState = HIGH;
}
// ✨ Kipas & Pemanas (logika seperti contohmu)
if (suhu > 30) {
pemanasState = LOW;
kipasState = HIGH;
}
else if (suhu > 26 && suhu <= 30) {
pemanasState = LOW;
kipasState = LOW;
}
else {
pemanasState = HIGH;
kipasState = LOW;
}
// ✨ Alarm
alarmState = (adaOrang || (suhu > 45 && levelAir < 20)) ? HIGH : LOW;
// ========================
// OUTPUT RELAY
// ========================
digitalWrite(RELAY_LAMPU, lampuState ? HIGH : LOW);
digitalWrite(RELAY_POMPA, pompaState ? HIGH : LOW);
digitalWrite(RELAY_PEMANAS, pemanasState ? HIGH : LOW);
digitalWrite(RELAY_KIPAS, kipasState ? HIGH : LOW);
digitalWrite(RELAY_ALARM, alarmState ? HIGH : LOW);
// ========================
// MQTT PUBLISH
// ========================
if (now - lastPublish >= PUB_INT) {
lastPublish = now;
client.publish("sabet/iot/suhu", String(suhu).c_str());
client.publish("sabet/iot/kelembaban", String(hum).c_str());
client.publish("sabet/iot/levelair", String(levelAir).c_str());
client.publish("sabet/iot/gerakan/status", adaOrang ? "ON" : "OFF");
// STATUS AKTUATOR (FIXED)
client.publish("sabet/iot/lampu/status", digitalRead(RELAY_LAMPU) == HIGH ? "ON" : "OFF", true);
client.publish("sabet/iot/pompa/status", digitalRead(RELAY_POMPA) == HIGH ? "ON" : "OFF", true);
client.publish("sabet/iot/pemanas/status", digitalRead(RELAY_PEMANAS) == HIGH ? "ON" : "OFF", true);
client.publish("sabet/iot/kipas/status", digitalRead(RELAY_KIPAS) == HIGH ? "ON" : "OFF", true);
client.publish("sabet/iot/alarm/status", digitalRead(RELAY_ALARM) == HIGH ? "ON" : "OFF", true);
}
// SERIAL MONITOR
if (now - lastSerial >= SERIAL_INT) {
lastSerial = now;
Serial.println("\n===== STATUS SISTEM =====");
Serial.printf("Suhu : %.1f °C\n", suhu);
Serial.printf("Kelembaban: %.0f %%\n", hum);
Serial.printf("Level Air : %.1f cm\n", levelAir);
Serial.printf("Gerakan : %s\n", adaOrang ? "ADA ORANG" : "NO");
}
}