featured image

IoT Home Automation System with ESP32

A comprehensive home automation system using ESP32 microcontrollers, MQTT protocol, and a React dashboard for controlling lights, temperature, and security.

Published

Tue Oct 15 2024

Technologies Used

ESP32 Arduino MQTT React IoT C++ Node.js Home Assistant
View on GitHub

Project Overview

This IoT home automation system demonstrates the integration of embedded systems with cloud services and web interfaces. The project uses ESP32 microcontrollers as edge devices, MQTT for communication, and a React-based dashboard for control and monitoring.

System Architecture

┌─────────────────┐
│  React Dashboard│
│   (Web/Mobile)  │
└────────┬────────┘


┌─────────────────┐
│  MQTT Broker    │
│  (Mosquitto)    │
└────────┬────────┘

    ┌────┴────┬────────┬────────┐
    ▼         ▼        ▼        ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
│ESP32  │ │ESP32  │ │ESP32  │ │ESP32  │
│Lights │ │Temp   │ │Door   │ │Camera │
└───────┘ └───────┘ └───────┘ └───────┘

Hardware Components

  • ESP32 DevKit - Main microcontroller (4 units)
  • DHT22 - Temperature and humidity sensor
  • Relay modules - For controlling AC devices
  • PIR motion sensors - For security monitoring
  • RGB LED strips - Smart lighting
  • Magnetic door sensors - Entry detection
  • ESP32-CAM - Security camera module

Firmware Implementation

The ESP32 firmware is written in C++ using the Arduino framework:

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// Configuration
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;

// Hardware pins
#define DHT_PIN 4
#define RELAY_PIN 5
#define PIR_PIN 18

DHT dht(DHT_PIN, DHT22);
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);
  
  // Initialize hardware
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(PIR_PIN, INPUT);
  dht.begin();
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
  
  // Connect to MQTT broker
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(mqttCallback);
  reconnectMQTT();
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  // Handle light control
  if (String(topic) == "home/living-room/light/set") {
    if (message == "ON") {
      digitalWrite(RELAY_PIN, HIGH);
      client.publish("home/living-room/light/state", "ON");
    } else if (message == "OFF") {
      digitalWrite(RELAY_PIN, LOW);
      client.publish("home/living-room/light/state", "OFF");
    }
  }
}

void loop() {
  if (!client.connected()) {
    reconnectMQTT();
  }
  client.loop();
  
  // Read and publish sensor data every 30 seconds
  static unsigned long lastRead = 0;
  if (millis() - lastRead > 30000) {
    float temperature = dht.readTemperature();
    float humidity = dht.readHumidity();
    
    if (!isnan(temperature) && !isnan(humidity)) {
      char tempStr[8];
      char humStr[8];
      dtostrf(temperature, 6, 2, tempStr);
      dtostrf(humidity, 6, 2, humStr);
      
      client.publish("home/living-room/temperature", tempStr);
      client.publish("home/living-room/humidity", humStr);
    }
    
    lastRead = millis();
  }
  
  // Check motion sensor
  if (digitalRead(PIR_PIN) == HIGH) {
    client.publish("home/living-room/motion", "DETECTED");
    delay(1000); // Debounce
  }
}

void reconnectMQTT() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32_LivingRoom")) {
      Serial.println("connected");
      client.subscribe("home/living-room/light/set");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" retrying in 5 seconds");
      delay(5000);
    }
  }
}

Dashboard Implementation

The React dashboard provides real-time monitoring and control:

import { useEffect, useState } from 'react';
import mqtt from 'mqtt';

interface DeviceState {
  temperature: number;
  humidity: number;
  lightOn: boolean;
  motionDetected: boolean;
}

export const Dashboard = () => {
  const [client, setClient] = useState<mqtt.MqttClient | null>(null);
  const [devices, setDevices] = useState<Record<string, DeviceState>>({});

  useEffect(() => {
    const mqttClient = mqtt.connect('ws://192.168.1.100:9001');
    
    mqttClient.on('connect', () => {
      console.log('Connected to MQTT broker');
      mqttClient.subscribe('home/#');
    });
    
    mqttClient.on('message', (topic, message) => {
      const value = message.toString();
      const parts = topic.split('/');
      const room = parts[1];
      const sensor = parts[2];
      
      setDevices(prev => ({
        ...prev,
        [room]: {
          ...prev[room],
          [sensor]: parseFloat(value) || value
        }
      }));
    });
    
    setClient(mqttClient);
    
    return () => {
      mqttClient.end();
    };
  }, []);

  const toggleLight = (room: string, state: boolean) => {
    if (client) {
      client.publish(`home/${room}/light/set`, state ? 'ON' : 'OFF');
    }
  };

  return (
    <div className="dashboard">
      <h1>Home Automation Dashboard</h1>
      
      {Object.entries(devices).map(([room, state]) => (
        <div key={room} className="room-card">
          <h2>{room}</h2>
          
          <div className="sensor-data">
            <p>Temperature: {state.temperatureC</p>
            <p>Humidity: {state.humidity}%</p>
            <p>Motion: {state.motionDetected ? '🚨 Detected' : '✅ Clear'}</p>
          </div>
          
          <button
            onClick={() => toggleLight(room, !state.lightOn)}
            className={state.lightOn ? 'light-on' : 'light-off'}
          >
            {state.lightOn ? '💡 Turn Off' : '🌙 Turn On'}
          </button>
        </div>
      ))}
    </div>
  );
};

Key Features

  1. Real-time monitoring of temperature, humidity, and motion
  2. Remote control of lights and appliances
  3. Security alerts via motion detection
  4. Energy monitoring with power consumption tracking
  5. Automation rules (e.g., turn on lights at sunset)
  6. Mobile-responsive dashboard
  7. Low latency communication via MQTT

Challenges & Solutions

Challenge 1: WiFi Reliability

Problem: ESP32 devices would occasionally lose WiFi connection.

Solution: Implemented automatic reconnection with exponential backoff and watchdog timer to reset the device if connection fails for too long.

Challenge 2: Power Management

Problem: Devices needed to run 24/7 but consumed significant power.

Solution: Used deep sleep mode between sensor readings and optimized WiFi usage to reduce power consumption by 70%.

Challenge 3: Security

Problem: MQTT traffic was unencrypted and vulnerable to attacks.

Solution: Implemented TLS encryption for MQTT, added authentication, and isolated IoT devices on a separate VLAN.

Lessons Learned

  1. Hardware debugging requires patience and systematic testing
  2. MQTT QoS levels matter for reliability
  3. OTA updates are essential for deployed devices
  4. Power consumption must be considered from the start
  5. Network segmentation is crucial for IoT security

Future Enhancements

  • Voice control integration (Alexa/Google Home)
  • Machine learning for predictive automation
  • Energy usage analytics and optimization
  • Integration with weather APIs for smart scheduling
  • Zigbee/Z-Wave support for commercial devices

Resources

Try It Out

Check out the live demo or explore the source code on GitHub.

We respect your privacy.

← View All Projects

Related Tutorials

    Ask me anything!