import json import base64 import cv2 import numpy as np import asyncio from fastapi import WebSocket, WebSocketDisconnect from services.vision import process_frame_synchronous from services.attendance import mark_attendance from core.state import active_connections async def websocket_endpoint(websocket: WebSocket): """ Hard-Locked WebSocket Connection with Visual Debugging. Returns crops and bounding boxes alongside the Truth Report. """ await websocket.accept() active_connections.append(websocket) try: while True: data = await websocket.receive_text() payload = json.loads(data) if payload.get("type") == "heartbeat": await websocket.send_json({"type": "heartbeat_ack"}) continue if payload.get("type") == "frame": encoded_data = payload["image"].split(',')[1] nparr = np.frombuffer(base64.b64decode(encoded_data), np.uint8) frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR) report, stats = await asyncio.to_thread(process_frame_synchronous, frame) results_summary = [] # Prepare visual data for frontend client_faces = [] for face in report: name = face["name"] score = face["score"] status = face["status"] # Store data for drawing boxes and showing crops client_faces.append({ "name": name, "score": score, "status": status, "box": face["box"], "crop": face["crop_b64"] }) if status == "match": # Business Logic: Mark Attendance status_db, time_str = mark_attendance(name) results_summary.append(f"✅ {name} ({score}%)") # Push to session attendance list await websocket.send_json({ "type": "attendance", "name": name, "time": time_str or "Just Now", "status": "success" }) else: results_summary.append(f"❌ {name} ({score}%)") # Detailed Terminal Output debug_msg = f"Faces: {stats['detected']} | " debug_msg += " | ".join(results_summary) if results_summary else "No faces found." # Send frame processing result back to browser await websocket.send_json({ "type": "ready", "debug": debug_msg, "faces": client_faces # ALL visual debug data included here }) except WebSocketDisconnect: if websocket in active_connections: active_connections.remove(websocket)