namespace Common.Hardware.Ports { using System; using System.Collections.Concurrent; using System.IO.Ports; using System.Threading; public abstract class SerialPortBase { private static readonly ConcurrentDictionary serialPorts = new ConcurrentDictionary(); private readonly SerialPortSettings settings; public SerialPortBase(SerialPortSettings settings) { this.settings = settings; this.PortName = settings.PortName; } public event Action Logging; public String PortName { get; } public Int32 ReadSize { get; private set; } public virtual void Close() { try { this.ReadSize = default(Int32); if (serialPorts.TryRemove(this.PortName, out var serialPort)) { if (serialPort != null) { serialPort.Close(); serialPort.Dispose(); serialPort = null; this.LogMessage($"Disconnected: {this}"); } else { this.LogMessage($"{this.PortName} is null!"); } } } catch (Exception e) { this.LogMessage(e.ToString()); } } public virtual void EnsureConnected() { if (!this.TryGetSerialPort(out var serialPort)) { this.Open(); } } public virtual void Open() { this.Close(); try { this.ReadSize = default(Int32); var serialPort = new System.IO.Ports.SerialPort { BaudRate = this.settings.BaudRate, DataBits = this.settings.DataBits, Parity = this.settings.Parity, PortName = this.settings.PortName, StopBits = this.settings.StopBits }; if (serialPorts.TryAdd(serialPort.PortName, serialPort)) { serialPort.Open(); if (serialPort.IsOpen) { this.ReadSize = serialPort.ReadBufferSize; } this.LogMessage($"Connected: {this}"); } else { this.LogMessage($"{this.PortName} can not be addedd!"); } } catch (Exception e) { this.LogMessage(e.ToString()); } } public override String ToString() => serialPorts.TryGetValue(this.PortName, out var serialPort) ? $"{serialPort.PortName}, " + $"{serialPort.BaudRate}, " + $"{serialPort.DataBits}, " + $"{serialPort.Parity}, " + $"{serialPort.StopBits}" : $"{this.settings.PortName}, " + $"{this.settings.BaudRate}, " + $"{this.settings.DataBits}, " + $"{this.settings.Parity}, " + $"{this.settings.StopBits}"; public virtual Byte[] Write(params Byte[] data) { this.Write(data, 0, data.Length); return data; } protected void LogMessage(String message) => this.Logging?.Invoke(message); protected Byte[] Read(Int32 sleep = 1) { Thread.Sleep(sleep); var bytes = new Byte[0]; if (this.TryGetSerialPort(out var serialPort)) { try { var buffer = new Byte[this.ReadSize]; var length = serialPort.Read(buffer, 0, this.ReadSize); Array.Resize(ref bytes, length); Array.Copy(buffer, 0, bytes, 0, length); } catch (Exception e) { this.LogMessage(e.ToString()); } } else { this.LogMessage($"{this.PortName} dose not exists!"); } return bytes; } protected void Write(Byte[] bytes, Int32 start, Int32 length, Int32 sleep = 1) { if (this.TryGetSerialPort(out var serialPort)) { try { serialPort.Write(bytes, start, length); } catch (Exception e) { this.LogMessage(e.ToString()); } } else { this.LogMessage($"{this.PortName} dose not exists!"); } Thread.Sleep(sleep); } private Boolean TryGetSerialPort(out System.IO.Ports.SerialPort serialPort) => serialPorts.TryGetValue(this.PortName, out serialPort) && serialPort?.IsOpen == true; } }