Secure, Real-Time Biometric Attendance Tracking with Encrypted Data Upload to Firebase for Educational Settings
Category: IoT, Embedded Systems, Biometric Systems, Secure Data Management
Tools & Technologies: ESP32 Development Board, AS608 Fingerprint Sensor, LiquidCrystal_I2C LCD
(16x2), Push Buttons, LEDs, Buzzer, Veroboard, Jumper Wires, Resistors, Firebase Realtime Database,
Arduino IDE, Python, Pyrebase4, Pycryptodome, Pandas, Tabulate, Openpyxl, AES Encryption, NTP
Server, WiFi Module (ESP32), EEPROM
Status: Completed
Addressing the inefficiencies of manual attendance systems in educational institutions, this project delivers an IoT-based fingerprint attendance system using the ESP32 microcontroller and AS608 fingerprint sensor. Integrated with Firebase Realtime Database, it ensures secure, real-time attendance tracking with AES-encrypted data uploads. A 16x2 LCD, push buttons, LEDs, and a buzzer provide an intuitive user interface, while WiFi connectivity enables cloud synchronization. The system supports fingerprint enrollment, deletion, and attendance marking (sign-in/sign-out) for up to 127 users, with data persisted in EEPROM. A Python script processes encrypted attendance records, generating CSV, HTML, and Excel reports. This solution enhances accuracy, security, and efficiency in attendance management, transitioning from paper-based methods to a robust biometric system. The project also aligns with secure real-time biometric data upload principles, emphasizing data integrity and privacy.
Aim:
To design and implement an IoT-based fingerprint attendance system
for educational institutions, enabling secure, real-time biometric data collection and
management.
Objectives:
The objectives of the project are outlined below:
// Excerpt from main.ino
void markAttendance(int fingerprintID) {
id = fingerprintID;
classNum = 0;
lcd.clear();
lcd.print("Enter Class 0-9:");
lcd.setCursor(0, 1);
lcd.print(classNum);
bool classSelected = false;
while (!classSelected) {
if (digitalRead(forward) == 0) {
digitalWrite(buzzer, HIGH);
delay(100);
digitalWrite(buzzer, LOW);
classNum++;
if (classNum > 9) classNum = 0;
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(classNum);
delay(150);
} else if (digitalRead(ok) == 0) {
digitalWrite(buzzer, HIGH);
delay(100);
digitalWrite(buzzer, LOW);
classSelected = true;
delay(150);
}
}
if (WiFi.status() == WL_CONNECTED && !fullDateTime.startsWith("0000")) {
reconnectWiFi();
String className = "EIE52" + String(classNum);
userState[id] = std::make_tuple(true, className, currentTime);
String matricNo = getMatricNo(id);
String encrypted = encryptData(id, matricNo, className, currentDate, 1, currentTime, "");
String path = "/attendance_records/" + className + "/" + currentDate + "/id_" + String(id);
if (Firebase.ready()) {
bool success = Firebase.setString(fbdo, path, encrypted);
Serial.printf("Sending Attendance Data... %s\n", success ? "Success" : fbdo.errorReason().c_str());
}
}
}
# Excerpt from process_attendance_decryption.py
def decrypt_data(encrypted_b64, class_name, date, identifier):
try:
encrypted_data = base64.b64decode(encrypted_b64)
cipher = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
padded_data = cipher.decrypt(encrypted_data)
plaintext = unpad(padded_data, AES.block_size)
json_data = json.loads(plaintext.decode('utf-8'))
print(f"Decrypted data for {class_name}/{date}/{identifier}: {json_data}")
return json_data
except Exception as e:
print(f"Decryption error for {class_name}/{date}/{identifier}: {e}")
return None
def fetch_and_process_attendance():
attendance_records = db.child("attendance_records").get().val()
for class_name in attendance_records:
class_data = attendance_records[class_name]
for date in class_data:
date_data = class_data[date]
csv_data = []
if isinstance(date_data, dict):
for id_key, record in date_data.items():
if id_key.startswith("id_"):
id_num = id_key.replace("id_", "")
else:
id_num = id_key
if isinstance(record, str):
encrypted_b64 = record
decrypted = decrypt_data(encrypted_b64, class_name, date, id_key)
if decrypted:
csv_data.append({
"id": decrypted["id"],
"matric_number": decrypted["matric_number"],
"course": decrypted["course"],
"date": decrypted["date"],
"present": decrypted["present"],
"present_time": decrypted["present_time"],
"absent_time": decrypted["absent_time"] if decrypted["absent_time"] else ""
})
if csv_data:
df = pd.DataFrame(csv_data)
output_dir = f"attendance/{class_name}"
os.makedirs(output_dir, exist_ok=True);
csv_path = f"{output_dir}/{date}.csv"
df.to_csv(csv_path, index=False)
print(f"Generated CSV: {csv_path}")
The following is the pinout diagram for the ESP32 Development Board used in this project, along with the GPIO pins utilized.
Pinout Diagram:GPIO Pin | Component | Description |
---|---|---|
GPIO 15 | WiFi LED | Indicates WiFi connectivity status. |
GPIO 2 | Validate LED | Signals successful fingerprint recognition. |
GPIO 4 | Enroll LED | Indicates enrollment mode activation. |
GPIO 32 | Buzzer | Provides audible feedback for operations. |
GPIO 13 | Register Button | Initiates fingerprint enrollment. |
GPIO 27 | Back Button | Navigates back in menu. |
GPIO 25 | Delete Button | Initiates fingerprint deletion. |
GPIO 14 | OK Button | Confirms selections. |
GPIO 12 | Forward Button | Increments ID/class selection. |
GPIO 26 | Reverse Button | Decrements ID/class selection. |
GPIO 16 (RXD2) | Fingerprint Sensor RX | Receives data from AS608 sensor. |
GPIO 17 (TXD2) | Fingerprint Sensor TX | Transmits data to AS608 sensor. |
GPIO 21 (SDA) | LCD I2C SDA | Serial data for LCD. |
GPIO 22 (SCL) | LCD I2C SCL | Serial clock for LCD. |
This pin configuration optimizes ESP32’s capabilities for real-time biometric operations.
Components Used: ESP32 Development Board, AS608 Fingerprint Sensor, LiquidCrystal_I2C, Push Buttons, LEDs, Buzzer, Veroboard, Jumper Wires, Resistors.
Functions of the Components Used:
Hardware Assembly
Casing Fabrication
Batteries, Veroboard, Charging Module, and ESP32 Development Board
Veroboard Soldered, Buzzer, DIL Connector, LEDs, LCD1602, Push Buttons, and Internal
Circuitry containing AS608 Fingerprint Sensor, and Switch
Front View of the Hardware Development (Complete Assembly)
Firebase Database Structure
/attendance_records/
/EIE520/
/2025-05-01/
id_001: "base64_encrypted_data"
id_002: "base64_encrypted_data"
/2025-05-02/
id_001: "base64_encrypted_data"
/EIE521/
/2025-05-01/
id_003: "base64_encrypted_data"
/registered_student_records/
/1/
fingerprint_id: 1
matric_number: "17CK022738"
timestamp: "2025-05-25 10:00:00"
/2/
fingerprint_id: 2
matric_number: "17CK022739"
timestamp: "2025-05-25 10:07:43"
Pictorial Results
Startup Display
WiFi Connecting
Fingerprint Scan Prompt to Mark Attendance
Attendance Marked
Enrollment Interface
Enrollment Interface
Enrollment Interface
Excel Report Sample
HTML Report Sample
Firebase Data View
Firebase Data View (registered students)
Firebase Data View (registered students)
Firebase Data View (attendance records)
Firebase Data View (attendance records)
My Design and Myself
Happy Me, and the Device I Built 🥳
I sincerely appreciate you taking the time to explore my portfolio and learn about my work and expertise. It is my hope that these projects and insights have demonstrated my passion for innovation, my technical skills, and my dedication to delivering impactful solutions.
If you have any questions, require further information, or wish to discuss potential collaborations, I would be delighted to connect. Please feel free to reach out via the Contact section. Your feedback and inquiries are highly valued and will be addressed promptly.
Thank you once again for your interest in my work. I look forward to the opportunity to collaborate and contribute meaningfully to your projects or organization. Together, let us innovate and achieve excellence.
Best regards,
Damilare Lekan Adekeye