common/Hardware/Common.Hardware.Ports/SirtSerialPort.cs
2026-04-23 17:50:07 +02:00

139 lines
4.0 KiB
C#

namespace Common.Hardware.Ports
{
using System;
using System.Threading;
using System.Threading.Tasks;
public class SirtSerialPort : SerialPortBase
{
private CancellationTokenSource cancellationTokenSource;
private CancellationToken cancellationToken;
private Task listener;
private bool listening;
public SirtSerialPort(SerialPortSettings settings) : base(settings)
{
}
protected event Action<Byte[]> DataReceived;
public override void Close()
{
this.StopListening();
base.Close();
}
public override void EnsureConnected()
{
base.EnsureConnected();
if (this.listening)
{
this.StopListening();
}
this.StartListening();
}
public override void Open()
{
base.Open();
this.StartListening();
}
private void StartListening()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.cancellationToken = this.cancellationTokenSource.Token;
this.listener = Task.Factory.StartNew(asyncState =>
{
if (asyncState is SirtSerialPort sirtSerialPort)
{
sirtSerialPort.listening = true;
const Byte SIRT2PC = 0xFF;
const Byte LENINDEX = 8;
const Byte MINLEN = 12;
var buffer = new Byte[0];
while (!sirtSerialPort.cancellationToken.IsCancellationRequested)
{
var bytesIn = sirtSerialPort.Read();
var bytesInLength = bytesIn.Length;
var bufferLength = buffer.Length;
Array.Resize(ref buffer, bufferLength + bytesInLength);
Array.Copy(bytesIn, 0, buffer, bufferLength, bytesInLength);
var start = Array.IndexOf(buffer, SIRT2PC);
if (start < 0)
{
Array.Resize(ref buffer, 0);
continue;
}
bufferLength = buffer.Length;
var lengthIndex = start + LENINDEX;
if (lengthIndex >= bufferLength)
{
continue;
}
var dataLength = buffer[lengthIndex] + MINLEN;
var holeLength = start + dataLength;
if (holeLength > bufferLength)
{
continue;
}
var data = new Byte[dataLength];
Array.Copy(buffer, start, data, 0, dataLength);
var _buffer = new Byte[bufferLength - dataLength];
Array.Copy(buffer, holeLength, _buffer, 0, bufferLength - holeLength);
buffer = _buffer;
sirtSerialPort?.DataReceived(data);
}
}
}, this, this.cancellationToken)
.ContinueWith(task =>
{
if (task.AsyncState is SirtSerialPort sirtSerialPort)
{
if (task.Exception != null)
{
sirtSerialPort.LogMessage(task.Exception.ToString());
}
sirtSerialPort.listening = false;
sirtSerialPort.StopListening();
}
}, this.cancellationToken);
}
private void StopListening()
{
try
{
this.cancellationTokenSource?.Cancel();
}
catch (Exception e)
{
this.LogMessage(e.ToString());
}
Thread.Sleep(1);
}
}
}