Eduard Codau
Published © GPL3+

Attendance system using Raspberry Pi 4 and RFID module

This project presents a monitor for attendance working with a RFID module which reads information encoded on a tag

BeginnerFull instructions provided3 hours2,656
Attendance system using Raspberry Pi 4 and RFID module

Things used in this project

Hardware components

Raspberry Pi 4 Model B
Raspberry Pi 4 Model B
×1
RFID reader (generic)
×1
I2C 16x4 LCD
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×1
Breadboard (generic)
Breadboard (generic)
×1
LED (generic)
LED (generic)
×2
Resistor 100 ohm
Resistor 100 ohm
×1
Male/Female Jumper Wires
Male/Female Jumper Wires
×13
Female/Female Jumper Wires
Female/Female Jumper Wires
×4

Software apps and online services

Python 3.7
Flask Web Server
Python modules: flask, json, time, RPi.GPIO, smbus, mfrc522, requests, email.mime.text, email.mime.multipart, datetime, threading, I2C_LCD_driver
Raspbian
Raspberry Pi Raspbian

Story

Read more

Schematics

Schematic

Code

read.py

Python
Reading the data written on the tag and performing the steps required for accessing the system
#!/usr/bin/env python

import RPi.GPIO as GPIO
import I2C_LCD_driver
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import threading
import requests
import json
from servo_driver import *
from mfrc522 import SimpleMFRC522
from datetime import datetime

GPIO.setmode(GPIO.BOARD)
reader = SimpleMFRC522()
lcd = I2C_LCD_driver.lcd()
servo = Servo_driver(7)

# for LEDs
GPIO.setup(11,GPIO.OUT)
GPIO.setup(13,GPIO.OUT)

# for email
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()

valid_entries = ["Cody"]

id = 0
text = ""
server_address = 'http://192.168.0.108:5000'
headers = {'Content-type': 'application/json', 'Accept':'text/plain'}

def send_email(content):

    server.login('lockdoor.monitoring@gmail.com','Aiwprton.1')
    server.sendmail('lockdoor.monitoring@gmail.com','eduard-alexandru.codau@student.tuiasi.ro',content.as_string())

def send_post_to_server(json_text):
    requests.post(server_address,data=json_text, headers=headers)
    
    
def display_waiting_text():
    global id
    global text
    while id == 0 and text == "":
        lcd.lcd_display_string("Waiting for card")
        lcd.lcd_clear()
        
        lcd.lcd_display_string("Waiting for card.")
        sleep(0.5)
        lcd.lcd_clear()
        
        lcd.lcd_display_string("Waiting for card..")
        sleep(0.5)
        lcd.lcd_clear()
        
        lcd.lcd_display_string("Waiting for card...")
        sleep(0.5)
        
def read():
    global id
    global text

    t = threading.Thread(target=display_waiting_text)
    t.start()
  
    id, text = reader.read()
    t.join()
    
    print(id)
    print(text)
    
    if str(text.split(" ")[0]) in valid_entries:
        GPIO.output(13, GPIO.HIGH)
        
        lcd.lcd_display_string("Acces granted: " + text,1)
        json_text = json.dumps({"name": str(text.split(" ")[0]), "time": str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S")), "status":"granted"})
        t1 = threading.Thread(target=send_post_to_server,args=(json_text,))
        t1.start()
        
        message = MIMEMultipart()
        message['From'] = 'lockdoor.monitoring@gmail.com'
        message['To'] = 'eduard-alexandru.codau@student.tuiasi.ro'
        message['Subject'] = 'Monitoring notification'
        email = "La data de " + str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S")) + " utilizatorul " + str(text.split(" ")[0]) + " a incercat sa acceseze sistemul. Rezultat: granted"
        message.attach(MIMEText(email,'plain'))
        
        t2 = threading.Thread(target=send_email,args=(message,))
        t2.start()
        
        servo.unlock()
        sleep(5)
        GPIO.output(13, GPIO.LOW)
        servo.lock()
    else:
        print(text)
        GPIO.output(11, GPIO.HIGH)
        lcd.lcd_display_string("Acces denied: " + text,1)
        json_text = json.dumps({"name": str(text.split(" ")[0]), "time": str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S")), "status":"denied"})
        t1 = threading.Thread(target=send_post_to_server, args=(json_text,))
        t1.start();
        
        message = MIMEMultipart()
        message['From'] = 'lockdoor.monitoring@gmail.com'
        message['To'] = 'eduard-alexandru.codau@student.tuiasi.ro'
        message['Subject'] = 'Monitoring notification'
        email = "La data de " + str(datetime.now().strftime("%d/%m/%Y, %H:%M:%S")) + " utilizatorul " + str(text.split(" ")[0]) + " a incercat sa acceseze sistemul. Rezultat: denied"
        message.attach(MIMEText(email,'plain'))
        
        t2 = threading.Thread(target=send_email,args=(message,))
        t2.start()
        sleep(3)
        GPIO.output(11, GPIO.LOW)

    id = 0
    text = ""

servo_driver.py

Python
Describes in an OOP manner the operations performed by the servo motor
import RPi.GPIO as GPIO
from time import sleep


class Servo_driver():
    def __init__(self, portNo):
        self.portNo = portNo;
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(self.portNo, GPIO.OUT)
        self.servoPWM = GPIO.PWM(self.portNo, 50)
        self.servoPWM.start(0)
        self.servoPWM.ChangeDutyCycle(2)


    def unlock(self):
        self.servoPWM.ChangeDutyCycle(5)
        sleep(0.5)
    
    def lock(self):
        self.servoPWM.ChangeDutyCycle(2) 
        sleep(0.5)

write.py

Python
This script is used to write data on a RFID tag
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522

reader = SimpleMFRC522()

try:
        text = input('New data:')
        print("Now place your tag to write")
        reader.write(text)
        print("Written")

finally:
        GPIO.cleanup()

main.py

Python
Represents the entry point in the application
import RPi.GPIO as GPIO
import threading
import read
GPIO.setmode(GPIO.BOARD)

while(True):
    try:
        read.read()
    finally:
        pass




				
				

app.py

Python
A simple python Flask server that renders a web page containing monitorization data in real time
import json

from flask import Flask, render_template, request
app = Flask(__name__)


@app.route('/', methods = ['POST', 'GET'])
def hello_world():
    if(request.method == 'GET'):
        with open("users.json",'r') as file:
            data = json.load(file)
            return render_template("index.html",content=data)

    elif(request.method == 'POST'):
        print(str(request.data,'utf-8'))
        json_data = json.loads(str(request.data,'utf-8'))
        print(json_data)
        with open("users.json",'r+') as file:
            data = json.load(file)
            data.append(json_data)
            file.seek(0)
            json.dump(data,file, sort_keys=True, indent='\t', separators=(',', ': '))
            return "JSON posted"

@app.route('/get-data', methods = ['GET'])
def get_data():
    with open("users.json", 'r+') as file:
        data = json.load(file)
        return json.dumps(data)


if __name__ == '__main__':
    app.run(host="192.168.0.108",port=5000)

index.html

HTML
This webpage can be used to present monitorization data collected from the users interacting with the system. It also executes asynchronous calls to the server for receiving a list of users to display.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home</title>
    <style>
        table {
            font-family: Arial, Helvetica, sans-serif;
            border-collapse: collapse;
            width: 50%;
            text-align:center;
        }
        td, th {
            border: 1px solid #ddd;
            padding: 8px;
        }
        th {
            padding-top: 12px;
            padding-bottom: 12px;
            text-align: center;
            background-color: #04AA6D;
            color: white;
         }

        tr:nth-child(even){
            background-color: #f2f2f2;
        }

        div.container {
            display: flex;
            justify-content: center;
        }
    </style>
</head>
<body>
    <h1 style="text-align:center">Lista cu utilizatorii care au incercat sa acceseze aplicatia in timp real</h1>
    <div class="container">
    <table>
        <thead>
        <tr>
            <th>Nume</th>
            <th>Status</th>
            <th>Data</th>
        </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    </div>

</body>
<script>
    setInterval(function(){
        var xhr = new XMLHttpRequest();
        xhr.open('GET','/get-data',true);

        xhr.onreadystatechange = () => {
            var new_body = document.createElement('tbody');
            data = JSON.parse(xhr.responseText);
            data.sort((a,b) => {
			if(parseInt(a.time) < parseInt(b.time))
			{
				return 1;
			}
			else
			{
				return -1;
			}
		});

            for(let i=0;i<data.length;i++)
            {
                var row = document.createElement('tr');
                var cell1 = document.createElement('td');
                cell1.innerHTML = data[i].name;
                row.appendChild(cell1);

                var cell2 = document.createElement('td');
                if(data[i].status == "denied")
                {
                    cell2.style.color = "red";
                }
                else
                {
                    cell2.style.color = "green";
                }
                cell2.innerHTML = data[i].status;
                row.appendChild(cell2);

                var cell3 = document.createElement('td');
                cell3.innerHTML = data[i].time;
                row.appendChild(cell3);

                new_body.appendChild(row);
            }

            old_table = document.getElementsByTagName('table')[0];
            old_body = document.getElementsByTagName('tbody')[0];
            old_table.replaceChild(new_body, old_body);
            console.log(data);
        }

        xhr.send();
    }, 1000);
</script>
</html>

Project files

Credits

Eduard Codau

Eduard Codau

1 project • 4 followers

Comments