[02] 2026
Pointage ZKTeco
Attendance from a real time clock, live in a dashboard
The problem
The team clocks in on a ZKTeco K40 Pro, and the punches stayed inside the device. Nobody could see who was in today, monthly sheets were rebuilt by hand, and leave requests had no place to live.
My role
I built all of it: the receiver for the clock's ADMS protocol, the REST API, the admin and employee dashboards, the device simulator, Docker Compose for local work and a Render blueprint for production.
Decisions
Resends are safe by design
On first contact the server answers with empty stamps, so the clock resends its entire history and every enrolled user. A unique index on (device serial, PIN, punch time) turns duplicates into no-ops: running the simulator twice still answers OK 7, and the log reads 0 new, 6 duplicates.
Only one clock may talk
Requests without a serial get 400, serials outside ALLOWED_SN get 403. A database error answers 500 on purpose: the clock retries later, so no punch is lost. Fingerprint templates sent by the device are never stored.
Rules for real punches, not ideal ones
When employees skip the function keys, the K40 sends status 0 for everything. So departure falls back to the last punch after arrival, breaks are paired 2 to 3, and all times are read in Africa/Tunis. An admin override beats an approved leave, which beats the automatic calculation.
The clock keeps the server awake
Render's free plan sleeps after 15 idle minutes. The clock polls every 10 seconds, so the backend never sleeps. The blueprint notes when to move to the paid plan for a guaranteed service.
What it does today
- Point the clock at the server and it shows online in the dashboard within one to two minutes, with its employees synced.
- Daily and monthly views, a CSV export ready for Excel, leave and remote-work requests approved by the admin in real time.
- Unit tests cover the protocol parsers and the daily calculation; a shell simulator replays a full day without hardware.