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? ReceivedDataEvent; public event EventHandler? SentDataEvent; public abstract ProtocolType ProtocolType { get; } public CommunicationProtocol(ILogger logger) { // initialize other this.cancellationTokenSource = new CancellationTokenSource(); this.logger = logger; } /// /// To be called when data was received from the connected device. /// /// protected void OnReceivedData(ReceivedDataEventArgs e) { this.ReceivedDataEvent?.Invoke(this, e); } /// /// To be called when data was sent to the connected device. /// /// protected void OnSentData(SentDataEventArgs e) { this.SentDataEvent?.Invoke(this, e); } /// /// Allows to send bytes using the implemented protocol. /// /// data as bytes protected abstract void InternalSendBytes(byte[] bytes); public void SendBytes(byte[] bytes) { this.InternalSendBytes(bytes); } /// /// Allows to connect to the selected device using the implemented protocol. /// /// protocol settings required to connect /// true on success protected abstract bool InternalConnect(IProtocolSettings settings); /// /// Reads from the connected device in an endless loop. /// The endless loop must be ended when the has set. /// /// cancellation token 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)); } } /// /// Allows to disconnect from the connected device. /// 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(); } }