# 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 1. Employee scans RFID card at timeclock 2. System triggers IP camera capture 3. Image is matched against MSSQL database record 4. 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: 1. **RFID Read Latency**: 2-5ms (physical card detection + data transfer) 2. **USB/Serial Communication**: 1-10ms depending on interface 3. **HTTP Request to Camera**: 20-100ms (network round-trip) 4. **Camera Shutter/IPE Frame Capture**: 50-200ms (depends on exposure/lighting) 5. **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: 1. **Fixed Focus** - Disable autofocus to eliminate 100-300ms delay 2. **Fixed Exposure** - Set manual exposure to eliminate AE calculation 3. **Low Resolution Stream** - Use 720p or lower for snapshot (faster transfer) 4. **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 ```bash pip install pyserial opencv-python requests onvif-zeep paho-mqtt ``` ### Code Sample 1: USB HID RFID Reader (Keyboard Emulation) ```python 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 ```python 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) ```python 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) ```python 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 ```python 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 ```sql -- 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 1. **Don't Store Images in MSSQL** - Store file paths only - Store perceptual hashes for comparison - Keep images on fast local SSD 2. **Pre-compute Face Embeddings** ```python 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 ``` 3. **Use Memory-Optimized Tables (SQL Server)** ```sql CREATE TABLE dbo.EmployeePhotos ( EmployeeID INT PRIMARY KEY NONCLUSTERED, PhotoHash VARBINARY(64) ) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA); ``` 4. **Query Pattern for Matching** ```sql -- 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) 1. Purchase USB HID RFID reader ($10-15) 2. Use `keyboard` library to detect scans 3. Trigger Hikvision/Dahua HTTP snapshot 4. Measure actual latency ### Phase 2: Optimization (RTSP Buffer) 1. If latency >100ms is problematic, implement OpenCV RTSP buffer 2. Capture frame from buffer instead of HTTP request 3. Measure improvement ### Phase 3: Advanced (Face Recognition) 1. Add `face_recognition` library 2. Pre-compute employee face embeddings 3. Match captured image against embeddings 4. 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: - Serial vs USB Interrupt: - Wireless Latency Benchmarks: - RFID Reader Options: ### Python RFID Integration - MFRC522 Python Library: - USB HID Reader Python: - Serial RFID Example: ### Camera APIs & ONVIF - Hikvision Snapshot URL: - ONVIF/OpenHAB Integration: - IP Camera Trigger Options: ### MQTT Camera Control - MQTT Camera Home Assistant: - Axis MQTT Integration: - Cam2MQTT Project: ### RFID Hardware Options - Dual-Frequency USB Readers: - ISO14443/EM4100 Readers: --- ## Summary **Key Takeaway:** The fastest solution for RFID-to-camera latency is combining: 1. USB HID RFID reader for <5ms card detection 2. OpenCV RTSP stream buffer for <20ms image capture 3. 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.*