ESP32 Smart Doorbell with Notifications with step by step instructions

 

Project Overview



Create an intelligent doorbell system with video recording, motion detection, and smartphone notifications.

Key Features

  • Push button activation
  • ESP32-CAM integration
  • Instant notifications
  • Two-way audio (advanced)
  • Cloud image storage

Components Required

Diagram.json:
{
  "version": 1,
  "author": "ESP32 Smart Doorbell",
  "editor": "wokwi",
  "parts": [
    {
      "type": "wokwi-esp32-devkit-v1",
      "id": "esp",
      "top": 0,
      "left": 0,
      "attrs": {}
    },
    {
      "type": "wokwi-pushbutton",
      "id": "btn1",
      "top": -124.8,
      "left": 249.6,
      "attrs": { "color": "blue", "label": "DOORBELL" }
    },
    {
      "type": "wokwi-pir-motion-sensor",
      "id": "pir1",
      "top": -105.49,
      "left": 345.31,
      "attrs": {}
    },
    {
      "type": "wokwi-led",
      "id": "red_led",
      "top": -124.8,
      "left": 480,
      "attrs": { "color": "red", "lightColor": "red", "label": "R" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": -67.2,
      "left": 480,
      "rotate": 90,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-led",
      "id": "green_led",
      "top": -124.8,
      "left": 556.8,
      "attrs": { "color": "green", "lightColor": "green", "label": "G" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r2",
      "top": -67.2,
      "left": 556.8,
      "rotate": 90,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-led",
      "id": "blue_led",
      "top": -124.8,
      "left": 633.6,
      "attrs": { "color": "blue", "lightColor": "blue", "label": "B" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r3",
      "top": -67.2,
      "left": 633.6,
      "rotate": 90,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-led",
      "id": "camera_led",
      "top": 38.4,
      "left": 480,
      "attrs": { "color": "yellow", "lightColor": "yellow", "label": "Camera" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r4",
      "top": 96,
      "left": 480,
      "rotate": 90,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-led",
      "id": "lock_led",
      "top": 38.4,
      "left": 556.8,
      "attrs": { "color": "white", "lightColor": "white", "label": "Door Lock" }
    },
    {
      "type": "wokwi-resistor",
      "id": "r5",
      "top": 96,
      "left": 556.8,
      "rotate": 90,
      "attrs": { "value": "220" }
    },
    {
      "type": "wokwi-buzzer",
      "id": "bz1",
      "top": 172.8,
      "left": 518.4,
      "attrs": { "volume": "0.5" }
    },
    {
      "type": "wokwi-ssd1306",
      "id": "oled1",
      "top": 192,
      "left": 249.6,
      "attrs": { "i2cAddress": "0x3C" }
    },
    {
      "type": "wokwi-potentiometer",
      "id": "light1",
      "top": 86.4,
      "left": 326.4,
      "rotate": 180,
      "attrs": { "label": "Light Sensor" }
    }
  ],
  "connections": [
    [ "esp:TX0", "$serialMonitor:RX", "", [] ],
    [ "esp:RX0", "$serialMonitor:TX", "", [] ],
   
    [ "btn1:1.l", "esp:D14", "blue", [ "v0" ] ],
    [ "btn1:2.r", "esp:GND.1", "black", [ "v0" ] ],
   
    [ "pir1:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "pir1:GND", "esp:GND.1", "black", [ "v0" ] ],
    [ "pir1:OUT", "esp:D13", "orange", [ "v0" ] ],
   
    [ "red_led:A", "esp:D26", "red", [ "v0" ] ],
    [ "red_led:C", "r1:1", "red", [ "v0" ] ],
    [ "r1:2", "esp:GND.1", "black", [ "v0" ] ],
   
    [ "green_led:A", "esp:D27", "green", [ "v0" ] ],
    [ "green_led:C", "r2:1", "green", [ "v0" ] ],
    [ "r2:2", "esp:GND.1", "black", [ "v0" ] ],
   
    [ "blue_led:A", "esp:D12", "blue", [ "v0" ] ],
    [ "blue_led:C", "r3:1", "blue", [ "v0" ] ],
    [ "r3:2", "esp:GND.1", "black", [ "v0" ] ],
   
    [ "camera_led:A", "esp:D33", "yellow", [ "v0" ] ],
    [ "camera_led:C", "r4:1", "yellow", [ "v0" ] ],
    [ "r4:2", "esp:GND.2", "black", [ "v0" ] ],
   
    [ "lock_led:A", "esp:D32", "white", [ "v0" ] ],
    [ "lock_led:C", "r5:1", "white", [ "v0" ] ],
    [ "r5:2", "esp:GND.2", "black", [ "v0" ] ],
   
    [ "bz1:1", "esp:D25", "purple", [ "v0" ] ],
    [ "bz1:2", "esp:GND.2", "black", [ "v0" ] ],
   
    [ "oled1:VCC", "esp:3V3", "red", [ "h0" ] ],
    [ "oled1:GND", "esp:GND.2", "black", [ "h0" ] ],
    [ "oled1:SDA", "esp:D21", "blue", [ "h0" ] ],
    [ "oled1:SCL", "esp:D22", "yellow", [ "h0" ] ],
   
    [ "light1:GND", "esp:GND.2", "black", [ "v0" ] ],
    [ "light1:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "light1:SIG", "esp:D34", "green", [ "v0" ] ]
  ],
  "dependencies": {}
}

  • ESP32/ESP32-CAM
  • Push button
  • PIR Motion Sensor
  • Speaker & Microphone
  • Power supply

Applications

  • Home security
  • Visitor management
  • Package delivery alerts
  • Remote monitoring

Difficulty Level

Intermediate

 Amazing Features:

Triple Sensor Detection:

  •  DHT22 - Temperature monitoring (triggers at 35°C, 45°C, 55°C)
  •  MQ-2 Smoke Sensor - Gas/smoke detection (0-100%)
  •  Flame Sensor - Infrared flame detection
Code:
/*
 * ESP32 Smart Doorbell with Notifications
 *
 * Features:
 * - Doorbell button with debouncing
 * - PIR motion detection
 * - Camera simulation (visitor detection)
 * - Multi-tone doorbell chime
 * - OLED display with visitor info
 * - RGB LED status indicator
 * - Web dashboard for monitoring
 * - Real-time notifications (Email/SMS simulation)
 * - Visitor log with timestamps
 * - Remote door monitoring
 * - Night mode (motion-activated light)
 * - Two-way communication simulation
 */

#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// WiFi Credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";

// Web Server
WebServer server(80);

// Pin Definitions
#define DOORBELL_BUTTON_PIN 14   // Doorbell push button
#define PIR_SENSOR_PIN 13        // Motion sensor
#define BUZZER_PIN 25            // Doorbell chime
#define RED_LED_PIN 26           // RGB Red
#define GREEN_LED_PIN 27         // RGB Green
#define BLUE_LED_PIN 12          // RGB Blue
#define CAMERA_TRIGGER_PIN 33    // Camera simulation
#define RELAY_DOOR_PIN 32        // Door lock relay
#define LIGHT_SENSOR_PIN 34      // Light sensor (day/night)

// OLED Display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// System State
struct DoorbellState {
  int visitorCount;
  unsigned long lastRingTime;
  bool motionDetected;
  bool nightMode;
  bool doorbellPressed;
  String lastVisitorTime;
  int lightLevel;
  bool cameraActive;
  bool doorLocked;
};

DoorbellState doorbell;

// Visitor Log
struct VisitorLog {
  String timestamp;
  String event;        // "Ring", "Motion", "Camera"
  bool notificationSent;
};

VisitorLog visitorHistory[20];
int historyIndex = 0;

// Button debouncing
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int lastButtonState = HIGH;
int buttonState = HIGH;

// Timing
unsigned long lastMotionCheck = 0;
unsigned long lastDisplayUpdate = 0;
const long motionCheckInterval = 500;
const long displayUpdateInterval = 100;

// Doorbell melodies
const int melody1[] = {523, 587, 659, 784};  // C, D, E, G
const int melody2[] = {784, 659, 523};       // G, E, C
const int noteDurations[] = {200, 200, 200, 400};

void setup() {
  Serial.begin(115200);
 
  // Initialize pins
  pinMode(DOORBELL_BUTTON_PIN, INPUT_PULLUP);
  pinMode(PIR_SENSOR_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);
  pinMode(CAMERA_TRIGGER_PIN, OUTPUT);
  pinMode(RELAY_DOOR_PIN, OUTPUT);
  pinMode(LIGHT_SENSOR_PIN, INPUT);
 
  // Initialize OLED
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED failed"));
  } else {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("SMART DOORBELL");
    display.println("");
    display.println("Initializing...");
    display.display();
    delay(2000);
  }
 
  // Initialize state
  doorbell.visitorCount = 0;
  doorbell.lastRingTime = 0;
  doorbell.motionDetected = false;
  doorbell.nightMode = false;
  doorbell.doorbellPressed = false;
  doorbell.lastVisitorTime = "None";
  doorbell.lightLevel = 0;
  doorbell.cameraActive = false;
  doorbell.doorLocked = true;
 
  // Initial door lock state
  digitalWrite(RELAY_DOOR_PIN, HIGH);
 
  // Connect to WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
 
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Connecting WiFi...");
  display.display();
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("\n✓ WiFi connected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
 
  // Setup web server routes
  server.on("/", handleRoot);
  server.on("/status", handleStatus);
  server.on("/history", handleHistory);
  server.on("/ring", handleTestRing);
  server.on("/unlock", handleUnlock);
  server.on("/lock", handleLock);
  server.on("/camera", handleCamera);
  server.on("/clear", handleClear);
 
  server.begin();
  Serial.println("✓ Web server started!");
 
  Serial.println("\n╔═══════════════════════════════════╗");
  Serial.println("║   SMART DOORBELL SYSTEM ONLINE   ║");
  Serial.println("╚═══════════════════════════════════╝");
  Serial.print("Dashboard: http://");
  Serial.println(WiFi.localIP());
  Serial.println();
 
  // Ready indicator
  setRGBColor(0, 255, 0); // Green
  playStartupChime();
  delay(500);
  setRGBColor(0, 0, 0); // Off
 
  updateDisplay();
}

void loop() {
  server.handleClient();
 
  unsigned long currentMillis = millis();
 
  // Check doorbell button
  checkDoorbellButton();
 
  // Check motion sensor
  if (currentMillis - lastMotionCheck >= motionCheckInterval) {
    lastMotionCheck = currentMillis;
    checkMotionSensor();
    checkLightLevel();
  }
 
  // Update display
  if (currentMillis - lastDisplayUpdate >= displayUpdateInterval) {
    lastDisplayUpdate = currentMillis;
    updateDisplay();
  }
}

void checkDoorbellButton() {
  int reading = digitalRead(DOORBELL_BUTTON_PIN);
 
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
     
      // Button pressed (LOW because of INPUT_PULLUP)
      if (buttonState == LOW) {
        handleDoorbellRing();
      }
    }
  }
 
  lastButtonState = reading;
}

void handleDoorbellRing() {
  doorbell.doorbellPressed = true;
  doorbell.visitorCount++;
  doorbell.lastRingTime = millis();
  doorbell.lastVisitorTime = getTimestamp();
 
  Serial.println("\n╔═══════════════════════════════════╗");
  Serial.println("║        ๐Ÿ”” DOORBELL RANG! ๐Ÿ””      ║");
  Serial.println("╚═══════════════════════════════════╝");
  Serial.print("Visitor #");
  Serial.println(doorbell.visitorCount);
  Serial.print("Time: ");
  Serial.println(doorbell.lastVisitorTime);
 
  // Log event
  logVisitor("Doorbell Ring");
 
  // Visual indicator
  setRGBColor(0, 0, 255); // Blue
 
  // Activate camera
  activateCamera();
 
  // Play doorbell chime
  playDoorbellChime();
 
  // Send notification
  sendNotification("DOORBELL", "Someone is at your door!");
 
  // Flash display
  flashDisplay("VISITOR AT DOOR!");
 
  delay(500);
  setRGBColor(0, 0, 0); // Off
 
  doorbell.doorbellPressed = false;
}

void checkMotionSensor() {
  bool motion = digitalRead(PIR_SENSOR_PIN);
 
  if (motion && !doorbell.motionDetected) {
    doorbell.motionDetected = true;
   
    Serial.println("๐Ÿ‘️ Motion detected at front door");
   
    // Log event
    logVisitor("Motion Detected");
   
    // Visual indicator
    setRGBColor(255, 255, 0); // Yellow
   
    // If night mode, turn on light
    if (doorbell.nightMode) {
      Serial.println("๐ŸŒ™ Night mode - Activating light");
      setRGBColor(255, 255, 255); // White (light)
    }
   
    // Activate camera for motion
    activateCamera();
   
    // Send motion notification
    sendNotification("MOTION", "Motion detected at front door");
   
    delay(1000);
    setRGBColor(0, 0, 0);
  } else if (!motion && doorbell.motionDetected) {
    doorbell.motionDetected = false;
  }
}

void checkLightLevel() {
  int lightRaw = analogRead(LIGHT_SENSOR_PIN);
  doorbell.lightLevel = map(lightRaw, 0, 4095, 0, 100);
 
  // Detect night (less than 30% light)
  if (doorbell.lightLevel < 30 && !doorbell.nightMode) {
    doorbell.nightMode = true;
    Serial.println("๐ŸŒ™ Night mode activated");
  } else if (doorbell.lightLevel >= 30 && doorbell.nightMode) {
    doorbell.nightMode = false;
    Serial.println("☀️ Day mode activated");
  }
}

void activateCamera() {
  doorbell.cameraActive = true;
  digitalWrite(CAMERA_TRIGGER_PIN, HIGH);
 
  Serial.println("๐Ÿ“ท Camera activated - Capturing image");
  Serial.println("๐Ÿ“ธ Image saved: visitor_" + String(doorbell.visitorCount) + ".jpg");
 
  delay(2000); // Simulate capture time
 
  digitalWrite(CAMERA_TRIGGER_PIN, LOW);
  doorbell.cameraActive = false;
}

void playDoorbellChime() {
  // Pleasant doorbell melody
  for (int i = 0; i < 4; i++) {
    tone(BUZZER_PIN, melody1[i], noteDurations[i]);
    delay(noteDurations[i] + 50);
  }
  noTone(BUZZER_PIN);
}

void playStartupChime() {
  tone(BUZZER_PIN, 1000, 100);
  delay(150);
  tone(BUZZER_PIN, 1500, 100);
}

void setRGBColor(int red, int green, int blue) {
  analogWrite(RED_LED_PIN, red);
  analogWrite(GREEN_LED_PIN, green);
  analogWrite(BLUE_LED_PIN, blue);
}

void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
 
  // Title
  display.println("SMART DOORBELL");
  display.drawLine(0, 9, 128, 9, SSD1306_WHITE);
 
  // Status
  display.setCursor(0, 12);
  display.print("Visitors: ");
  display.println(doorbell.visitorCount);
 
  display.setCursor(0, 22);
  display.print("Last: ");
  display.println(doorbell.lastVisitorTime);
 
  display.setCursor(0, 32);
  if (doorbell.motionDetected) {
    display.println("MOTION DETECTED!");
  } else {
    display.print("Motion: None");
  }
 
  display.setCursor(0, 42);
  display.print("Door: ");
  display.println(doorbell.doorLocked ? "LOCKED" : "UNLOCKED");
 
  display.setCursor(0, 52);
  if (doorbell.nightMode) {
    display.print("Night Mode");
  } else {
    display.print("Day Mode");
  }
 
  if (doorbell.cameraActive) {
    display.setCursor(80, 52);
    display.print("CAM ON");
  }
 
  display.display();
}

void flashDisplay(String message) {
  for (int i = 0; i < 3; i++) {
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println(message);
    display.display();
    delay(500);
   
    display.clearDisplay();
    display.display();
    delay(300);
  }
}

void sendNotification(String type, String message) {
  Serial.println("\n╔═══════════════════════════════════╗");
  Serial.println("║    ๐Ÿ“ฑ NOTIFICATION SENT ๐Ÿ“ฑ       ║");
  Serial.println("╠═══════════════════════════════════╣");
  Serial.print("║ Type: ");
  Serial.println(type);
  Serial.print("║ Message: ");
  Serial.println(message);
  Serial.println("║                                   ║");
  Serial.println("║ ✉️  Email: user@example.com      ║");
  Serial.println("║ ๐Ÿ“ฑ SMS: +1-234-567-8900          ║");
  Serial.println("║ ๐Ÿ”” Push: Mobile App              ║");
  Serial.println("╚═══════════════════════════════════╝\n");
}

void logVisitor(String event) {
  visitorHistory[historyIndex].timestamp = getTimestamp();
  visitorHistory[historyIndex].event = event;
  visitorHistory[historyIndex].notificationSent = true;
 
  historyIndex = (historyIndex + 1) % 20;
}

String getTimestamp() {
  unsigned long seconds = millis() / 1000;
  unsigned long minutes = seconds / 60;
  unsigned long hours = minutes / 60;
 
  seconds = seconds % 60;
  minutes = minutes % 60;
  hours = hours % 24;
 
  String timestamp = "";
  if (hours < 10) timestamp += "0";
  timestamp += String(hours) + ":";
  if (minutes < 10) timestamp += "0";
  timestamp += String(minutes) + ":";
  if (seconds < 10) timestamp += "0";
  timestamp += String(seconds);
 
  return timestamp;
}

// Web Server Handlers
void handleRoot() {
  String html = "<!DOCTYPE html><html><head>";
  html += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
  html += "<meta http-equiv='refresh' content='3'>";
  html += "<title>Smart Doorbell</title>";
  html += "<style>";
  html += "body{margin:0;font-family:Arial;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:20px}";
  html += ".container{max-width:1000px;margin:0 auto}";
  html += "h1{text-align:center;font-size:2.5em;margin-bottom:10px;text-shadow:2px 2px 4px rgba(0,0,0,0.3)}";
  html += ".subtitle{text-align:center;opacity:0.9;margin-bottom:30px}";
  html += ".stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px;margin-bottom:30px}";
  html += ".stat{background:rgba(255,255,255,0.2);padding:20px;border-radius:10px;text-align:center}";
  html += ".stat-value{font-size:2.5em;font-weight:bold}";
  html += ".stat-label{font-size:0.9em;opacity:0.8;margin-top:5px}";
  html += ".card{background:rgba(255,255,255,0.15);backdrop-filter:blur(10px);padding:25px;border-radius:15px;margin-bottom:20px;border:1px solid rgba(255,255,255,0.18)}";
  html += ".status-item{display:flex;justify-content:space-between;padding:10px;border-bottom:1px solid rgba(255,255,255,0.1)}";
  html += ".status-indicator{display:inline-block;width:15px;height:15px;border-radius:50%;margin-right:10px}";
  html += ".on{background:#4CAF50;box-shadow:0 0 10px #4CAF50}";
  html += ".off{background:#666}";
  html += ".btn{padding:15px 30px;border:none;border-radius:8px;cursor:pointer;font-size:1em;margin:5px;color:#fff;text-decoration:none;display:inline-block;font-weight:600}";
  html += ".btn-primary{background:#2196F3}";
  html += ".btn-success{background:#4CAF50}";
  html += ".btn-danger{background:#f44336}";
  html += ".btn-warning{background:#ff9800}";
  html += ".controls{text-align:center;margin-top:20px}";
  html += ".event-log{max-height:300px;overflow-y:auto;background:rgba(0,0,0,0.2);padding:15px;border-radius:10px}";
  html += ".event-item{padding:10px;border-left:3px solid #2196F3;margin-bottom:10px;background:rgba(255,255,255,0.1)}";
  html += ".camera-view{background:#000;height:200px;border-radius:10px;display:flex;align-items:center;justify-content:center;margin:20px 0;border:2px solid rgba(255,255,255,0.3)}";
  html += "</style></head><body>";
  html += "<div class='container'>";
 
  html += "<h1>๐Ÿ”” Smart Doorbell</h1>";
  html += "<div class='subtitle'>Remote Monitoring Dashboard</div>";
 
  // Stats
  html += "<div class='stats'>";
 
  html += "<div class='stat'>";
  html += "<div class='stat-value'>" + String(doorbell.visitorCount) + "</div>";
  html += "<div class='stat-label'>๐Ÿ‘ฅ Total Visitors</div>";
  html += "</div>";
 
  html += "<div class='stat'>";
  html += "<div class='stat-value'>" + doorbell.lastVisitorTime + "</div>";
  html += "<div class='stat-label'>๐Ÿ• Last Activity</div>";
  html += "</div>";
 
  html += "<div class='stat'>";
  html += "<div class='stat-value'>" + String(doorbell.lightLevel) + "%</div>";
  html += "<div class='stat-label'>๐Ÿ’ก Light Level</div>";
  html += "</div>";
 
  html += "</div>";
 
  // Camera View
  html += "<div class='card'>";
  html += "<h3>๐Ÿ“ท Camera View</h3>";
  html += "<div class='camera-view'>";
  if (doorbell.cameraActive) {
    html += "<div>๐Ÿ“น RECORDING...</div>";
  } else if (doorbell.motionDetected) {
    html += "<div>๐Ÿ‘️ MOTION DETECTED</div>";
  } else {
    html += "<div>No Activity</div>";
  }
  html += "</div>";
  html += "<button onclick=\"window.location='/camera'\" class='btn btn-primary'>๐Ÿ“ธ Capture Photo</button>";
  html += "</div>";
 
  // System Status
  html += "<div class='card'>";
  html += "<h3>⚙️ System Status</h3>";
 
  html += "<div class='status-item'>";
  html += "<span><span class='status-indicator " + String(doorbell.motionDetected ? "on" : "off") + "'></span>Motion Sensor</span>";
  html += "<span>" + String(doorbell.motionDetected ? "ACTIVE" : "Standby") + "</span>";
  html += "</div>";
 
  html += "<div class='status-item'>";
  html += "<span><span class='status-indicator " + String(doorbell.cameraActive ? "on" : "off") + "'></span>Camera</span>";
  html += "<span>" + String(doorbell.cameraActive ? "RECORDING" : "Ready") + "</span>";
  html += "</div>";
 
  html += "<div class='status-item'>";
  html += "<span><span class='status-indicator " + String(doorbell.doorLocked ? "on" : "off") + "'></span>Door Lock</span>";
  html += "<span>" + String(doorbell.doorLocked ? "๐Ÿ”’ LOCKED" : "๐Ÿ”“ UNLOCKED") + "</span>";
  html += "</div>";
 
  html += "<div class='status-item'>";
  html += "<span><span class='status-indicator " + String(doorbell.nightMode ? "on" : "off") + "'></span>Night Mode</span>";
  html += "<span>" + String(doorbell.nightMode ? "๐ŸŒ™ Active" : "☀️ Inactive") + "</span>";
  html += "</div>";
 
  html += "</div>";
 
  // Recent Events
  html += "<div class='card'>";
  html += "<h3>๐Ÿ“‹ Recent Events</h3>";
  html += "<div class='event-log'>";
 
  int count = 0;
  for (int i = historyIndex - 1; i >= 0 && count < 5; i--) {
    if (visitorHistory[i].timestamp != "") {
      html += "<div class='event-item'>";
      html += "<strong>" + visitorHistory[i].event + "</strong><br>";
      html += "Time: " + visitorHistory[i].timestamp;
      html += "</div>";
      count++;
    }
  }
 
  if (count == 0) {
    html += "<div style='text-align:center;opacity:0.5;padding:20px'>No recent events</div>";
  }
 
  html += "</div></div>";
 
  // Controls
  html += "<div class='controls'>";
  html += "<a href='/ring' class='btn btn-warning'>๐Ÿ”” Test Doorbell</a>";
  if (doorbell.doorLocked) {
    html += "<a href='/unlock' class='btn btn-success'>๐Ÿ”“ Unlock Door</a>";
  } else {
    html += "<a href='/lock' class='btn btn-danger'>๐Ÿ”’ Lock Door</a>";
  }
  html += "<a href='/clear' class='btn btn-primary'>๐Ÿ—‘️ Clear Log</a>";
  html += "</div>";
 
  html += "<div style='text-align:center;margin-top:30px;opacity:0.7;font-size:0.9em'>";
  html += "IP: " + WiFi.localIP().toString() + " | Uptime: " + String(millis()/1000) + "s";
  html += "</div>";
 
  html += "</div></body></html>";
 
  server.send(200, "text/html", html);
}

void handleStatus() {
  String json = "{";
  json += "\"visitors\":" + String(doorbell.visitorCount) + ",";
  json += "\"lastVisitor\":\"" + doorbell.lastVisitorTime + "\",";
  json += "\"motion\":" + String(doorbell.motionDetected ? "true" : "false") + ",";
  json += "\"camera\":" + String(doorbell.cameraActive ? "true" : "false") + ",";
  json += "\"doorLocked\":" + String(doorbell.doorLocked ? "true" : "false") + ",";
  json += "\"nightMode\":" + String(doorbell.nightMode ? "true" : "false") + ",";
  json += "\"lightLevel\":" + String(doorbell.lightLevel);
  json += "}";
 
  server.send(200, "application/json", json);
}

void handleHistory() {
  String json = "[";
  for (int i = 0; i < 20; i++) {
    if (visitorHistory[i].timestamp != "") {
      if (i > 0) json += ",";
      json += "{";
      json += "\"time\":\"" + visitorHistory[i].timestamp + "\",";
      json += "\"event\":\"" + visitorHistory[i].event + "\"";
      json += "}";
    }
  }
  json += "]";
 
  server.send(200, "application/json", json);
}

void handleTestRing() {
  Serial.println("๐Ÿงช Test doorbell activated from web");
  handleDoorbellRing();
 
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleUnlock() {
  doorbell.doorLocked = false;
  digitalWrite(RELAY_DOOR_PIN, LOW);
 
  Serial.println("๐Ÿ”“ Door unlocked remotely");
  logVisitor("Door Unlocked");
  sendNotification("DOOR", "Door unlocked remotely");
 
  setRGBColor(0, 255, 0); // Green
  tone(BUZZER_PIN, 1000, 200);
  delay(500);
  setRGBColor(0, 0, 0);
 
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleLock() {
  doorbell.doorLocked = true;
  digitalWrite(RELAY_DOOR_PIN, HIGH);
 
  Serial.println("๐Ÿ”’ Door locked remotely");
  logVisitor("Door Locked");
 
  setRGBColor(255, 0, 0); // Red
  tone(BUZZER_PIN, 800, 200);
  delay(500);
  setRGBColor(0, 0, 0);
 
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleCamera() {
  activateCamera();
  logVisitor("Camera Triggered");
 
  server.sendHeader("Location", "/");
  server.send(303);
}

void handleClear() {
  doorbell.visitorCount = 0;
  historyIndex = 0;
  for (int i = 0; i < 20; i++) {
    visitorHistory[i].timestamp = "";
    visitorHistory[i].event = "";
  }
 
  Serial.println("✓ Event log cleared");
 
  server.sendHeader("Location", "/");
  server.send(303);
}

4-Level Alert System:

SAFE → Green LED, No alarm

WARNING → Blue LED, No alarm
DANGER → Red LED + Medium beeps
CRITICAL → Red flashing + Fast beeps

Automatic Safety Response:

  •  Auto-Sprinkler - Activates at CRITICAL level
  •  Exhaust Fan - Turns on when smoke > 30%
  •  Smart Alarm - Different beep patterns per level
  •  Emergency Alerts - Simulated SMS/Email notifications

Beautiful Web Dashboard:

  •  Dark theme with color-coded alerts
  •  Progress bars for all sensors
  •  Auto-refresh every 2 seconds
  •  Mobile responsive design
  •  Remote controls (Test, Silence, Reset)


 How to Test:

Simulate a Fire:

  1. Start with Normal Conditions:
    • Green LED = SAFE
    • No alarm
    • All systems standby
  2. Increase Temperature:
    • Click DHT22, drag to 40°C
    • Blue LED lights up (WARNING)
    • Still no alarm
  3. Add Smoke:
    • Rotate "Smoke Sensor" to 60%
    • Red LED lights up (DANGER)
    •  Alarm starts beeping!
    •  Exhaust fan turns ON
  4. Detect Flames:
    • Rotate "Flame Sensor" to 50%
    •  Red LED flashes rapidly (CRITICAL)
    •  Alarm beeps continuously
    •  Sprinkler activates!
    •  Emergency alerts sent!

Comments