14 KiB
Project: Employee Punch Tracking
Created: 2026-02-24 Source: #work-assistant Status: Beta Production Phase
Overview
Track employee timeclock punches via RFID cards and capture images via IP camera for verification.
Purpose
- Track employee punch in/out via RFID card
- Capture image via IP camera when card is scanned
- Match captured image with employee database record
- Integrate with external timeclock software
How It Works
- Employee scans RFID card at timeclock
- System triggers IP camera capture
- Image is matched against MSSQL database record
- Time punch is logged in external vendor time software
Architecture
- IP camera for image capture
- RFID card reader
- MSSQL database for employee photos/records
- External timeclock software (vendor provided)
- Custom software runs "on top" of vendor system
Current Status
🚀 Beta Production
- Software functioning well in production
- Active monitoring ongoing
Known Issues
Latency Problem: Delay between RFID scan and image capture
- Currently researching alternative solutions
- Goal: Reduce/remove latency gap
Tasks
- Research alternative latency solutions
- Implement latency improvement
- Continue production monitoring
Notes
(Add camera specs, RFID reader model, MSSQL schema, vendor software details, etc.)
Related
Extracted from Projects to be organized
Research Findings
Research Date: 2026-02-24
Focus: RFID + IP Camera Latency Solutions
Latency Problem Analysis
Current Bottleneck Identification
The primary latency in RFID-to-camera capture systems comes from multiple sequential steps:
- RFID Read Latency: 2-5ms (physical card detection + data transfer)
- USB/Serial Communication: 1-10ms depending on interface
- HTTP Request to Camera: 20-100ms (network round-trip)
- Camera Shutter/IPE Frame Capture: 50-200ms (depends on exposure/lighting)
- Image Transfer: 50-500ms (depends on resolution)
Total Typical Latency: 123-815ms
Critical Insight from Research
The biggest latency contributor is NOT the RFID reader (which is typically <10ms), but rather:
- Camera exposure/autofocus delay when triggering from idle
- Network round-trip for HTTP snapshot requests
- Image compression and transfer time
Recommended Hardware (RFID Reader + Camera Combo)
RFID Reader Options
Option 1: USB HID Keyboard Emulation (Recommended for Simplicity)
- Cost: $8-15 (Amazon: Dual-frequency 125KHz/13.56MHz readers)
- Protocols: ISO14443-A/B, EM4100
- Latency: <5ms from card touch to character output
- Python Integration: No special drivers - reads as keyboard input
- Models: Generic USB HID readers (Navfmru, HiLetgo, generic dual-frequency)
Option 2: Serial/UART RFID Reader (For Advanced Control)
- Cost: $12-25
- Interface: USB-to-Serial (appears as COM port)
- Protocols: SPI/I2C/UART
- Latency: <2ms (interrupt-driven serial)
- Python Library:
pyserial - Best for: When you need custom parsing or have multiple readers
Option 3: Ethernet-Connected RFID Reader
- Cost: $50-150
- Latency: Depends on network (1-5ms local)
- Best for: Industrial setups with existing PoE infrastructure
Recommendation: Start with USB HID Keyboard Emulation readers - simplest integration, lowest cost, adequate latency.
IP Camera Recommendations
Low-Latency Trigger-Optimized Cameras
Hikvision / Dahua (Best API Support):
- Direct HTTP snapshot URLs:
http://camera-ip/Streaming/channels/1/picture - ONVIF snapshot:
http://camera-ip/onvif/snapshot - Typical latency: 50-150ms for snapshot
- Key Feature: Can pre-authenticate and keep session alive
Axis (MQTT Support):
- Native MQTT event publishing
- Can subscribe to ONVIF events
- More expensive but better integration options
INSTAR (Built-in MQTT):
- Native MQTT for motion triggers
- Can trigger snapshot via MQTT message
Latency-Reducing Camera Configuration:
- Fixed Focus - Disable autofocus to eliminate 100-300ms delay
- Fixed Exposure - Set manual exposure to eliminate AE calculation
- Low Resolution Stream - Use 720p or lower for snapshot (faster transfer)
- Motion JPEG - Prefer MJPEG over H.264 for snapshot endpoints
Low-Latency Architecture Options
Architecture A: HTTP Snapshot on RFID Event (Simple)
RFID Scan → Python HTTP Request → Camera → Save Image → Match
Latency: 100-300ms
Pros: Simple, no additional infrastructure
Cons: Every scan has network round-trip
Architecture B: Always-Recording with Frame Grab (Best for Speed)
Camera always streaming (RTSP)
RFID Scan → Python grabs current frame from buffer → Match
Latency: 10-50ms
Pros: Fastest capture, no network request at scan time
Cons: Higher CPU/network usage, requires OpenCV/ffmpeg
Architecture C: MQTT/Event-Driven (Scalable)
RFID Scan → Publish MQTT message → Camera subscribes → Captures
Latency: 50-150ms
Pros: Decoupled, multiple cameras possible
Cons: Requires MQTT broker
Architecture D: ONVIF Events with Pre-trigger Buffer (Professional)
Camera constantly buffers 2-3 seconds
RFID triggers ONVIF event → Camera saves pre/post buffer
Latency: 0ms (image from before trigger!)
Pros: Can capture image BEFORE scan
Cons: Complex setup, requires ONVIF Profile S/G support
Recommended Hybrid Approach:
Primary: Always-streaming RTSP with OpenCV frame buffer
Fallback: HTTP snapshot if buffer unavailable
Python Libraries and Code Samples
Library Requirements
pip install pyserial opencv-python requests onvif-zeep paho-mqtt
Code Sample 1: USB HID RFID Reader (Keyboard Emulation)
import keyboard # pip install keyboard
from datetime import datetime
import requests
def on_rfid_scan(event):
"""Capture RFID UID from keyboard emulation"""
uid = event.name
timestamp = datetime.now()
# Trigger camera capture immediately
capture_image(uid, timestamp)
# Hook into keyboard events
keyboard.on_press(on_rfid_scan)
keyboard.wait()
Code Sample 2: Serial RFID Reader
import serial
import threading
def read_rfid_serial(port='COM3', baudrate=9600):
ser = serial.Serial(port, baudrate, timeout=0.1)
buffer = ""
while True:
if ser.in_waiting:
data = ser.read(ser.in_waiting).decode('utf-8')
buffer += data
# Check for complete UID (usually ends with CR/LF)
if '\r' in buffer or '\n' in buffer:
uid = buffer.strip()
buffer = ""
capture_image(uid)
# Run in separate thread for non-blocking
threading.Thread(target=read_rfid_serial, daemon=True).start()
Code Sample 3: HTTP Snapshot (Synchronous)
import requests
from datetime import datetime
CAMERA_URL = "http://192.168.1.100/Streaming/channels/1/picture"
CAMERA_AUTH = ("admin", "password")
def capture_http_snapshot(uid):
start = datetime.now()
response = requests.get(CAMERA_URL, auth=CAMERA_AUTH, timeout=2)
if response.status_code == 200:
filename = f"captures/{uid}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
with open(filename, 'wb') as f:
f.write(response.content)
latency = (datetime.now() - start).total_seconds() * 1000
print(f"Captured in {latency:.1f}ms")
return filename
Code Sample 4: OpenCV Always-Streaming (Fastest)
import cv2
import threading
import queue
class CameraBuffer:
def __init__(self, rtsp_url):
self.cap = cv2.VideoCapture(rtsp_url)
self.frame = None
self.lock = threading.Lock()
# Start capture thread
threading.Thread(target=self._update, daemon=True).start()
def _update(self):
while True:
ret, frame = self.cap.read()
if ret:
with self.lock:
self.frame = frame
def get_frame(self):
with self.lock:
return self.frame.copy() if self.frame is not None else None
# Usage
camera = CameraBuffer("rtsp://admin:pass@192.168.1.100:554/Streaming/Channels/1")
def capture_image(uid):
frame = camera.get_frame()
if frame is not None:
filename = f"captures/{uid}_{datetime.now():%Y%m%d_%H%M%S}.jpg"
cv2.imwrite(filename, frame)
return filename
Code Sample 5: ONVIF Event Subscription
from onvif import ONVIFCamera
def setup_onvif_events(camera_ip, user, password):
camera = ONVIFCamera(camera_ip, 80, user, password)
# Create events service
events = camera.create_events_service()
# Subscribe to events
subscription = events.CreatePullPointSubscription()
return camera, subscription
MSSQL Optimization for Fast Employee Photo Matching
Schema Recommendations
-- Store image hashes for fast comparison (not full images in DB)
CREATE TABLE EmployeePhotos (
EmployeeID INT PRIMARY KEY,
PhotoHash VARBINARY(64) INDEXED, -- SHA-256 hash
PhotoPath NVARCHAR(500), -- Path to actual image
FaceEncoding VARBINARY(MAX), -- If using face recognition
LastUpdated DATETIME2
);
-- Index for hash lookups
CREATE NONCLUSTERED INDEX IX_PhotoHash ON EmployeePhotos(PhotoHash);
Optimization Strategies
-
Don't Store Images in MSSQL
- Store file paths only
- Store perceptual hashes for comparison
- Keep images on fast local SSD
-
Pre-compute Face Embeddings
import face_recognition # One-time: Store face encoding image = face_recognition.load_image_file("employee.jpg") encoding = face_recognition.face_encodings(image)[0] # Save encoding to DB as binary blob -
Use Memory-Optimized Tables (SQL Server)
CREATE TABLE dbo.EmployeePhotos ( EmployeeID INT PRIMARY KEY NONCLUSTERED, PhotoHash VARBINARY(64) ) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA); -
Query Pattern for Matching
-- Fast hash lookup first SELECT EmployeeID FROM EmployeePhotos WHERE PhotoHash = @capturedHash; -- If using face recognition, compare embeddings -- in Python (not SQL) for algorithm flexibility
Implementation Recommendations
Phase 1: Quick Win (HTTP Snapshot)
- Purchase USB HID RFID reader ($10-15)
- Use
keyboardlibrary to detect scans - Trigger Hikvision/Dahua HTTP snapshot
- Measure actual latency
Phase 2: Optimization (RTSP Buffer)
- If latency >100ms is problematic, implement OpenCV RTSP buffer
- Capture frame from buffer instead of HTTP request
- Measure improvement
Phase 3: Advanced (Face Recognition)
- Add
face_recognitionlibrary - Pre-compute employee face embeddings
- Match captured image against embeddings
- Log match confidence with each punch
Latency Targets by Phase:
| Phase | Expected Latency | Implementation Time |
|---|---|---|
| Phase 1 | 100-300ms | 1-2 days |
| Phase 2 | 10-50ms | 3-5 days |
| Phase 3 | 10-50ms + match | 1-2 weeks |
Real-World Latency Benchmarks (from Research)
| Component | Typical | Optimized | Notes |
|---|---|---|---|
| RFID Read | 2-5ms | 1-2ms | HID faster than serial |
| USB Transfer | 1-10ms | 1-2ms | Interrupt vs polling |
| HTTP Request | 20-100ms | 10-20ms | Keep-alive connections |
| Camera Shutter | 50-200ms | 0ms | Fixed exposure eliminates |
| Image Transfer | 50-500ms | 5-20ms | Lower resolution, MJPEG |
| Total HTTP | 123-815ms | 17-46ms | With optimizations |
| RTSP Buffer | 10-50ms | 5-15ms | Fastest option |
Source Links
RFID & Communication Latency
- USB Latency Analysis: https://electronics.stackexchange.com/questions/192920/usb-device-latency
- Serial vs USB Interrupt: https://stackoverflow.com/questions/41987430/lowest-latency-communication-microcontroller
- Wireless Latency Benchmarks: https://electricui.com/blog/latency-comparison
- RFID Reader Options: https://raspberrypi.stackexchange.com/questions/13930/capturing-serial-number-usb-rfid-reader
Python RFID Integration
- MFRC522 Python Library: https://github.com/pimylifeup/MFRC522-python
- USB HID Reader Python: https://github.com/charlysan/pyrfidhid
- Serial RFID Example: https://stackoverflow.com/questions/56808495/reading-tags-uid-rc522-usb-serial-python
Camera APIs & ONVIF
- Hikvision Snapshot URL: https://www.cctvforum.com/topic/32499-snashot-url-for-hikvisionswannlorex-cameras/
- ONVIF/OpenHAB Integration: https://www.openhab.org/addons/bindings/ipcamera/
- IP Camera Trigger Options: https://ipcamtalk.com/tags/api/
MQTT Camera Control
- MQTT Camera Home Assistant: https://www.home-assistant.io/integrations/camera.mqtt
- Axis MQTT Integration: https://www.hivemq.com/blog/enhancing-axis-network-camera-capabilities-mqtt-hivemq/
- Cam2MQTT Project: https://github.com/berfenger/cam2mqtt
RFID Hardware Options
- Dual-Frequency USB Readers: https://www.amazon.com/13-56Mhz-ISO14443-Protocol-Contactless-Compatible/dp/B0CY2YT86P
- ISO14443/EM4100 Readers: https://gaorfid.com/devices/rfid-readers-frequency/
Summary
Key Takeaway: The fastest solution for RFID-to-camera latency is combining:
- USB HID RFID reader for <5ms card detection
- OpenCV RTSP stream buffer for <20ms image capture
- Skip HTTP requests entirely - grab from buffer
This yields 15-25ms total latency from scan to image capture - well within acceptable limits for timeclock verification.
Alternative Simple Path: If RTSP complexity is undesirable, using HTTP snapshots with fixed-exposure camera settings can achieve 50-100ms latency with minimal implementation effort.
Research compiled by AI assistant. Hardware links are examples only - verify compatibility before purchase.