#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#include <ESP32Servo.h>
// WIFI
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT
const char* mqtt_server = "broker.hivemq.com";
const char* topic_pub = "smarthome/2330205030065/data";
const char* topic_sub = "smarthome/2330205030065/control";
WiFiClient espClient;
PubSubClient client(espClient);
// PIN
#define DHT_PIN 4
#define DHT_TYPE DHT22
#define LDR_PIN 34
#define PIR_PIN 27
#define MQ2_PIN 35
#define TRIG_PIN 18
#define ECHO_PIN 19
#define LED_PIN 26
#define RELAY_PIN 25
#define BUZZER_PIN 33
#define SERVO_PIN 13
// OBJECT
DHT dht(DHT_PIN, DHT_TYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myServo;
// MODE
String mode = "AUTO";
// SENSOR VARIABLES
float temperature = 0, humidity = 0;
int lightValue = 0, motionValue = 0, gasValue = 0;
float distanceCM = 0;
// MOVING AVERAGE
#define N 5
float tempArr[N];
int indexMA = 0;
// TIMING
unsigned long lastMillis = 0;
const long interval = 3000;
// THRESHOLD
int lightThreshold = 2000;
int gasThreshold = 2000;
// ================= FUNCTIONS =================
// WIFI
void connectWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" Connected!");
}
// MQTT
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Connecting MQTT...");
if (client.connect("ESP32Client-0065")) {
Serial.println("Connected");
client.subscribe(topic_sub);
} else {
Serial.println("Retry...");
delay(2000);
}
}
}
// ULTRASONIC
float readDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
if (duration == 0) return -1;
return duration * 0.034 / 2;
}
// MOVING AVERAGE
float movingAverage(float newVal) {
tempArr[indexMA] = newVal;
indexMA = (indexMA + 1) % N;
float sum = 0;
for (int i = 0; i < N; i++) sum += tempArr[i];
return sum / N;
}
// SENSOR READ
void readSensors() {
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) {
Serial.println("DHT ERROR!");
return;
}
temperature = movingAverage(t);
humidity = h;
lightValue = analogRead(LDR_PIN);
motionValue = digitalRead(PIR_PIN);
gasValue = analogRead(MQ2_PIN);
distanceCM = readDistance();
}
// CONTROL SYSTEM
void controlSystem() {
if (mode == "AUTO") {
digitalWrite(LED_PIN, (lightValue > lightThreshold || motionValue) ? HIGH : LOW);
digitalWrite(RELAY_PIN, (temperature > 28) ? HIGH : LOW);
digitalWrite(BUZZER_PIN, (gasValue > gasThreshold) ? HIGH : LOW);
myServo.write((distanceCM > 0 && distanceCM < 20) ? 90 : 0);
}
if (mode == "SECURITY") {
if (motionValue == HIGH) {
digitalWrite(BUZZER_PIN, HIGH);
client.publish(topic_pub, "{\"alert\":\"motion\"}", true);
} else {
digitalWrite(BUZZER_PIN, LOW);
}
}
}
// MQTT CALLBACK
void callback(char* topic, byte* payload, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) msg += (char)payload[i];
msg.trim();
Serial.println("CMD: " + msg);
if (msg == "AUTO") mode = "AUTO";
else if (msg == "MANUAL") mode = "MANUAL";
else if (msg == "SECURITY") mode = "SECURITY";
if (mode == "MANUAL") {
if (msg == "LAMP_ON") digitalWrite(LED_PIN, HIGH);
if (msg == "LAMP_OFF") digitalWrite(LED_PIN, LOW);
if (msg == "AC_ON") digitalWrite(RELAY_PIN, HIGH);
if (msg == "AC_OFF") digitalWrite(RELAY_PIN, LOW);
if (msg == "BUZZER_ON") digitalWrite(BUZZER_PIN, HIGH);
if (msg == "BUZZER_OFF") digitalWrite(BUZZER_PIN, LOW);
if (msg == "DOOR_OPEN") myServo.write(90);
if (msg == "DOOR_CLOSE") myServo.write(0);
}
}
// PUBLISH
void publishData() {
String payload = "{";
payload += "\"temp\":" + String(temperature) + ",";
payload += "\"hum\":" + String(humidity) + ",";
payload += "\"light\":" + String(lightValue) + ",";
payload += "\"motion\":" + String(motionValue) + ",";
payload += "\"gas\":" + String(gasValue) + ",";
payload += "\"distance\":" + String(distanceCM) + ",";
payload += "\"mode\":\"" + mode + "\"}";
client.publish(topic_pub, payload.c_str(), true);
Serial.println(payload);
}
// LCD
void updateLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("T:");
lcd.print(temperature);
lcd.print(" ");
lcd.print(mode);
lcd.setCursor(0, 1);
lcd.print("L:");
lcd.print(lightValue);
}
// ================= SETUP =================
void setup() {
Serial.begin(115200);
connectWiFi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dht.begin();
pinMode(PIR_PIN, INPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
myServo.attach(SERVO_PIN);
lcd.init();
lcd.backlight();
}
// ================= LOOP =================
void loop() {
if (WiFi.status() != WL_CONNECTED) connectWiFi();
if (!client.connected()) reconnectMQTT();
client.loop();
if (millis() - lastMillis > interval) {
lastMillis = millis();
readSensors();
controlSystem();
publishData();
updateLCD();
}
}