namespace Common.Hardware.SIRT { using System; using System.Collections.Concurrent; using System.Timers; public partial class SIRTTask { public readonly ConcurrentStack responses; public readonly SIRTMessage request; protected readonly Timer timeoutTimer; public SIRTTask(int frequency, int timeout = 5_000) { this.Timeout = timeout; this.Frequency = frequency; this.responses = new ConcurrentStack(); this.request = new SIRTMessage(); this.timeoutTimer = new Timer { AutoReset = false, Enabled = false, Interval = this.Timeout }; this.timeoutTimer.Elapsed += this.OnTimeout; } public event Action Completed; public event Action Cancelled; public event Action Timeouted; public event Action Updated; public byte Cmd { get => this.request.Cmd; set => this.request.Cmd = value; } public byte P1 { get => this.request.P1; set => this.request.P1 = value; } public byte P2 { get => this.request.P2; set => this.request.P2 = value; } public uint RequestAddress { get => this.request.Address; set { this.request.Address = value; this.ResponseAddress = value; } } public uint ResponseAddress { get; set; } public byte[] Data { get => this.request.Data; set => this.request.Data = value; } public int Timeout { get; } public int Frequency { get; } public SIRTTaskState State { get; protected set; } public void PushResponse(SIRTMessage response) { if (this.State == SIRTTaskState.Cancelled) { return; } this.responses.Push(response); if (response.Length >= 13) { var responseAddress = response.Address; if (responseAddress != this.RequestAddress) { var requestAddress = this.RequestAddress; this.RequestAddress = this.ResponseAddress; this.ResponseAddress = requestAddress; this.NotifyUpdated(); } } this.ProcessResponse(response); } public virtual byte[] ToByteArray() => this.request.ToByteArray(); public override string ToString() => BitConverter.ToString(this.ToByteArray()); public virtual void UpdateFrom(SIRTTask task) { this.P1 = task.P1; this.P2 = task.P2; this.RequestAddress = task.RequestAddress; this.ResponseAddress = task.ResponseAddress; } protected void NotifyCancelled() => this.Cancelled?.Invoke(this); protected void NotifyCompleted() => this.Completed?.Invoke(this); protected void NotifyTimeouted() => this.Timeouted?.Invoke(this); protected void NotifyUpdated() => this.Updated?.Invoke(this); protected virtual void OnTimeout(object sender, ElapsedEventArgs e) { this.State = SIRTTaskState.Cancelled; this.NotifyCancelled(); } protected virtual void ProcessResponse(SIRTMessage response) { if (this.State == SIRTTaskState.Running) { if (response.Cmd == SIRTMessage.ACKNANSW || (response.Data.Length > 0 && response.Data[0] == SIRTMessage.SEMI)) { this.State = SIRTTaskState.Completed; } } if (this.State == SIRTTaskState.Completed) { this.timeoutTimer.Stop(); this.NotifyCompleted(); } else if (this.State == SIRTTaskState.Cancelled) { this.timeoutTimer.Stop(); this.NotifyCancelled(); } } } }