188 lines
5.5 KiB
C#
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}");
|
|
}
|
|
}
|