using Crestron.SimplSharp; using PhotoBooth; using RandomNameGeneratorLibrary; using Timeout = System.Threading.Timeout; namespace CrestronOpenCvSharp.Capture; public class MjpegCapture { private readonly HttpClient _client = new HttpClient(); private readonly string? _mjpegUrl; private readonly string? _directory; private readonly FacialRecognition? _facialRecognition; private Timer? _timer; private readonly PersonNameGenerator _personNameGenerator; private Contract _contract; public bool CaptureRunning { get; private set; } private const string BaseUrl = "https://ise2025.local.staal.one/VirtualControl/MA/Rooms/MYFIRSTAI/Html/"; public MjpegCapture(string? url, string? directory, FacialRecognition? facialRecognition, Contract contract) { _mjpegUrl = url; _directory = Path.Combine(directory!, "captures"); _facialRecognition = facialRecognition; _contract = contract; _personNameGenerator = new PersonNameGenerator(); } public void StartCapture(int timeout) { if (string.IsNullOrEmpty(_directory)) { Console.WriteLine("Directory variable was null or empty."); CaptureRunning = false; return; } CheckIfDirectoryExists(_directory); // Only create if it's null _timer = new Timer(CaptureImage, null, 0, timeout); CaptureRunning = true; } public void StopCapture() { if (_timer is not null) { // Stop the timer _timer.Change(Timeout.Infinite, Timeout.Infinite); // Dispose it _timer.Dispose(); } CaptureRunning = false; } private void CheckIfDirectoryExists(string directory) { Console.WriteLine($"Checking if directory {directory} exists."); if (Directory.Exists(directory)) { // Remove the directory and all its contents Directory.Delete(directory, true); Console.WriteLine($"Directory '{directory}' and all its contents have been removed."); Directory.CreateDirectory(directory); Console.WriteLine($"Directory '{directory}' has been created."); } else { // Create the directory Directory.CreateDirectory(directory); Console.WriteLine($"Directory '{directory}' has been created."); } } private async void CaptureImage(object? state) { try { CaptureRunning = true; var uniqueName = $"frame_{DateTime.Now:yyyyMMdd_HHmmss}.jpg"; var fileName = Path.Combine(_directory!, uniqueName); try { HttpResponseMessage response = await _client.GetAsync(_mjpegUrl, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); await using (var stream = await response.Content.ReadAsStreamAsync()) await using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { await stream.CopyToAsync(fileStream); } Console.WriteLine($"Saved frame to {fileName}"); _contract.Main.ImagePreview_Url(string.Format($"{BaseUrl}/captures/{uniqueName}")); Console.WriteLine($"Sending URL {string.Format($"{BaseUrl}/captures/{uniqueName}")}"); if (_facialRecognition!.CheckForFace(fileName)) { StopCapture(); _contract.Main.ImagePreview_Url(string.Empty); Thread.Sleep(1000); Console.WriteLine("Face detected, stopping capture"); Console.WriteLine("Comparing captured face against database"); var result = await _facialRecognition.CompareFaces(); if (result is not null) { Console.WriteLine($"We have found a match! The person in front of the camera is: {result}"); _contract.Main.txtFeedback_Indirect($"{result} detected!"); } else { Console.WriteLine("No match was found in our database, let's add this person!"); var randomFullName = _personNameGenerator.GenerateRandomFirstAndLastName(); _facialRecognition.AddPersonToDatabase(randomFullName); Console.WriteLine("Person added to database"); _contract.Main.txtFeedback_Indirect($"{randomFullName} added to database"); } } else { Console.WriteLine("No face detected, carrying on!"); _contract.Main.txtFeedback_Indirect($"No face detected!"); } } catch (Exception ex) { Console.WriteLine($"Error capturing image: {ex.Message}"); } } catch (Exception e) { Console.WriteLine($"Error capturing image: {e}"); } } }