using Common.Logging; namespace MultiTerm.Protocols; public abstract class CommunicationProtocol : ICommunicationProtocol { public string NewlineSequenceOnSend { get; set; } public string NewlineOnReceivedSequence { get; set; } public ProtocolConnectionSettings? ConnectionSettings { get; set; } protected ILogger logger; private CancellationTokenSource cancellationTokenSource; private Thread? readingThread; public event EventHandler? ReceivedDataEvent; public event EventHandler? SentDataEvent; public CommunicationProtocol(ILogger logger) { // initialize with empty string, must be correctly initalized by factory this.NewlineSequenceOnSend = string.Empty; this.NewlineOnReceivedSequence = string.Empty; // 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. /// /// true on success protected abstract bool InternalConnect(); /// /// 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() { if (this.InternalConnect()) { // 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(); } }