You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.6 KiB
100 lines
3.6 KiB
using Common.Logging;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using MultiTerm.Protocols.Types;
|
|
|
|
namespace MultiTerm.Protocols;
|
|
|
|
public abstract class CommunicationProtocol : ICommunicationProtocol
|
|
{
|
|
protected ILogger logger;
|
|
private CancellationTokenSource cancellationTokenSource;
|
|
private Thread? readingThread;
|
|
|
|
public event EventHandler<ReceivedDataEventArgs>? ReceivedDataEvent;
|
|
public event EventHandler<SentDataEventArgs>? SentDataEvent;
|
|
|
|
public abstract ProtocolType ProtocolType { get; }
|
|
|
|
public CommunicationProtocol(ILogger logger)
|
|
{
|
|
// initialize other
|
|
this.cancellationTokenSource = new CancellationTokenSource();
|
|
this.logger = logger;
|
|
}
|
|
|
|
/// <summary>
|
|
/// To be called when data was received from the connected device.
|
|
/// </summary>
|
|
/// <param name="e"><see cref="ReceivedDataEventArgs"/></param>
|
|
protected void OnReceivedData(ReceivedDataEventArgs e) { this.ReceivedDataEvent?.Invoke(this, e); }
|
|
|
|
/// <summary>
|
|
/// To be called when data was sent to the connected device.
|
|
/// </summary>
|
|
/// <param name="e"><see cref="SentDataEventArgs"/></param>
|
|
protected void OnSentData(SentDataEventArgs e) { this.SentDataEvent?.Invoke(this, e); }
|
|
|
|
/// <summary>
|
|
/// Allows to send bytes using the implemented protocol.
|
|
/// </summary>
|
|
/// <param name="bytes">data as bytes</param>
|
|
protected abstract void InternalSendBytes(byte[] bytes);
|
|
|
|
public void SendBytes(byte[] bytes)
|
|
{
|
|
this.InternalSendBytes(bytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows to connect to the selected device using the implemented protocol.
|
|
/// </summary>
|
|
/// <param name="settings">protocol settings required to connect</param>
|
|
/// <returns>true on success</returns>
|
|
protected abstract bool InternalConnect(IProtocolSettings settings);
|
|
|
|
/// <summary>
|
|
/// Reads from the connected device in an endless loop.
|
|
/// The endless loop must be ended when the <paramref name="ct"/> has <see cref="CancellationToken.IsCancellationRequested"/> set.
|
|
/// </summary>
|
|
/// <param name="ct">cancellation token</param>
|
|
protected abstract void InternalRead(CancellationToken ct);
|
|
|
|
public void Connect(IProtocolSettings settings)
|
|
{
|
|
// check if settings are valid, cancel if not
|
|
if (settings.AreValid() == false)
|
|
{
|
|
this.logger.LogError($"'{nameof(Connect)}()' failed since the provided protocol settings are invalid", nameof(CommunicationProtocol));
|
|
return;
|
|
}
|
|
|
|
// try connecting if serttings are valid
|
|
if (this.InternalConnect(settings))
|
|
{
|
|
// renew token source
|
|
this.cancellationTokenSource = new CancellationTokenSource();
|
|
// start internal reading thread
|
|
this.readingThread = new Thread(() => this.InternalRead(this.cancellationTokenSource.Token));
|
|
this.readingThread.Start();
|
|
}
|
|
else
|
|
{
|
|
this.logger.LogWarn($"'{nameof(Connect)}()' failed to connect to protocol, did not start reading thread.", nameof(CommunicationProtocol));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows to disconnect from the connected device.
|
|
/// </summary>
|
|
protected abstract void InternalDisconnect();
|
|
public void Disconnect()
|
|
{
|
|
// if reading thread exists and is running => cancel it and wait
|
|
if (this.readingThread != null && this.readingThread.IsAlive)
|
|
{
|
|
this.cancellationTokenSource.Cancel();
|
|
this.readingThread.Join();
|
|
}
|
|
this.InternalDisconnect();
|
|
}
|
|
}
|
|
|