139 lines
4.0 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|