diff --git a/alpr-service/main.py b/alpr-service/main.py index 186b691..cdd6c2e 100644 --- a/alpr-service/main.py +++ b/alpr-service/main.py @@ -57,10 +57,24 @@ def save_plate_capture(plate_number, full_frame): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") # Solo guardar frame completo - filename = f"{DATASET_DIR}/{plate_number}_{timestamp}.jpg" - cv2.imwrite(filename, full_frame, [cv2.IMWRITE_JPEG_QUALITY, 95]) + filename = f"{plate_number}_{timestamp}.jpg" + filepath = f"{DATASET_DIR}/{filename}" + cv2.imwrite(filepath, full_frame, [cv2.IMWRITE_JPEG_QUALITY, 95]) - print(f"📸 Saved to dataset: {plate_number}") + # Contar total de capturas + total_count = len([f for f in os.listdir(DATASET_DIR) if f.endswith('.jpg')]) + + # Notificar al backend para WebSocket + try: + requests.post(f"{BACKEND_URL}/api/dataset/capture", json={ + 'plate_number': plate_number, + 'filename': filename, + 'count': total_count + }, timeout=2) + except: + pass # No bloquear si falla la notificación + + print(f"📸 Saved to dataset: {plate_number} (Total: {total_count})") return True except Exception as e: print(f"❌ Error saving capture: {e}") diff --git a/backend/src/index.js b/backend/src/index.js index 766ffa1..626d42f 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -329,6 +329,22 @@ app.post('/api/detect', async (req, res) => { } }); +// Dataset Capture Notification (from ALPR Python) +app.post('/api/dataset/capture', (req, res) => { + const { plate_number, filename, count } = req.body; + console.log(`📸 Dataset capture: ${plate_number} (Total: ${count})`); + + // Notify Frontend via WebSocket + io.emit('dataset_updated', { + plate: plate_number, + filename, + count, + timestamp: new Date() + }); + + res.json({ message: 'Notification sent' }); +}); + const bcrypt = require('bcryptjs'); const PORT = process.env.PORT || 3000; diff --git a/frontend/src/pages/AdminDashboard.jsx b/frontend/src/pages/AdminDashboard.jsx index 64e18ff..3c86e51 100644 --- a/frontend/src/pages/AdminDashboard.jsx +++ b/frontend/src/pages/AdminDashboard.jsx @@ -33,29 +33,31 @@ function AdminDashboard({ token }) { fetchData(); fetchDatasetCount(); - // Actualizar contador de dataset cada 10 segundos - const datasetInterval = setInterval(fetchDatasetCount, 10000); - // Live detection listener socket.on('new_detection', (data) => { setDetections(prev => [data, ...prev].slice(0, 10)); }); + // Real-time dataset updates + socket.on('dataset_updated', (data) => { + setDatasetCount(data.count); + }); + // Real-time updates for approvals socket.on('new_plate_registered', () => fetchData()); socket.on('new_person_registered', () => fetchData()); - socket.on('plate_status_updated', () => fetchData()); // Reused for consistency + socket.on('plate_status_updated', () => fetchData()); socket.on('plate_deleted', () => fetchData()); socket.on('person_deleted', () => fetchData()); return () => { socket.off('new_detection'); + socket.off('dataset_updated'); socket.off('new_plate_registered'); socket.off('new_person_registered'); socket.off('plate_status_updated'); socket.off('plate_deleted'); socket.off('person_deleted'); - clearInterval(datasetInterval); }; }, [token]);