Files
laatzen/Common/Hardware/Common.Hardware.SIRT/SIRTTask.cs
T

206 lines
5.7 KiB
C#

namespace Common.Hardware.SIRT
{
using Common.Hardware.SIRT.Parameters;
using System;
using System.Collections.Concurrent;
using System.Timers;
public class SIRTTask
{
protected readonly Timer timer;
protected readonly SIRTMessage request;
protected readonly ConcurrentStack<SIRTMessage> responses;
/// <param name="timeout">The tiemout in milliseconds, after the task will be cancelled.</param>
public SIRTTask(int timeout = 5_000)
{
this.Timeout = timeout;
this.State = SIRTTaskState.Pending;
this.timer = new Timer();
this.request = new SIRTMessage();
this.responses = new ConcurrentStack<SIRTMessage>();
// Cancel after 10 seconds
this.timer.AutoReset = false;
this.timer.Enabled = false;
this.timer.Interval = this.Timeout;
this.timer.Elapsed += this.Timer_Elapsed;
}
public event Action<SIRTTask> Completed;
public event Action<SIRTTask> Cancelled;
public event Action<SIRTTask> Timeouted;
public event Action<SIRTTask> 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;
}
/// <summary>
/// The tiemout in milliseconds, after the task will be cancelled.
/// </summary>
public int Timeout { get; }
public int Frequency { get; set; }
public int Index { get; internal set; }
public SIRTTaskState State { get; protected set; }
public virtual void BeginReceiveMessage(SIRTMessage response)
{
this.responses.Push(response);
if (this.State == SIRTTaskState.Running)
{
if (response.Cmd == SIRTMessage.FROMAIR && response?.Data?[0] == SIRTMessage.SEMI)
{
this.State = SIRTTaskState.Completed;
}
else if (response.Cmd == SIRTMessage.ACKNANSW)
{
this.State = SIRTTaskState.Completed;
}
}
this.EndReceiveMessage(response);
}
public virtual void SetRunning()
{
this.State = SIRTTaskState.Running;
this.timer.Start();
}
public virtual byte[] ToByteArray()
=> this.request.ToByteArray();
public override string ToString()
=> BitConverter.ToString(this.ToByteArray());
protected void Cancel()
{
this.State = SIRTTaskState.Cancelled;
this.Cancelled?.Invoke(this);
}
protected virtual void EndReceiveMessage(SIRTMessage _)
{
if (this.State == SIRTTaskState.Completed)
{
this.timer.Stop();
this.Completed?.Invoke(this);
}
else if (this.State == SIRTTaskState.Cancelled)
{
this.timer.Stop();
this.Cancelled?.Invoke(this);
}
}
protected void NotifyUpdated()
=> this.Updated?.Invoke(this);
protected virtual void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
this.State = SIRTTaskState.Pending;
this.Timeouted?.Invoke(this);
}
public static implicit operator byte[](SIRTTask task)
=> task.ToByteArray();
public static implicit operator SIRTMessage(SIRTTask task)
=> task.request;
internal static readonly AnswerTask ActivateSIRT = new AnswerTask
{
Cmd = SIRTMessage.W_REG,
RequestAddress = 0x20000000,
P2 = 0x05,
Data = new byte[]
{
new SirtOperating { /* default */ },
new BluetoothOperating { BtOff = true },
new RFModuleOperating { RfOff = true },
new RFModuleOperating { OpMode = OperatingModes.ReceiveF1TransmitSensusRFF3 },
new PamTimeout { Minutes = 1 }
}
};
internal static readonly AnswerTask IdentifySIRT = new AnswerTask
{
Cmd = SIRTMessage.R_REG,
RequestAddress = 0x11001820,
P2 = 0x08
};
internal static readonly AnswerTask ReadPamPool = new AnswerTask
{
Cmd = SIRTMessage.R_PAM,
RequestAddress = 0xFFFFFFFF
};
internal static AnswerTask DeleteFromPamPool(uint address) => new AnswerTask
{
Cmd = SIRTMessage.W_PAM,
P1 = new P811 { DelPamAdr = true },
RequestAddress = address
};
}
public class AnswerTask : SIRTTask
{
public AnswerTask(int timeout = 3000) : base(timeout)
{
}
public byte[] Last { get; private set; }
public override void BeginReceiveMessage(SIRTMessage response)
{
base.BeginReceiveMessage(response);
this.Last = response.Data ?? new byte[] { };
}
}
}