Files
laatzen/Common/Hardware/Common.Hardware.SIRT/SIRTStream.cs
T

188 lines
5.5 KiB
C#

namespace Common.Hardware.SIRT
{
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Runtime.CompilerServices;
using System.Threading;
public sealed class SIRTStream
{
private readonly SerialPort serialPort;
public SIRTStream(string portName)
=> this.serialPort = new SerialPort(portName, 112500, Parity.None, 8, StopBits.One);
public event Action<SIRTStream> Connected;
public event Action<SIRTStream> Disconnected;
public event Action<object> StateLogging;
public bool IsOpen => this.serialPort.IsOpen;
public void Close()
{
var disposeEvent = new ManualResetEventSlim();
void SerialPort_Disposed(object sender, EventArgs args)
{
disposeEvent.Set();
}
this.serialPort.Disposed += SerialPort_Disposed;
try
{
this.serialPort.Close();
disposeEvent.Wait(5000);
}
catch (Exception e)
{
this.Invoke_StateLogging(e);
}
this.serialPort.Disposed -= SerialPort_Disposed;
this.Disconnected?.Invoke(this);
}
public void Open()
{
this.Close();
try
{
this.serialPort.Open();
this.Connected?.Invoke(this);
}
catch (Exception e)
{
this.Invoke_StateLogging(e);
this.Disconnected?.Invoke(this);
}
}
public IEnumerable<byte[]> Read()
{
var receiveEvent = new ManualResetEventSlim();
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs args)
{
if (args.EventType == SerialData.Chars)
{
receiveEvent.Set();
}
}
this.serialPort.DataReceived += SerialPort_DataReceived;
// read variables
var receiveBuffer = new List<byte>();
var receiveBufferCount = default(int);
var readBuffer = default(byte[]);
var readLength = default(int);
// message variables
var startIndex = default(int);
var lengthIndex = default(int);
var length = default(int);
var endIndex = default(int);
var messageLength = default(int);
var message = default(byte[]);
while (this.serialPort.IsOpen)
{
if (!receiveEvent.IsSet)
{
receiveEvent.Wait();
receiveEvent.Reset();
}
try
{
readBuffer = new byte[this.serialPort.ReadBufferSize];
readLength = this.serialPort.Read(readBuffer, 0, readBuffer.Length);
Array.Resize(ref readBuffer, readLength);
receiveBuffer.AddRange(readBuffer);
}
catch (Exception e)
{
this.Invoke_StateLogging(e);
}
receiveBufferCount = receiveBuffer.Count;
while (receiveBufferCount > 0)
{
if (startIndex < 0)
{
startIndex = 0;
}
startIndex = receiveBuffer.IndexOf(SIRTConstants.SIRT_PC, startIndex);
// when no start byte found clear and break
if (startIndex < 0)
{
receiveBuffer.Clear();
break;
}
lengthIndex = startIndex + SIRTConstants.LEN_IX;
// when not enough bytes for the length just break
if (lengthIndex >= receiveBufferCount)
{
break;
}
length = receiveBuffer[lengthIndex];
endIndex = lengthIndex + length + 3;
// when not enough bytes for the end just break
if (endIndex >= receiveBufferCount)
{
break;
}
// when message end not 0x16 try again with next start index
if (receiveBuffer[endIndex] != SIRTConstants.MSG_END)
{
startIndex++;
continue;
}
messageLength = endIndex - startIndex + 1;
message = new byte[messageLength];
receiveBuffer.CopyTo(startIndex, message, 0, messageLength);
receiveBuffer.RemoveRange(0, endIndex + 1);
yield return message;
receiveBufferCount = receiveBuffer.Count;
}
}
this.serialPort.DataReceived -= SerialPort_DataReceived;
}
public void Write(byte[] bytes)
{
try
{
this.serialPort.Write(bytes, 0, bytes.Length);
}
catch (Exception e)
{
this.Invoke_StateLogging(e);
}
}
private void Invoke_StateLogging(object state, [CallerMemberName] string member = "")
=> this.StateLogging?.Invoke($"{nameof(SIRTStream)}|{member}|{this.serialPort.PortName}|{state}");
}
}