using System.IO.Ports; using InnovEnergy.Lib.Protocols.Modbus.Protocol; namespace InnovEnergy.Lib.Protocols.Modbus.Connections; public class ModbusSerialConnection : ModbusConnection { private String PortName { get; } private Int32 BaudRate { get; } private Parity Parity { get; } private Int32 DataBits { get; } private StopBits StopBits { get; } private Int32 TimeoutMs { get; } private Byte[] Buffer { get; } = new Byte[1024]; private SerialPort? _SerialPort; public ModbusSerialConnection(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, TimeSpan timeout) { PortName = portName; BaudRate = baudRate; Parity = parity; DataBits = dataBits; StopBits = stopBits; TimeoutMs = (Int32) timeout.TotalMilliseconds; } public override IReadOnlyList Receive(UInt16 bytesToRead) { var bytesReceived = 0; var serialPort = SerialPort(); do { var received = serialPort.Read(Buffer, bytesReceived, Buffer.Length - bytesReceived); if (received < 0) throw new NotConnectedException("Serial Connection has been closed"); bytesReceived += received; } while (bytesReceived < bytesToRead); return new ArraySegment(Buffer, 0, bytesToRead); } public override void Transmit(IEnumerable data) { var array = data.ToArray(); SerialPort().Write(array, 0, array.Length); } public override void Open() => SerialPort(); private SerialPort SerialPort() { if (_SerialPort == null) { _SerialPort = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits) { ReadTimeout = TimeoutMs, WriteTimeout = TimeoutMs}; _SerialPort.Open(); } return _SerialPort; } public override void Close() { if (_SerialPort != null) { try { _SerialPort.Close(); _SerialPort?.Dispose(); } catch (Exception) { // ignored } } _SerialPort = null; } }