Skip to content
This repository was archived by the owner on Aug 28, 2026. It is now read-only.
 
 

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BLE Attendance Clicker

A Bluetooth Low Energy attendance system for classrooms. Clicker devices (currently in our prototype: authorized Raspberry Pi Picos) broadcast a signed beacon; a scanner on the host machine verifies it and writes daily check-in records that a local web dashboard reads.

How it works

Each Pico is flashed with a student ID and a shared secret salt. On boot it broadcasts a BLE manufacturer advertisement containing the student ID and a 2-byte SHA-256 HMAC derived from student_id + SECRET_SALT. The scanner verifies the hash — if it matches, the student is checked in. The secret never goes over the air.

Pico  →  [student_id | sha256(id+salt)[:2]]  →  BLE advert
Scanner  →  recompute hash  →  match?  →  write attendance/YYYY-MM-DD.json
Browser  →  GET /api/today  →  dashboard

Requirements

Python 3.9+

bleak==3.0.1
# macOS only — remove or comment out on Linux:
# pyobjc-core==12.1
# pyobjc-framework-Cocoa==12.1
# pyobjc-framework-CoreBluetooth==12.1
# pyobjc-framework-libdispatch==12.1

Linux only — ensure bluez is installed and running:

sudo apt install bluetooth bluez
sudo systemctl enable --now bluetooth

Setup

git clone <repo>
cd <repo>
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

Edit the config block at the top of scanner.py to match your Pico's firmware:

MY_UUID      = "797CDF70-..."   # must match the Pico
SECRET_SALT  = "Networks"       # must match the Pico
COMPANY_ID   = 0xFFFF

Running

# Terminal 1 — BLE scanner (needs Bluetooth access)
python scanner.py

# Terminal 2 — web dashboard
python attendance_server.py
# → http://localhost:8080

Both scripts must run from the same directory. The scanner writes to attendance/ and the server reads from it.

File structure

.
├── scanner.py             # BLE scanner + attendance writer
├── attendance_server.py   # HTTP server (stdlib, no extra deps)
├── index.html             # Web dashboard (served at /)
├── requirements.txt
└── attendance/
    ├── 2025-01-20.json
    └── 2025-01-21.json

Each attendance file looks like:

{
  "date": "2025-01-21",
  "checkins": {
    "42": { "time": "09:03:11", "rssi": -67 },
    "7":  { "time": "09:05:44", "rssi": -72 }
  }
}

API

Endpoint Description
GET /api/today Today's check-ins
GET /api/date/YYYY-MM-DD A specific day's check-ins
GET /api/dates All days that have records

Security notes

  • The 2-byte hash truncation means 65,536 possible values — sufficient for a closed classroom, not for production.
  • There is no replay protection. A sniffed packet can be rebroadcast. Add a rolling counter or timestamp to the payload if this matters.
  • Anyone with scanner.py has the secret salt. Treat the source as sensitive.

About

Code for attendance clicker system

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages