From 28c4c7427f46f05e63b764010fc13f687f6df621 Mon Sep 17 00:00:00 2001 From: andrea <2404> Date: Wed, 24 Dec 2025 16:41:31 +0100 Subject: [PATCH] Aggiungere i file di progetto. --- OMControl.slnx | 3 + OMControl/Form1.Designer.cs | 59 +++++++++++++ OMControl/Form1.cs | 46 ++++++++++ OMControl/Form1.resx | 120 ++++++++++++++++++++++++++ OMControl/OMControl.csproj | 15 ++++ OMControl/Program.cs | 17 ++++ OMControl/Serial/SerialDeviceProbe.cs | 112 ++++++++++++++++++++++++ OMControl/Serial/SerialManager.cs | 53 ++++++++++++ OMControl/Serial/SerialPortWatcher.cs | 52 +++++++++++ 9 files changed, 477 insertions(+) create mode 100644 OMControl.slnx create mode 100644 OMControl/Form1.Designer.cs create mode 100644 OMControl/Form1.cs create mode 100644 OMControl/Form1.resx create mode 100644 OMControl/OMControl.csproj create mode 100644 OMControl/Program.cs create mode 100644 OMControl/Serial/SerialDeviceProbe.cs create mode 100644 OMControl/Serial/SerialManager.cs create mode 100644 OMControl/Serial/SerialPortWatcher.cs diff --git a/OMControl.slnx b/OMControl.slnx new file mode 100644 index 0000000..3f8367c --- /dev/null +++ b/OMControl.slnx @@ -0,0 +1,3 @@ + + + diff --git a/OMControl/Form1.Designer.cs b/OMControl/Form1.Designer.cs new file mode 100644 index 0000000..99bdfba --- /dev/null +++ b/OMControl/Form1.Designer.cs @@ -0,0 +1,59 @@ +namespace OMControl +{ + partial class Form1 + { + + + /// + /// 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() + { + listBoxPorts = new ListBox(); + SuspendLayout(); + // + // listBoxPorts + // + listBoxPorts.FormattingEnabled = true; + listBoxPorts.Location = new Point(196, 150); + listBoxPorts.Name = "listBoxPorts"; + listBoxPorts.Size = new Size(150, 104); + listBoxPorts.TabIndex = 0; + // + // Form1 + // + AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(800, 450); + Controls.Add(listBoxPorts); + Name = "Form1"; + Text = "Form1"; + ResumeLayout(false); + } + + #endregion + + private ListBox listBoxPorts; + } +} diff --git a/OMControl/Form1.cs b/OMControl/Form1.cs new file mode 100644 index 0000000..14c0678 --- /dev/null +++ b/OMControl/Form1.cs @@ -0,0 +1,46 @@ +using System.IO.Ports; + +namespace OMControl +{ + public partial class Form1 : Form + { + private SerialPortWatcher _watcher; + public Form1() + { + InitializeComponent(); + this.Load += Form1_Load; + + } + + + private void Form1_Load(object sender, EventArgs e) + { + listBoxPorts.Items.Clear(); + foreach (var p in SerialPort.GetPortNames()) + listBoxPorts.Items.Add(p); + + // start watcher + _watcher = new SerialPortWatcher(1000); + + _watcher.PortsAdded += ports => BeginInvoke(() => + { + foreach (var p in ports) + if (!listBoxPorts.Items.Contains(p)) + listBoxPorts.Items.Add(p); + }); + + _watcher.PortsRemoved += ports => BeginInvoke(() => + { + foreach (var p in ports) + listBoxPorts.Items.Remove(p); + }); + + _watcher.Start(); + } + protected override void OnFormClosing(FormClosingEventArgs e) + { + _watcher?.Dispose(); + base.OnFormClosing(e); + } + } +} diff --git a/OMControl/Form1.resx b/OMControl/Form1.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/OMControl/Form1.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/OMControl/OMControl.csproj b/OMControl/OMControl.csproj new file mode 100644 index 0000000..80c58a3 --- /dev/null +++ b/OMControl/OMControl.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net10.0-windows + enable + true + enable + + + + + + + \ No newline at end of file diff --git a/OMControl/Program.cs b/OMControl/Program.cs new file mode 100644 index 0000000..a006931 --- /dev/null +++ b/OMControl/Program.cs @@ -0,0 +1,17 @@ +namespace OMControl +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } + } +} \ No newline at end of file diff --git a/OMControl/Serial/SerialDeviceProbe.cs b/OMControl/Serial/SerialDeviceProbe.cs new file mode 100644 index 0000000..77cfaaa --- /dev/null +++ b/OMControl/Serial/SerialDeviceProbe.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +public sealed class SerialDeviceProbe +{ + public record ProbeResult(string Port, bool Success, string? DeviceId, byte[]? RawResponse, string? Error); + + // Define known signatures here + // Example: response contains ASCII "DEV:XYZ" or starts with 0xAA 0x55 etc. + private readonly List<(string Name, Func Match)> _signatures = new(); + + public SerialDeviceProbe AddSignature(string name, Func match) + { + _signatures.Add((name, match)); + return this; + } + + public async Task ProbeAsync( + string portName, + int baudRate, + byte[] probeBytes, + int readTimeoutMs = 250, + int writeTimeoutMs = 250, + int settleDelayMs = 80, + int maxReadBytes = 256, + CancellationToken ct = default) + { + try + { + return await Task.Run(() => + { + ct.ThrowIfCancellationRequested(); + + using var sp = new SerialPort(portName, baudRate) + { + ReadTimeout = readTimeoutMs, + WriteTimeout = writeTimeoutMs, + Encoding = Encoding.ASCII, + DtrEnable = true, // often needed for Arduino-like boards + RtsEnable = true + }; + + sp.Open(); + + // Some devices reboot on open (Arduino). Give them a moment. + Thread.Sleep(settleDelayMs); + + sp.DiscardInBuffer(); + sp.DiscardOutBuffer(); + + sp.Write(probeBytes, 0, probeBytes.Length); + + // Read available bytes up to timeout + var buffer = new List(maxReadBytes); + var start = Environment.TickCount; + + while (buffer.Count < maxReadBytes && Environment.TickCount - start < readTimeoutMs) + { + ct.ThrowIfCancellationRequested(); + + try + { + int b = sp.ReadByte(); // blocks until byte or timeout + if (b >= 0) buffer.Add((byte)b); + + // Optional: break early if you know response length or terminator + // e.g. if buffer ends with '\n' + if (buffer.Count >= 2 && buffer[^1] == (byte)'\n') break; + } + catch (TimeoutException) + { + break; + } + } + + var resp = buffer.ToArray(); + if (resp.Length == 0) + return new ProbeResult(portName, false, null, resp, "No response"); + + // Identify by signature + foreach (var sig in _signatures) + { + if (sig.Match(resp)) + return new ProbeResult(portName, true, sig.Name, resp, null); + } + + // Unknown but responded + return new ProbeResult(portName, true, "Unknown", resp, null); + + }, ct); + } + catch (Exception ex) + { + return new ProbeResult(portName, false, null, null, ex.Message); + } + } + + public async Task ProbeAllAsync( + IEnumerable ports, + int baudRate, + byte[] probeBytes, + CancellationToken ct = default) + { + var tasks = ports.Select(p => ProbeAsync(p, baudRate, probeBytes, ct: ct)); + return await Task.WhenAll(tasks); + } +} diff --git a/OMControl/Serial/SerialManager.cs b/OMControl/Serial/SerialManager.cs new file mode 100644 index 0000000..eaff1fd --- /dev/null +++ b/OMControl/Serial/SerialManager.cs @@ -0,0 +1,53 @@ +using System; +using System.IO.Ports; +using System.Text; + +public class SerialManager : IDisposable +{ + private SerialPort _serialPort; + + public event Action? DataReceived; + + public bool IsOpen => _serialPort?.IsOpen ?? false; + + public SerialManager(string portName, int baudRate) + { + _serialPort = new SerialPort(portName, baudRate) + { + Encoding = Encoding.ASCII, + NewLine = "\n" + }; + + _serialPort.DataReceived += OnDataReceived; + } + + public void Open() + { + if (!_serialPort.IsOpen) + _serialPort.Open(); + } + + public void Close() + { + if (_serialPort.IsOpen) + _serialPort.Close(); + } + + public void Send(string data) + { + if (_serialPort.IsOpen) + _serialPort.WriteLine(data); + } + + private void OnDataReceived(object sender, SerialDataReceivedEventArgs e) + { + string data = _serialPort.ReadLine(); + DataReceived?.Invoke(data); + } + + public void Dispose() + { + Close(); + _serialPort.Dispose(); + } +} diff --git a/OMControl/Serial/SerialPortWatcher.cs b/OMControl/Serial/SerialPortWatcher.cs new file mode 100644 index 0000000..de73894 --- /dev/null +++ b/OMControl/Serial/SerialPortWatcher.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Timers; + +public sealed class SerialPortWatcher : IDisposable +{ + private readonly System.Timers.Timer _timer; + private HashSet _last = new(StringComparer.OrdinalIgnoreCase); + + public event Action? PortsAdded; + public event Action? PortsRemoved; + + public SerialPortWatcher(double intervalMs = 1000) + { + _timer = new System.Timers.Timer(intervalMs); + _timer.Elapsed += (_, _) => Tick(); + _timer.AutoReset = true; + } + + public void Start() + { + _last = GetPorts(); + _timer.Start(); + } + + public void Stop() => _timer.Stop(); + + private void Tick() + { + var current = GetPorts(); + + var added = current.Except(_last).ToArray(); + var removed = _last.Except(current).ToArray(); + + if (added.Length > 0) PortsAdded?.Invoke(added); + if (removed.Length > 0) PortsRemoved?.Invoke(removed); + + _last = current; + } + + private static HashSet GetPorts() + => new HashSet(SerialPort.GetPortNames(), StringComparer.OrdinalIgnoreCase); + + public void Dispose() + { + _timer.Stop(); + _timer.Dispose(); + } +} +