using System.IO.Ports; using System.Text; using MaterialSkin.Controls; using Serilog; using VisionBuilder.UI.Common; using VisionBuilder.UI.Common.Processing; using VisionBuilder.UI.Statistics; namespace CandyboxPlugin.Modules.Barcode; public class CandyboxBarcodeReader : IVisionBuilderModule { private readonly ILoadingService _loadingService; private readonly CandyboxBarcodeReaderSettings _settings; private readonly SingleCameraVM _singleCameraVm; private readonly VisionBuilderStatistics _statistics; private SerialPort _port; public EReaderState _readerState = EReaderState.ReadingRecipe; private MaterialCancellableLoader? _loader; public CandyboxBarcodeReader(CandyboxBarcodeReaderSettings settings, SingleCameraVM singleCameraVm, VisionBuilderStatistics statistics) { _settings = settings; _singleCameraVm = singleCameraVm; _statistics = statistics; } private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e) { Thread.Sleep(500); if(_singleCameraVm.IsRunning)return; if(_readerState == EReaderState.ReadingRecipe) ReadRecipe(); if (_readerState == EReaderState.ReadingAUF) ReadAUF(); } private void ReadRecipe() { if (_singleCameraVm.IsRunning) return; byte[] buffer = new byte[_port.BytesToRead]; _port.Read(buffer, 0, _port.BytesToRead); var data = Encoding.ASCII.GetString(buffer).Trim(); if (string.IsNullOrEmpty(data)) { Log.Warning("Received empty recipe"); return; } var vm = _singleCameraVm.GetRecipeSelectionVm(); var recipes = vm.Recipes; string searchString = data; Log.Information("Read Recipe: {Recipe}", data); if (_settings.BarcodeRecipeMappings.Any(x => x.Barcode == searchString)) { searchString = _settings.BarcodeRecipeMappings.First(x => x.Barcode == searchString).RecipeName; } var existingRecipe = recipes.FirstOrDefault(x => x.RecipeName == searchString); if (existingRecipe == null) { Log.Warning("No matching recipe found for data: {Data}", data); return; } vm.SelectedRecipe = vm.Recipes.FirstOrDefault(r => r.RecipeName == existingRecipe.RecipeName); _singleCameraVm.SynchronizationContext!.Post((_) => { _loader = new MaterialCancellableLoader(); _loader.StartLoading("Waiting for AUF..."); _loader.LoadingCancelled += CancelWaiting; _singleCameraVm.ProcessRecipeSelectionVm(vm); }, null); Application.DoEvents(); _readerState = EReaderState.ReadingAUF; } private void CancelWaiting(object? sender, string e) { _singleCameraVm.SynchronizationContext!.Post((_) => { _loader.FinishLoading("Waiting for AUF..."); _loader.LoadingCancelled -= CancelWaiting; _loader = null; }, null); _readerState = EReaderState.ReadingRecipe; } private void ReadAUF() { byte[] buffer = new byte[_port.BytesToRead]; _port.Read(buffer, 0, _port.BytesToRead); var data = Encoding.ASCII.GetString(buffer).Trim(); if (string.IsNullOrEmpty(data)) { Log.Warning("Received empty AUF"); return; } Log.Information("Read AUF: {AUF}", data); if (_loader != null) { CancelWaiting(this, string.Empty); } _statistics.Metadata = data; _=_singleCameraVm.Start().ConfigureAwait(false); Application.DoEvents(); _readerState = EReaderState.ReadingRecipe; } public void InitializeModule() { try { _port = new SerialPort(_settings.ComPort, 9600); _port.Open(); _port.DataReceived += _port_DataReceived; } catch (Exception e) { Log.Warning(e, "Failed to open com-port"); } } }