diff --git a/Hawkeye.VisionBuilder.UI.Sources.Emulation/EmulationCameraImageSource.cs b/Hawkeye.VisionBuilder.UI.Sources.Emulation/EmulationCameraImageSource.cs
index c7d5d2c..4ad59a8 100644
--- a/Hawkeye.VisionBuilder.UI.Sources.Emulation/EmulationCameraImageSource.cs
+++ b/Hawkeye.VisionBuilder.UI.Sources.Emulation/EmulationCameraImageSource.cs
@@ -36,11 +36,7 @@ namespace Hawkeye.VisionBuilder.UI.Sources.Emulation
//clear the channel if it is full
if (_channel.Reader.Count > 0)
{
- while (await _channel.Reader.WaitToReadAsync(token))
- {
- if (_channel.Reader.TryRead(out _)) continue;
- break;
- }
+ while (_channel.Reader.TryRead(out _)) { }
}
//get the next image
await Task.Run(new Action(() => _ = GetImageInternal(CancellationToken.None)), token);
diff --git a/Hawkeye.VisionBuilder.Workflow/Hawkeye.VisionBuilder.Workflow.csproj b/Hawkeye.VisionBuilder.Workflow/Hawkeye.VisionBuilder.Workflow.csproj
index f0fb47d..d3e6325 100644
--- a/Hawkeye.VisionBuilder.Workflow/Hawkeye.VisionBuilder.Workflow.csproj
+++ b/Hawkeye.VisionBuilder.Workflow/Hawkeye.VisionBuilder.Workflow.csproj
@@ -18,7 +18,6 @@
-
diff --git a/VisionBuilder.UI.Camera/ModuleExtensions.cs b/VisionBuilder.UI.Camera/ModuleExtensions.cs
index d9181a6..bbf123a 100644
--- a/VisionBuilder.UI.Camera/ModuleExtensions.cs
+++ b/VisionBuilder.UI.Camera/ModuleExtensions.cs
@@ -12,6 +12,7 @@ public static class ModuleExtensions
{
self.Bind().ToConstant(new CameraSettings(cameraName));
self.Bind().ToConstant(new EmulationSettings(cameraName));
+ self.Bind().ToSelf().InSingletonScope();
return self;
}
private static void BindCameras(CameraSettings cameraSettings, IChildKernel kernel)
diff --git a/VisionBuilder.UI.Common/Extensions.cs b/VisionBuilder.UI.Common/Extensions.cs
index 47c61b5..312673c 100644
--- a/VisionBuilder.UI.Common/Extensions.cs
+++ b/VisionBuilder.UI.Common/Extensions.cs
@@ -1,6 +1,7 @@
using Inspectron.Settings;
using Ninject;
using Ninject.Extensions.ChildKernel;
+using Serilog;
namespace VisionBuilder.UI.Common;
@@ -28,10 +29,18 @@ public static class Extensions
var serviceTypes = self.GetAll(typeof(IVisionBuilderModule)).Select(x => (IVisionBuilderModule)x).ToList();
foreach (var service in serviceTypes)
{
- if (service != null)
+ try
{
- service.InitializeModule();
+ if (service != null)
+ {
+ service.InitializeModule();
+ }
}
+ catch (Exception e)
+ {
+ Log.Error($"Error initializing module {service.GetType().Name}: {e.Message}", e);
+ }
+
}
}
diff --git a/VisionBuilder.UI.Common/VisionBuilder.UI.Common.csproj b/VisionBuilder.UI.Common/VisionBuilder.UI.Common.csproj
index b0a2cfb..58a79d0 100644
--- a/VisionBuilder.UI.Common/VisionBuilder.UI.Common.csproj
+++ b/VisionBuilder.UI.Common/VisionBuilder.UI.Common.csproj
@@ -11,6 +11,7 @@
+
diff --git a/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.Designer.cs b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.Designer.cs
new file mode 100644
index 0000000..4376e34
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.Designer.cs
@@ -0,0 +1,49 @@
+namespace VisionBuilder.UI.IOCommander.Windows
+{
+ partial class IOCommanderVirtualInput
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ SuspendLayout();
+ //
+ // IOCommanderVirtualInput
+ //
+ AutoScaleDimensions = new SizeF(7F, 15F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(200, 500);
+ ControlBox = false;
+ FormBorderStyle = FormBorderStyle.FixedToolWindow;
+ MaximizeBox = false;
+ MinimizeBox = false;
+ Name = "IOCommanderVirtualInput";
+ Text = "IO Commander Virtual Input";
+ ResumeLayout(false);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.cs b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.cs
new file mode 100644
index 0000000..a9125f3
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using VisionBuilder.UI.Common;
+using VisionBuilder.UI.IOCommander.Interfaces;
+
+namespace VisionBuilder.UI.IOCommander.Windows
+{
+ public partial class IOCommanderVirtualInput : Form, IIOCommander
+ {
+ private CheckBox[] _checkBoxes;
+
+ public IOCommanderVirtualInput()
+ {
+ InitializeComponent();
+ InitializeCheckboxes();
+ }
+
+ public BitArray PinState { get; set; } = new BitArray(20);
+ public event Action? OnPinChanged = delegate { };
+
+ public void SetPins(int pin, bool state)
+ {
+ // This is a dummy function as per requirement
+ }
+
+ private void InitializeCheckboxes()
+ {
+ // Set form properties
+ this.Text = "IO Commander Virtual Input";
+ this.ClientSize = new Size(200, 500);
+ this.FormBorderStyle = FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.StartPosition = FormStartPosition.Manual;
+ this.Location = new Point(350, 50); // Set a fixed position for the form
+
+ // Create a panel to contain checkboxes with scrolling if needed
+ Panel panel = new Panel
+ {
+ Dock = DockStyle.Fill,
+ AutoScroll = true
+ };
+ this.Controls.Add(panel);
+
+ // Initialize checkboxes
+ _checkBoxes = new CheckBox[20];
+
+ for (int i = 0; i < 20; i++)
+ {
+ int pinNumber = i + 1; // Pins are 1-indexed
+ _checkBoxes[i] = new CheckBox
+ {
+ Text = pinNumber.ToString(),
+ Location = new Point(20, 20 + (i * 22)),
+ Size = new Size(150, 20),
+ Tag = pinNumber, // Store the pin number in Tag for easy reference
+ };
+
+ // Add event handler
+ _checkBoxes[i].CheckedChanged += CheckBox_CheckedChanged;
+
+ panel.Controls.Add(_checkBoxes[i]);
+ }
+ }
+
+ private void CheckBox_CheckedChanged(object? sender, EventArgs e)
+ {
+ if (sender is CheckBox checkBox)
+ {
+ int pin = (int)checkBox.Tag;
+ bool state = checkBox.Checked;
+
+ // Update the BitArray
+ PinState.Set(pin - 1, state); // Adjust for 0-based indexing in BitArray
+
+ // Trigger the event
+ OnPinChanged?.Invoke(pin, state);
+ }
+ }
+
+
+ protected override void OnShown(EventArgs e)
+ {
+ TopMost= true;
+ Focus();
+ TopMost = true;
+ }
+ }
+}
diff --git a/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.resx b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.resx
new file mode 100644
index 0000000..8b2ff64
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInput.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInputFactory.cs b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInputFactory.cs
new file mode 100644
index 0000000..89c6022
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander.Windows/IOCommanderVirtualInputFactory.cs
@@ -0,0 +1,28 @@
+using VisionBuilder.UI.IOCommander.Interfaces;
+using VisionBuilder.UI.IOCommander.Settings;
+
+namespace VisionBuilder.UI.IOCommander.Windows;
+
+public class IOCommanderVirtualInputFactory: IIOCommanderFactory
+{
+ private readonly VirtualInputSettings _settings;
+ private readonly DefaultIOCommanderFactory _defaultFactory;
+
+ public IOCommanderVirtualInputFactory(VirtualInputSettings settings, IOCommanderSettings ioCommanderSettings)
+ {
+ _settings = settings;
+ _defaultFactory = new DefaultIOCommanderFactory(ioCommanderSettings);
+ }
+
+ public IIOCommander Create()
+ {
+ if (_settings.Enabled)
+ {
+ var res = new IOCommanderVirtualInput();
+ res.Show();
+ return res;
+ }
+
+ return _defaultFactory.Create();
+ }
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander.Windows/ModuleExtensions.cs b/VisionBuilder.UI.IOCommander.Windows/ModuleExtensions.cs
index 8ec85b6..a9e421c 100644
--- a/VisionBuilder.UI.IOCommander.Windows/ModuleExtensions.cs
+++ b/VisionBuilder.UI.IOCommander.Windows/ModuleExtensions.cs
@@ -18,4 +18,11 @@ public static class ModuleExtensions
self.Bind().ToConstant(new WindowsIOCommanderDebugViewSettings());
return self;
}
+
+ public static IKernel UseIOCommanderVirtualInput(this IKernel self)
+ {
+ self.Bind().To().InSingletonScope();
+ self.Rebind().To().InSingletonScope();
+ return self;
+ }
}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander.Windows/VirtualInputSettings.cs b/VisionBuilder.UI.IOCommander.Windows/VirtualInputSettings.cs
new file mode 100644
index 0000000..425d873
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander.Windows/VirtualInputSettings.cs
@@ -0,0 +1,13 @@
+using Inspectron.Settings;
+using VisionBuilder.UI.Common;
+
+namespace VisionBuilder.UI.IOCommander.Windows;
+
+public class VirtualInputSettings: ISettings
+{
+ public bool Enabled { get; set; }
+ public void RegisterSettings(InspectronSettings settings)
+ {
+ settings.RegisterSimple(this,()=>this.Enabled,"IOCommander/Virtual input",nameof(Enabled));
+ }
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander/DefaultIOCommanderFactory.cs b/VisionBuilder.UI.IOCommander/DefaultIOCommanderFactory.cs
new file mode 100644
index 0000000..c521412
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander/DefaultIOCommanderFactory.cs
@@ -0,0 +1,19 @@
+using VisionBuilder.UI.IOCommander.Interfaces;
+using VisionBuilder.UI.IOCommander.Settings;
+
+namespace VisionBuilder.UI.IOCommander;
+
+public class DefaultIOCommanderFactory: IIOCommanderFactory
+{
+ private readonly IOCommanderSettings _settings;
+
+ public DefaultIOCommanderFactory(IOCommanderSettings settings)
+ {
+ _settings = settings;
+ }
+
+ public IIOCommander Create()
+ {
+ return new IOCommander(_settings.Port);
+ }
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander/IOCommander.cs b/VisionBuilder.UI.IOCommander/IOCommander.cs
index 4de7a2f..85934ea 100644
--- a/VisionBuilder.UI.IOCommander/IOCommander.cs
+++ b/VisionBuilder.UI.IOCommander/IOCommander.cs
@@ -1,9 +1,10 @@
using System.Collections;
using System.IO.Ports;
+using VisionBuilder.UI.IOCommander.Interfaces;
namespace VisionBuilder.UI.IOCommander;
-public class IOCommander
+public class IOCommander : IIOCommander
{
SerialPort _port;
diff --git a/VisionBuilder.UI.IOCommander/Interfaces/IIOCommander.cs b/VisionBuilder.UI.IOCommander/Interfaces/IIOCommander.cs
new file mode 100644
index 0000000..0f3f0bd
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander/Interfaces/IIOCommander.cs
@@ -0,0 +1,10 @@
+using System.Collections;
+
+namespace VisionBuilder.UI.IOCommander.Interfaces;
+
+public interface IIOCommander
+{
+ BitArray PinState { get; }
+ event Action OnPinChanged;
+ void SetPins(int pin, bool state);
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander/Interfaces/IIOCommanderFactory.cs b/VisionBuilder.UI.IOCommander/Interfaces/IIOCommanderFactory.cs
new file mode 100644
index 0000000..373d0fc
--- /dev/null
+++ b/VisionBuilder.UI.IOCommander/Interfaces/IIOCommanderFactory.cs
@@ -0,0 +1,6 @@
+namespace VisionBuilder.UI.IOCommander.Interfaces;
+
+public interface IIOCommanderFactory
+{
+ public IIOCommander Create();
+}
\ No newline at end of file
diff --git a/VisionBuilder.UI.IOCommander/ModuleExtensions.cs b/VisionBuilder.UI.IOCommander/ModuleExtensions.cs
index 6a22782..6630f1b 100644
--- a/VisionBuilder.UI.IOCommander/ModuleExtensions.cs
+++ b/VisionBuilder.UI.IOCommander/ModuleExtensions.cs
@@ -22,6 +22,7 @@ public static class ModuleExtensions
self.Bind().To().InSingletonScope();
self.Bind().To().InSingletonScope();
self.Bind().To().InSingletonScope();
+ self.Bind().To().InSingletonScope();
return self;
}
diff --git a/VisionBuilder.UI.IOCommander/Modules/IOCommanderCameraModule.cs b/VisionBuilder.UI.IOCommander/Modules/IOCommanderCameraModule.cs
index ea0ea84..ae7ee25 100644
--- a/VisionBuilder.UI.IOCommander/Modules/IOCommanderCameraModule.cs
+++ b/VisionBuilder.UI.IOCommander/Modules/IOCommanderCameraModule.cs
@@ -14,22 +14,54 @@ public class IOCommanderCameraModule: IVisionBuilderModule
private readonly IOCommanderCameraSettings _cameraSettings;
private readonly IRecognitionControl _recognitionControl;
private readonly MainWindowVM _mainWindowVm;
+ private readonly SingleCameraVM _cameraVm;
- public IOCommanderCameraModule(IOCommanderModule mainModule, IOCommanderSettings settings, IOCommanderCameraSettings cameraSettings, IRecognitionControl recognitionControl, MainWindowVM mainWindowVm)
+ public IOCommanderCameraModule(IOCommanderModule mainModule, IOCommanderSettings settings, IOCommanderCameraSettings cameraSettings, IRecognitionControl recognitionControl, MainWindowVM mainWindowVm, SingleCameraVM cameraVm)
{
_mainModule = mainModule;
_settings = settings;
_cameraSettings = cameraSettings;
_recognitionControl = recognitionControl;
_mainWindowVm = mainWindowVm;
+ _cameraVm = cameraVm;
_recognitionControl.ImageProcessed += _recognitionControl_ImageProcessed;
_recognitionControl.SessionStarted += _recognitionControl_SessionStarted;
_recognitionControl.SessionEnded += _recognitionControl_SessionEnded;
+ mainModule.OnPinChangedEvent += MainModule_OnPinChangedEvent;
}
-
+
+ private void ProcessCommand(EGPIOCommand command)
+ {
+ switch (command)
+ {
+ case EGPIOCommand.Start:
+ if(_cameraVm.StartCommand.CanExecute(null))
+ {
+ _cameraVm.StartCommand.Execute(null);
+ }
+ break;
+ case EGPIOCommand.Stop:
+ if(_cameraVm.StopCommand.CanExecute(null))
+ {
+ _cameraVm.StopCommand.Execute(null);
+ }
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(command), command, null);
+ }
+ }
+
+ private void MainModule_OnPinChangedEvent(int arg1, bool arg2)
+ {
+ var @event = _cameraSettings.GPIOCommands.FirstOrDefault(x => x.Pin == arg1 && x.OnHigh == arg2);
+ if (@event != null)
+ {
+ ProcessCommand(@event.Command);
+ }
+ }
private void EmitEvent(EProcessingEvent @event)
{
diff --git a/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs b/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs
index 9dedc8f..2bbb91e 100644
--- a/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs
+++ b/VisionBuilder.UI.IOCommander/Modules/IOCommanderModule.cs
@@ -12,28 +12,32 @@ namespace VisionBuilder.UI.IOCommander.Modules;
public class IOCommanderModule:IVisionBuilderModule
{
private readonly IOCommanderSettings _settings;
+ private readonly IIOCommanderFactory _factory;
private readonly IIOCommanderDebugViewService _debugViewService;
- private IOCommander? _ioCommander;
- public IOCommanderModule(IOCommanderSettings settings, IIOCommanderDebugViewService debugViewService)
+ private IIOCommander? _ioCommander;
+ public IOCommanderModule(IOCommanderSettings settings, IIOCommanderFactory factory, IIOCommanderDebugViewService debugViewService)
{
_settings = settings;
+ _factory = factory;
_debugViewService = debugViewService;
}
public void InitializeModule()
{
- if (!_settings.EmulationMode)
- {
- _ioCommander = new IOCommander(_settings.Port);
- _ioCommander.OnPinChanged += OnPinChanged;
- }
+ _ioCommander = _factory.Create();
+ _ioCommander.OnPinChanged += OnPinChanged;
- if(_settings.ShowDebugView)_debugViewService.ShowDebugView();
+ if (_settings.ShowDebugView)_debugViewService.ShowDebugView();
}
ConcurrentDictionary _pinStates = new ConcurrentDictionary();
+ public event Action? OnPinChangedEvent
+ {
+ add => _ioCommander!.OnPinChanged += value;
+ remove => _ioCommander!.OnPinChanged -= value;
+ }
private void OnPinChanged(int arg1, bool arg2)
{
_pinStates.TryAdd(arg1, arg2);
diff --git a/VisionBuilder.UI.IOCommander/Settings/IOCommanderSettings.cs b/VisionBuilder.UI.IOCommander/Settings/IOCommanderSettings.cs
index a8b807d..7424f59 100644
--- a/VisionBuilder.UI.IOCommander/Settings/IOCommanderSettings.cs
+++ b/VisionBuilder.UI.IOCommander/Settings/IOCommanderSettings.cs
@@ -8,7 +8,6 @@ public class IOCommanderSettings: ISettings
{
public IOCommanderCameraSettings[] Cameras { get; }
public int PulseLength { get; set; } = 100;
- public bool EmulationMode { get; set; } = true;
public bool ShowDebugView { get; set; } = false;
public string Port { get; set; }="COM3";
@@ -27,7 +26,6 @@ public class IOCommanderSettings: ISettings
{
settings.RegisterSimple(this, () => Port, "IOCommander", nameof(Port));
settings.RegisterSimple(this, () => PulseLength, "IOCommander", nameof(PulseLength));
- settings.RegisterSimple(this, () => EmulationMode, "IOCommander", nameof(EmulationMode));
settings.RegisterSimple(this, () => ShowDebugView, "IOCommander", nameof(ShowDebugView));
foreach (IOCommanderProcessingEvent @event in GlobalEvents)
diff --git a/VisionBuilder.UI.Windows.Test/Program.cs b/VisionBuilder.UI.Windows.Test/Program.cs
index ab793b2..329f0d6 100644
--- a/VisionBuilder.UI.Windows.Test/Program.cs
+++ b/VisionBuilder.UI.Windows.Test/Program.cs
@@ -43,6 +43,7 @@ namespace VisionBuilder.UI.Windows.Test
mainKernel
.UseIOCommander([CAMERA1])
.UseIOCommanderWindowsDebug()
+ .UseIOCommanderVirtualInput()
.UseConsole()
.UseWindowsServices();
diff --git a/VisionBuilder.UI.Windows/Components/SingleCameraControl.cs b/VisionBuilder.UI.Windows/Components/SingleCameraControl.cs
index ed33986..04ace7c 100644
--- a/VisionBuilder.UI.Windows/Components/SingleCameraControl.cs
+++ b/VisionBuilder.UI.Windows/Components/SingleCameraControl.cs
@@ -23,6 +23,12 @@ namespace VisionBuilder.UI.Windows.Components
this.stats1.SetViewModel(singleCameraVm.StatisticsVm);
SetBindings();
+ _singleCameraVm.PropertyChanged += SingleCameraVm_PropertyChanged;
+ }
+
+ private void SingleCameraVm_PropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+
}
private void SetBindings()