using Emgu.CV; using FaceRecognitionApp.Models; namespace FaceRecognitionApp.Services; public class CameraService : IDisposable { private VideoCapture? _capture; private readonly FaceRecognitionService _recognition; private readonly Action _onDetected; private CancellationTokenSource? _cts; private Task? _task; private DateTime _lastTime = DateTime.MinValue; private bool _isDisposed = false; public CameraService(string url, FaceRecognitionService recognition, Action onDetected) { _recognition = recognition; _onDetected = onDetected; Console.WriteLine($"Initializing camera with URL: {url}"); _capture = new VideoCapture(url); // Даем камере время на инициализацию потока Thread.Sleep(1000); if (!_capture.IsOpened) throw new Exception("Camera failed to open. Check URL and network connection."); Console.WriteLine("Camera hardware initialized."); } public void Start() { if (_isDisposed) return; _cts = new CancellationTokenSource(); _task = Task.Run(() => Loop(_cts.Token)); Console.WriteLine("Camera processing loop started."); } private async Task Loop(CancellationToken token) { Console.WriteLine("🎥 Frame processing loop active..."); while (!token.IsCancellationRequested) { try { using var frame = new Mat(); // Читаем кадр с таймаутом if (_capture!.Read(frame)) { if (!frame.IsEmpty && frame.Width > 0 && frame.Height > 0) { var face = _recognition.ProcessFrame(frame); if (face != null) { // Лимит частоты отправок (не чаще раза в 2 секунды) if ((DateTime.Now - _lastTime).TotalMilliseconds > 2000) { _lastTime = DateTime.Now; _onDetected(face); string status = face.IsRecognized ? $"✅ Recognized: {face.MatchedEmployee?.Name}" : "❌ Unknown face"; Console.WriteLine($"{DateTime.Now:HH:mm:ss} - {status}"); } } } } else { // Если Read вернул false, возможно потеря связи Console.WriteLine("⚠️ Failed to read frame, retrying..."); await Task.Delay(500, token); } // Небольшая задержка, чтобы не грузить процессор на 100% await Task.Delay(50, token); } catch (OperationCanceledException) { // Это нормальная ситуация при остановке break; } catch (Exception ex) { Console.WriteLine($"⚠️ Error in camera loop: {ex.Message}"); await Task.Delay(1000, token); } } Console.WriteLine("🛑 Camera loop finished."); } public void Stop() { if (_cts == null) return; Console.WriteLine("Stopping camera service..."); _cts.Cancel(); try { // Ждем завершения задачи, но не бесконечно if (_task != null) { _task.Wait(TimeSpan.FromSeconds(5)); } } catch (AggregateException ex) { // Игнорируем ошибки отмены задачи foreach (var inner in ex.InnerExceptions) { if (!(inner is TaskCanceledException || inner is OperationCanceledException)) { Console.WriteLine($"Unexpected error during stop: {inner.Message}"); } } } catch (Exception ex) { Console.WriteLine($"Error stopping task: {ex.Message}"); } } public void Dispose() { if (_isDisposed) return; Stop(); _capture?.Dispose(); _cts?.Dispose(); _isDisposed = true; Console.WriteLine("Camera resources released."); } }