io commander

This commit is contained in:
meelstorm
2025-07-19 15:57:59 +02:00
parent 40d74d6da6
commit cd70088d9a
46 changed files with 2198 additions and 28 deletions

View File

@@ -0,0 +1,150 @@
using Inspectron.Settings;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using Inspectron.Settings.Attributes;
using VisionBuilder.UI.Common;
namespace VisionBuilder.UI.IOCommander.Settings
{
public class IOCommanderCameraSettings:ISettings
{
public string CameraName { get; }
public List<IOCommanderProcessingEvent> ProcessingEvents { get; set; } = [
new (EProcessingEvent.SessionStarted),
new (EProcessingEvent.SessionEnded),
new (EProcessingEvent.ErrorOccurred),
new (EProcessingEvent.GoodOccured),
];
[SettingDescription(@"
Overrides pin values during test mode.
")]
public List<IOCommanderPinAction> TestModeOverride { get; set; } = new List<IOCommanderPinAction>();
public List<IOCommanderCommand> GPIOCommands { get; set; } = new List<IOCommanderCommand>();
public IOCommanderCameraSettings(string cameraName)
{
CameraName = cameraName;
}
public void RegisterSettings(InspectronSettings settings)
{
foreach (var processingEvent in ProcessingEvents)
{
settings.RegisterSimple(processingEvent, () => processingEvent.Actions, CameraName + "/IOCommander/Outputs/"+processingEvent.Event.ToString(), nameof(processingEvent.Actions));
}
settings.RegisterSimple(this, () => TestModeOverride, CameraName + "/IOCommander/Outputs/" + nameof(TestModeOverride), nameof(TestModeOverride));
settings.RegisterSimple(this, () => GPIOCommands, CameraName + "/IOCommander/Inputs", nameof(GPIOCommands));
}
}
public class IOCommanderCommandListConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string stringValue)
{
// Check if we're converting to a single IOCommanderCommand
if (context?.PropertyDescriptor?.PropertyType == typeof(IOCommanderCommand))
{
return ConvertFromString(context, culture, stringValue);
}
// Otherwise, convert to a list of IOCommanderCommand
var commands = new List<IOCommanderCommand>();
if (!string.IsNullOrEmpty(stringValue))
{
var lines = stringValue.Split('\n', StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var command = ConvertFromString(context, culture, line.Trim());
if (command != null)
commands.Add(command);
}
}
return commands;
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
// Handle single IOCommanderCommand
if (value is IOCommanderCommand command)
{
return ConvertToString(context, culture, command);
}
// Handle list of IOCommanderCommand
if (value is List<IOCommanderCommand> commands)
{
var lines = commands.Select(c =>
ConvertToString(context, culture, c)
).Where(line => !string.IsNullOrEmpty(line));
return string.Join("\n", lines);
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
/// <summary>
/// Convert a single string to IOCommanderCommand
/// </summary>
private IOCommanderCommand ConvertFromString(ITypeDescriptorContext context, CultureInfo culture, string stringValue)
{
if (string.IsNullOrEmpty(stringValue))
return null;
var parts = stringValue.Split(',');
if (parts.Length == 3)
{
if (int.TryParse(parts[0], out int pin) &&
bool.TryParse(parts[1], out bool onHigh) &&
Enum.TryParse<EGPIOCommand>(parts[2], out EGPIOCommand command))
{
return new IOCommanderCommand
{
Pin = pin,
OnHigh = onHigh,
Command = command
};
}
}
return null;
}
/// <summary>
/// Convert a single IOCommanderCommand to string
/// </summary>
private string ConvertToString(ITypeDescriptorContext context, CultureInfo culture, IOCommanderCommand command)
{
if (command == null)
return null;
return $"{command.Pin},{command.OnHigh},{command.Command}";
}
}
}

View File

@@ -0,0 +1,38 @@
using Inspectron.Settings;
using Inspectron.Settings.Attributes;
using VisionBuilder.UI.Common;
namespace VisionBuilder.UI.IOCommander.Settings;
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";
public List<IOCommanderProcessingEvent> GlobalEvents { get; set; } =
[
new(EProcessingEvent.ProgramStarted),
new(EProcessingEvent.ProgramEnded),
];
public IOCommanderSettings(IOCommanderCameraSettings[] cameras)
{
Cameras = cameras;
}
public void RegisterSettings(InspectronSettings settings)
{
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)
{
settings.RegisterSimple(@event, () => @event.Actions, "IOCommander/Global outputs/" + @event.Event.ToString(), nameof(@event.Actions));
}
}
}