Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:proiecte:2025sric:rfidscanner [2025/04/10 08:39]
robert_ionut.alexa
iothings:proiecte:2025sric:rfidscanner [2025/05/29 10:07] (current)
flaviu.ghena
Line 1: Line 1:
 ====== ESP32 RFID scanner ====== ====== ESP32 RFID scanner ======
 +Author: [[mailto:​ghena.flaviu@gmail.com|Ghena Flaviu]] \\
 +Master: SRIC
  
-AuthorFlaviu Ghena+===== Project Description ===== 
 + 
 +This project implements a secure RFID-based access control system using an ESP32-WROOM-32 microcontroller and an RC522 RFID reader. The system grants or denies access based on scanned RFID cards, with visual feedback provided by green (access granted) and red (access denied) LEDs. 
 + 
 +===== Concept ===== 
 + 
 +This project implements an IoT-based RFID access control system using an ESP32 microcontroller. It scans RFID cards, validates them against a predefined list, and provides visual feedback via LEDs. The system logs all access attempts to Firebase in real-time and sends Telegram notifications for unauthorized access. A web interface allows remote monitoring and manual control. 
 + 
 +Key features include: 
 +Real-time access logging to Firebase Realtime Database [1] 
 +Remote monitoring and control through a web interface 
 +Instant Telegram notifications for unauthorized access attempts [2] 
 +Manual access control via web interface buttons 
 +Time-synchronized logging with NTP server 
 + 
 +The system validates scanned cards against a predefined list of authorized cards, providing immediate LED feedback and updating the cloud database. Unauthorized access attempts trigger Telegram alerts to the system administrator. 
 + 
 +===== Hardware Description ===== 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu4.jpg?​600|}} 
 + 
 +**Parts List:** 
 +  * ESP32-WROOM-32:​ Main microcontroller for processing and connectivity. 
 +  * RFID-RC522 Module: Reads RFID card UIDs. 
 +  * Green LED: Indicates authorized access. 
 +  * Red LED: Indicates denied access. 
 +  * Resistors (2x): Current-limiting resistors for LEDs 
 +  * Breadboard/​Jumper Wires: For prototyping connections. 
 +  * Power Supply: 3.3V for ESP32 and RC522. 
 + 
 +**ESP32-WROOM-32:​** \\ 
 +- Connects to WiFi for cloud communication.\\ 
 +- Interfaces with the RC522 via SPI (GPIO 5, 18, 19, 23).\\ 
 +- Controls LEDs via GPIO 25 (green) and 26 (red).\\ 
 + 
 +**RFID-RC522:​** \\ 
 +- Communicates with ESP32 via SPI pins.\\ 
 +- Powered by 3.3V \\ 
 +- Antenna gain boosted for better sensitivity.\\ 
 + 
 +**LEDs:** \\ 
 +- Green LED: Activated for valid cards or manual "​grant"​ commands.\\ 
 +- Red LED: Activated for invalid cards or manual "​deny"​ commands.\\ 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu3.png?​600|}} 
 + 
 +===== Functionality Breakdown ===== 
 + 
 +**Key Components** 
 + 
 +**RFID Handling:​** 
 +- The MFRC522 library interfaces with the RFID reader\\ 
 +- Cards are identified by their UID and converted to decimal format\\ 
 +- Reader automatically resets after periods of inactivity\\ 
 + 
 +**Access Control Logic:** 
 +- Compares scanned card IDs against authorized list\\ 
 +- Provides immediate visual feedback via LEDs\\ 
 +- Green LED for authorized access, red for denied\\ 
 + 
 +**Firebase Integration:​** 
 +- Stores all access events with timestamps\\ 
 +- Allows remote control via the ledControl path\\ 
 +- Uses anonymous authentication for security\\ 
 + 
 +**Realtime Database rules** 
 +<​code>​ 
 +
 +  "​rules":​ { 
 +    "​rfidSystem":​ { 
 +      "​control":​ { 
 +        "​.read":​ true, 
 +        "​.write":​ true 
 +      }, 
 +      "​logs":​ { 
 +        "​.read":​ true, 
 +        "​.write":​ true 
 +      }, 
 +      "​ledControl":​ { 
 +        "​.read":​ true, 
 +        "​.write":​ true 
 +      } 
 +    } 
 +  } 
 +
 + 
 +</​code>​ 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu6.png?​300|}} 
 + 
 +**Telegram Notifications:​** 
 +- Sends instant alerts for all access attempts\\ 
 +- Differentiates between authorized and unauthorized access\\ 
 +- Includes system startup notification\\ 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu2.jpeg?​250|}} 
 + 
 + 
 +**Web Interface:​** 
 +- Provides real-time access logs display\\ 
 +- Allows manual access control via buttons\\ 
 +- Shows system connection status\\ 
 +- The system combines local hardware control with cloud connectivity for a comprehensive access control solution with remote monitoring capabilities.\\ 
 + 
 +**Error Handling:​** 
 +- Auto-resets RFID reader if inactive.\\ 
 +- Reconnects to WiFi/​Firebase if disconnected.\\ 
 + 
 +^ RC522 Pin  ^ ESP32 Pin  ^ 
 +| SDA       | GPIO 5     | 
 +| SCK       | GPIO 18    | 
 +| MOSI      | GPIO 23    | 
 +| MISO      | GPIO 19    | 
 +| IRQ       | Not connected | 
 +| GND       | GND        | 
 +| RST       | GPIO 22    | 
 +| 3.3V      | 3.3V       | 
 + 
 +^ LED Pin         ^ ESP32 Pin  ^ 
 +| GREEN LED PIN   | GPIO 25    | 
 +| RED LED PIN     | GPIO 26    | 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu1.png?​600|}} 
 + 
 + 
 + 
 + 
 +===== Code Breakdown ===== 
 + 
 +<​code>​ 
 +#include <​SPI.h>​ 
 +#include <​MFRC522.h>​ 
 +#include <​WiFi.h>​ 
 +#include <​WiFiClientSecure.h>​ 
 +#include <​HTTPClient.h>​ 
 +#include <​Firebase_ESP_Client.h>​ 
 +#include "​addons/​TokenHelper.h"​ 
 +#include "​addons/​RTDBHelper.h"​ 
 +#include <​time.h>​ 
 + 
 +// Configuration Section 
 +#define WIFI_SSID "​DIGI-x39P"​ 
 +#define WIFI_PASSWORD "​xxxx"​ 
 +#define API_KEY "​xxxx"​ 
 +#define DATABASE_URL "​https://​iotproiectflaviu-default-rtdb.europe-west1.firebasedatabase.app"​ 
 + 
 +// Telegram Bot Settings 
 +#define BOT_TOKEN "​7635387808:​AAGwtP_Y6fJ0LEhLbCuXkeLQb5a-0iDDQgs"​ 
 +#define CHAT_ID "​2124464812"​ 
 +const char* TELEGRAM_HOST = "​api.telegram.org";​ 
 + 
 +// Hardware Configuration 
 +#define RST_PIN 22 
 +#define SS_PIN 5 
 +#define GREEN_LED_PIN 25 
 +#define RED_LED_PIN 26 
 +#define READ_TIMEOUT 300 
 +#define LED_FEEDBACK_MS 1000 
 + 
 +// System Objects 
 +MFRC522 mfrc522(SS_PIN,​ RST_PIN); 
 +FirebaseData fbdo; 
 +FirebaseData ledControlStream;​ 
 +FirebaseAuth auth; 
 +FirebaseConfig config; 
 + 
 +// Database Paths 
 +String databasePath = "​rfidSystem";​ 
 +String logsPath = "/​logs";​ 
 +String ledControlPath = "/​ledControl";​ 
 + 
 +// Authorized Cards List 
 +const unsigned long validCards[] = {2318660736,​ 240163822};​ 
 +const int numValidCards = sizeof(validCards)/​sizeof(validCards[0]);​ 
 + 
 +// NTP Configuration 
 +const char* ntpServer = "​pool.ntp.org";​ 
 +const long gmtOffset_sec = 0; 
 +const int daylightOffset_sec = 0; 
 + 
 +// Function to send Telegram alerts 
 +void sendTelegramAlert(unsigned long cardID, bool isAuthorized) { 
 +  WiFiClientSecure client; 
 +  client.setInsecure();​ // Bypass SSL verification 
 +   
 +  HTTPClient https; 
 +  String url = "​https://"​ + String(TELEGRAM_HOST) + "/​bot"​ + String(BOT_TOKEN) + "/​sendMessage";​ 
 +   
 +  // Customize message based on access status 
 +  String message = isAuthorized ?  
 +    "✅ Authorized access: Card " + String(cardID) : 
 +    "🚨 Unauthorized access attempt: Card " + String(cardID);​ 
 +   
 +  String payload = "​chat_id="​ + String(CHAT_ID) + "&​text="​ + message; 
 + 
 +  if (https.begin(client,​ url)) { 
 +    https.addHeader("​Content-Type",​ "​application/​x-www-form-urlencoded"​);​ 
 +    int httpCode = https.POST(payload);​ 
 +    if (httpCode == HTTP_CODE_OK) { 
 +      Serial.println("​Telegram alert sent"​);​ 
 +    } else { 
 +      Serial.printf("​Telegram error: %d\n", httpCode);​ 
 +    } 
 +    https.end();​ 
 +  } else { 
 +    Serial.println("​Failed to connect to Telegram"​);​ 
 +  } 
 +
 + 
 +// Initialize WiFi connection 
 +void connectToWiFi() { 
 +  Serial.print("​Connecting to WiFi"​);​ 
 +  WiFi.begin(WIFI_SSID,​ WIFI_PASSWORD);​ 
 +   
 +  while (WiFi.status() != WL_CONNECTED) { 
 +    Serial.print('​.'​);​ 
 +    // Blink both LEDs while connecting 
 +    digitalWrite(GREEN_LED_PIN,​ !digitalRead(GREEN_LED_PIN));​ 
 +    digitalWrite(RED_LED_PIN,​ !digitalRead(RED_LED_PIN));​ 
 +    delay(300);​ 
 +  } 
 +   
 +  Serial.println("​\nConnected with IP: " + WiFi.localIP().toString());​ 
 +  // Quick green LED confirmation 
 +  digitalWrite(GREEN_LED_PIN,​ HIGH); 
 +  delay(500);​ 
 +  digitalWrite(GREEN_LED_PIN,​ LOW); 
 +  digitalWrite(RED_LED_PIN,​ LOW); 
 +
 + 
 +// Initialize time synchronization 
 +void initTime() { 
 +  configTime(gmtOffset_sec,​ daylightOffset_sec,​ ntpServer);​ 
 +  Serial.println("​Waiting for NTP time sync..."​);​ 
 +   
 +  time_t now; 
 +  while ((now = time(nullptr)) < 8 * 3600 * 2) { 
 +    Serial.print("​."​);​ 
 +    delay(500);​ 
 +  } 
 +   
 +  Serial.println("​\nCurrent time: " + String(ctime(&​now)));​ 
 +
 + 
 +// Initialize Firebase connection 
 +void initFirebase() { 
 +  config.api_key = API_KEY; 
 +  config.database_url = DATABASE_URL;​ 
 +  config.token_status_callback = tokenStatusCallback;​ 
 +   
 +  Firebase.reconnectWiFi(true);​ 
 +  fbdo.setResponseSize(4096);​ 
 +   
 +  // Anonymous authentication 
 +  if (Firebase.signUp(&​config,​ &auth, "",​ ""​)) { 
 +    Serial.println("​Anonymous signup successful"​);​ 
 +  } else { 
 +    Serial.println("​Signup error: " + fbdo.errorReason());​ 
 +  } 
 +   
 +  Firebase.begin(&​config,​ &​auth);​ 
 +   
 +  // Wait for Firebase connection 
 +  unsigned long startTime = millis(); 
 +  while (!Firebase.ready() && millis() - startTime < 15000) { 
 +    Serial.print("​."​);​ 
 +    delay(300);​ 
 +  } 
 +   
 +  if (Firebase.ready()) { 
 +    Serial.println("​Firebase connected!"​);​ 
 +    // Start listening for LED control commands 
 +    if (!Firebase.RTDB.beginStream(&​ledControlStream,​ (databasePath + ledControlPath).c_str())) { 
 +      Serial.println("​Stream begin error: " + ledControlStream.errorReason());​ 
 +    } 
 +  } else { 
 +    Serial.println("​Failed to connect to Firebase"​);​ 
 +    // Blink red LED indefinitely on failure 
 +    while(1) { 
 +      digitalWrite(RED_LED_PIN,​ HIGH); 
 +      delay(500);​ 
 +      digitalWrite(RED_LED_PIN,​ LOW); 
 +      delay(500);​ 
 +    } 
 +  } 
 +
 + 
 +// Handle LED control commands from Firebase 
 +void handleLEDControl() { 
 +  if (Firebase.RTDB.readStream(&​ledControlStream)) { 
 +    if (ledControlStream.streamAvailable()) { 
 +      FirebaseJsonData jsonData; 
 +      FirebaseJson *json = ledControlStream.jsonObjectPtr();​ 
 +       
 +      if (json->​get(jsonData,​ "​command"​)) { 
 +        String command = jsonData.stringValue;​ 
 +        Serial.println("​Received LED command: " + command); 
 +         
 +        if (command == "​grant"​) { 
 +          digitalWrite(GREEN_LED_PIN,​ HIGH); 
 +          digitalWrite(RED_LED_PIN,​ LOW); 
 +          delay(LED_FEEDBACK_MS);​ 
 +          digitalWrite(GREEN_LED_PIN,​ LOW); 
 +          sendToFirebase(0,​ true, true); // Manual grant 
 +          sendTelegramAlert(0,​ true); ​   // Notify manual grant 
 +        } else if (command == "​deny"​) { 
 +          digitalWrite(RED_LED_PIN,​ HIGH); 
 +          digitalWrite(GREEN_LED_PIN,​ LOW); 
 +          delay(LED_FEEDBACK_MS);​ 
 +          digitalWrite(RED_LED_PIN,​ LOW); 
 +          sendToFirebase(0,​ false, true); // Manual deny 
 +          sendTelegramAlert(0,​ false); ​   // Notify manual deny 
 +        } 
 +      } 
 +    } 
 +  } 
 +
 + 
 +// Send access event to Firebase 
 +void sendToFirebase(unsigned long cardID, bool accessGranted,​ bool isManual) { 
 +  if (Firebase.ready()) { 
 +    time_t now; 
 +    time(&​now);​ 
 +     
 +    String path = databasePath + logsPath + "/"​ + String(now);​ 
 +    FirebaseJson json; 
 +     
 +    // Prepare JSON data 
 +    json.set("​card_id",​ String(cardID));​ 
 +    json.set("​timestamp",​ now); 
 +    json.set("​access_granted",​ accessGranted);​ 
 +    json.set("​is_manual",​ isManual);​ 
 +     
 +    if (Firebase.RTDB.setJSON(&​fbdo,​ path.c_str(),​ &json)) { 
 +      Serial.println("​Data sent to Firebase"​);​ 
 +    } else { 
 +      Serial.println("​Firebase error: " + fbdo.errorReason());​ 
 +    } 
 +  } 
 +
 + 
 +// Check if card is authorized 
 +bool isCardValid(unsigned long cardID) { 
 +  for (int i = 0; i < numValidCards;​ i++) { 
 +    if (cardID == validCards[i]) return true; 
 +  } 
 +  return false; 
 +
 + 
 +// Reset RFID reader 
 +void resetReader() { 
 +  mfrc522.PCD_Reset();​ 
 +  mfrc522.PCD_Init();​ 
 +  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_48dB);​ // Increase sensitivity 
 +  Serial.println("​Reader was reset"​);​ 
 +
 + 
 +// Setup function - runs once at startup 
 +void setup() { 
 +  Serial.begin(115200);​ 
 +   
 +  // Initialize hardware 
 +  pinMode(GREEN_LED_PIN,​ OUTPUT); 
 +  pinMode(RED_LED_PIN,​ OUTPUT); 
 +  digitalWrite(GREEN_LED_PIN,​ LOW); 
 +  digitalWrite(RED_LED_PIN,​ LOW); 
 +   
 +  SPI.begin();​ 
 +  resetReader();​ // Initialize RFID reader 
 +   
 +  // Connect to services 
 +  connectToWiFi();​ 
 +  initTime();​ 
 +  initFirebase();​ 
 +   
 +  // Send startup notification 
 +  sendTelegramAlert(0,​ true); // System startup notification 
 +  Serial.println("​System ready"​);​ 
 +
 + 
 +// Main program loop 
 +void loop() { 
 +  static bool readerEnabled = true; 
 +  static unsigned long lastReadTime = 0; 
 +   
 +  // Handle incoming Firebase commands 
 +  handleLEDControl();​ 
 +   
 +  // Reset reader if inactive for too long 
 +  if (millis() - lastReadTime > 3000 && readerEnabled) { 
 +    readerEnabled = false; 
 +    resetReader();​ 
 +    lastReadTime = millis(); 
 +    readerEnabled = true; 
 +  } 
 +   
 +  // Skip if not time to read yet or reader disabled 
 +  if (millis() - lastReadTime < READ_TIMEOUT || !readerEnabled) return; 
 +   
 +  // Check for new card 
 +  if (!mfrc522.PICC_IsNewCardPresent()) return; 
 +  if (!mfrc522.PICC_ReadCardSerial()) { 
 +    Serial.println("​Failed to read card"​);​ 
 +    return; 
 +  } 
 +   
 +  lastReadTime = millis(); 
 +  readerEnabled = false; 
 +   
 +  // Read card ID 
 +  unsigned long cardID = 0; 
 +  Serial.print("​Card UID:"​);​ 
 +   
 +  for (byte i = 0; i < mfrc522.uid.size;​ i++) { 
 +    cardID = (cardID << 8) | mfrc522.uid.uidByte[i];​ 
 +    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "); 
 +    Serial.print(mfrc522.uid.uidByte[i],​ HEX); 
 +  } 
 +   
 +  Serial.print("​ | Decimal: "); 
 +  Serial.println(cardID);​ 
 +   
 +  // Check access and provide feedback 
 +  bool accessGranted = isCardValid(cardID);​ 
 +  digitalWrite(GREEN_LED_PIN,​ accessGranted ? HIGH : LOW); 
 +  digitalWrite(RED_LED_PIN,​ accessGranted ? LOW : HIGH); 
 +   
 +  // Log event and send notifications 
 +  sendToFirebase(cardID,​ accessGranted,​ false); 
 +  sendTelegramAlert(cardID,​ accessGranted);​ 
 +   
 +  // LED feedback duration 
 +  delay(LED_FEEDBACK_MS);​ 
 +  digitalWrite(GREEN_LED_PIN,​ LOW); 
 +  digitalWrite(RED_LED_PIN,​ LOW); 
 +   
 +  // Clean up RFID communication 
 +  mfrc522.PICC_HaltA();​ 
 +  mfrc522.PCD_StopCrypto1();​ 
 +  readerEnabled = true; 
 +
 +</​code>​ 
 + 
 + 
 +===== Webpage ===== 
 + 
 +{{:​iothings:​proiecte:​2025sric:​flaviu5.png?​600|}} 
 + 
 +<​code>​ 
 +<​!DOCTYPE html> 
 +<​html>​ 
 +<​head>​ 
 +  <​title>​RFID Access Control</​title>​ 
 +  <meta name="​viewport"​ content="​width=device-width,​ initial-scale=1">​ 
 +  <script src="​https://​www.gstatic.com/​firebasejs/​8.10.0/​firebase-app.js"></​script>​ 
 +  <script src="​https://​www.gstatic.com/​firebasejs/​8.10.0/​firebase-auth.js"></​script>​ 
 +  <script src="​https://​www.gstatic.com/​firebasejs/​8.10.0/​firebase-database.js"></​script>​ 
 +  <​style>​ 
 +    body { font-family:​ Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } 
 +    .card { background: #f9f9f9; border-radius:​ 8px; padding: 20px; margin-bottom:​ 20px; box-shadow: 0 2px 4px rgba(0,​0,​0,​0.1);​ } 
 +    button { padding: 10px 15px; margin: 5px; border: none; border-radius:​ 4px; cursor: pointer; } 
 +    .grant-btn { background-color:​ #4CAF50; color: white; } 
 +    .deny-btn { background-color:​ #f44336; color: white; } 
 +    table { width: 100%; border-collapse:​ collapse; margin-top: 20px; } 
 +    th, td { padding: 12px; text-align: left; border-bottom:​ 1px solid #ddd; } 
 +    .access-granted { color: #4CAF50; } 
 +    .access-denied { color: #f44336; } 
 +    .manual-access { font-style: italic; } 
 +  </​style>​ 
 +</​head>​ 
 +<​body>​ 
 +  <div class="​card">​ 
 +    <​h1>​RFID Access Control System</​h1>​ 
 +    <div id="​authStatus"></​div>​ 
 +    <​div>​ 
 +      <​h2>​Manual Control</​h2>​ 
 +      <button id="​grantBtn"​ class="​grant-btn">​Grant Access</​button>​ 
 +      <button id="​denyBtn"​ class="​deny-btn">​Deny Access</​button>​ 
 +    </​div>​ 
 +  </​div>​ 
 + 
 +  <div class="​card">​ 
 +    <​h2>​Access Logs</​h2>​ 
 +    <div id="​connectionStatus"></​div>​ 
 +    <​table>​ 
 +      <​thead>​ 
 +        <​tr>​ 
 +          <​th>​Timestamp</​th>​ 
 +          <​th>​Card ID</​th>​ 
 +          <​th>​Access</​th>​ 
 +        </​tr>​ 
 +      </​thead>​ 
 +      <tbody id="​logsBody"></​tbody>​ 
 +    </​table>​ 
 +  </​div>​ 
 + 
 +  <​script>​ 
 +    const firebaseConfig = { 
 +      apiKey: "​AIzaSyAK0KP-a7qqbuoqp-qyPt1e-8xuktIrHVo",​ 
 +      authDomain: "​iotproiectflaviu.firebaseapp.com",​ 
 +      databaseURL:​ "​https://​iotproiectflaviu-default-rtdb.europe-west1.firebasedatabase.app"​ 
 +    }; 
 + 
 +    firebase.initializeApp(firebaseConfig);​ 
 +    const database = firebase.database();​ 
 +    const ledControlRef = database.ref('​rfidSystem/​ledControl'​);​ 
 +    const logsRef = database.ref('​rfidSystem/​logs'​);​ 
 + 
 +    // Auth state 
 +    firebase.auth().signInAnonymously() 
 +      .then(() => { 
 +        document.getElementById('​authStatus'​).textContent = "​Authenticated";​ 
 +      }) 
 +      .catch(error => { 
 +        document.getElementById('​authStatus'​).innerHTML =  
 +          `<span style="​color:​red">​Auth error: ${error.message}</​span>​`;​ 
 +      }); 
 + 
 +    // Connection state 
 +    database.ref('​.info/​connected'​).on('​value',​ (snapshot) => { 
 +      const isConnected = snapshot.val();​ 
 +      document.getElementById('​connectionStatus'​).innerHTML = isConnected ?  
 +        '<​span style="​color:​green">​Connected to Firebase</​span>'​ :  
 +        '<​span style="​color:​red">​Disconnected</​span>';​ 
 +    }); 
 + 
 +    // Button handlers 
 +    document.getElementById('​grantBtn'​).addEventListener('​click',​ () => { 
 +      ledControlRef.set({ command: "​grant",​ timestamp: Date.now() }) 
 +        .then(() => console.log("​Grant command sent"​)) 
 +        .catch(error => console.error("​Error:",​ error)); 
 +    }); 
 + 
 +    document.getElementById('​denyBtn'​).addEventListener('​click',​ () => { 
 +      ledControlRef.set({ command: "​deny",​ timestamp: Date.now() }) 
 +        .then(() => console.log("​Deny command sent"​)) 
 +        .catch(error => console.error("​Error:",​ error)); 
 +    }); 
 + 
 +    // Logs display 
 +    logsRef.limitToLast(20).on('​value',​ (snapshot) => { 
 +      const logsBody = document.getElementById('​logsBody'​);​ 
 +      logsBody.innerHTML = '';​ 
 +       
 +      if (!snapshot.exists()) { 
 +        logsBody.innerHTML = '<​tr><​td colspan="​3">​No logs found</​td></​tr>';​ 
 +        return; 
 +      } 
 + 
 +      const logs = []; 
 +      snapshot.forEach(child => { 
 +        logs.push({ 
 +          key: child.key,​ 
 +          ...child.val() 
 +        }); 
 +      }); 
 + 
 +      logs.sort((a,​ b) => b.timestamp - a.timestamp);​ 
 +       
 +      logs.forEach(log => { 
 +        const row = document.createElement('​tr'​);​ 
 +        if (log.is_manual) row.classList.add('​manual-access'​);​ 
 +         
 +        const timeCell = document.createElement('​td'​);​ 
 +        timeCell.textContent = new Date(log.timestamp * 1000).toLocaleString();​ 
 +        row.appendChild(timeCell);​ 
 +         
 +        const idCell = document.createElement('​td'​);​ 
 +        idCell.textContent = log.card_id === "​0"​ ? "​MANUAL"​ : log.card_id;​ 
 +        row.appendChild(idCell);​ 
 +         
 +        const accessCell = document.createElement('​td'​);​ 
 +        accessCell.textContent = log.access_granted ? '​Granted'​ : '​Denied';​ 
 +        accessCell.className = log.access_granted ? '​access-granted'​ : '​access-denied';​ 
 +        row.appendChild(accessCell);​ 
 +         
 +        logsBody.appendChild(row);​ 
 +      }); 
 +    }); 
 +  </​script>​ 
 +</​body>​ 
 +</​html>​ 
 +</​code>​ 
 + 
 +===== Libraries ===== 
 + 
 +  * SPI.h: Enables SPI communication for the RC522. 
 +  * MFRC522.h: Interfaces with the RFID reader. 
 +  * WiFi.h: Manages WiFi connectivity. 
 +  * Firebase_ESP_Client.h:​ Handles Firebase Realtime Database operations. 
 +  * WiFiClientSecure.h/​HTTPClient.h:​ Sends Telegram alerts via HTTPS. 
 +  * time.h: Syncs time via NTP for accurate timestamps. 
 + 
 + 
 +===== Conclusions ===== 
 +This project demonstrates a scalable IoT access control system combining hardware (ESP32, RFID, LEDs) with cloud services (Firebase, Telegram). Key achievements:​ 
 +- Security: Real-time validation and alerts for unauthorized access. 
 +- Remote Monitoring: Web interface and Telegram notifications. 
 +- Reliability:​ Auto-reset functions and error handling. 
 +- Future enhancements could include adding biometric verification or integrating with physical locks. 
 + 
 +===== Demo ===== 
 + 
 +<​html><​iframe width="​456"​ height="​811"​ src="​https://​www.youtube.com/​embed/​BdYKw6g49gY"​ title="​RFID22"​ frameborder="​0"​ allow="​accelerometer;​ autoplay; clipboard-write;​ encrypted-media;​ gyroscope; picture-in-picture;​ web-share"​ allowfullscreen></​iframe></​html>​ 
 + 
 +<​html><​iframe width="​456"​ height="​811"​ src="​https://​www.youtube.com/​embed/​UwR_TnAOcD8"​ title="​RFID11"​ frameborder="​0"​ allow="​accelerometer;​ autoplay; clipboard-write;​ encrypted-media;​ gyroscope; picture-in-picture;​ web-share"​ allowfullscreen></​iframe></​html>​ 
 + 
 +===== References ===== 
 +[1] https://​randomnerdtutorials.com/​control-esp-gpios-firebase-web-app/​ \\ 
 +[2] https://​randomnerdtutorials.com/​esp32-door-status-telegram/​
iothings/proiecte/2025sric/rfidscanner.1744263549.txt.gz · Last modified: 2025/04/10 08:39 by robert_ionut.alexa
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0