321 lines
9.1 KiB
C#
321 lines
9.1 KiB
C#
namespace Common.Hardware.SIRT.Tasks
|
|
{
|
|
using Common.Hardware.SIRT.Parameters;
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
public class WritePamTask : SIRTTask
|
|
{
|
|
private event Action<SIRTMessage> AKNReceived;
|
|
private event Action<SIRTMessage> BUPReceived;
|
|
private event Action<SIRTMessage> LATReceived;
|
|
private event Action<SIRTMessage> DEBUGReceived;
|
|
private event Action<SIRTMessage> SEMIReceived;
|
|
private event Action<SIRTMessage> UnknownReceived;
|
|
|
|
protected P811 p811;
|
|
protected bool latReceived;
|
|
protected bool debugReceived;
|
|
|
|
public WritePamTask()
|
|
{
|
|
this.p811 = this.request.P1;
|
|
this.request.Command = SIRTConstants.W_PAM;
|
|
this.MessageSent += this.OnMessageSent;
|
|
this.AKNReceived += this.OnAKNReceived;
|
|
this.BUPReceived += this.OnBUPReceived;
|
|
this.LATReceived += this.OnLATReceived;
|
|
this.DEBUGReceived += this.OnDEBUGReceived;
|
|
this.SEMIReceived += this.OnSEMIReceived;
|
|
this.UnknownReceived += this.OnUnknownReceived;
|
|
this.RequireLAT = true;
|
|
this.PamStatusIX = 11;
|
|
this.DebugLength = 52;
|
|
this.SemiLength = 91;
|
|
}
|
|
|
|
public event Action<SIRTMessage> MessageSent;
|
|
public event Action<SIRTMessage> MessageReceived;
|
|
|
|
public bool RequireLAT { get; set; }
|
|
|
|
public bool RequireDEBUG { get; set; }
|
|
|
|
public bool IsEncrypted { get; set; }
|
|
|
|
public byte[] EncryptionKeyI { get; set; }
|
|
|
|
private byte[] encryptionKeyII;
|
|
public byte[] EncryptionKeyII
|
|
{
|
|
get => this.encryptionKeyII;
|
|
set
|
|
{
|
|
this.encryptionKeyII = value;
|
|
this.IsEncrypted = true;
|
|
}
|
|
}
|
|
|
|
public bool WakeUpModul
|
|
{
|
|
get => this.p811.WakeUpModul;
|
|
set => this.SetP811(x => x.WakeUpModul = value);
|
|
}
|
|
|
|
public bool WakeUpCmd
|
|
{
|
|
get => this.p811.WakeUpCmd;
|
|
set => this.SetP811(x => x.WakeUpCmd = value);
|
|
}
|
|
|
|
public bool IgnoreTimeout
|
|
{
|
|
get => this.p811.IgnoreTimeout;
|
|
set => this.SetP811(x => x.IgnoreTimeout = value);
|
|
}
|
|
|
|
public bool DelPamSemi
|
|
{
|
|
get => this.p811.DelPamSemi;
|
|
set => this.SetP811(x => x.DelPamSemi = value);
|
|
}
|
|
|
|
public bool DelPamTx
|
|
{
|
|
get => this.p811.DelPamTx;
|
|
set => this.SetP811(x => x.DelPamTx = value);
|
|
}
|
|
|
|
public bool DelPamAdr
|
|
{
|
|
get => this.p811.DelPamAdr;
|
|
set => this.SetP811(x => x.DelPamAdr = value);
|
|
}
|
|
|
|
public bool DelPamAll
|
|
{
|
|
get => this.p811.DelPamAll;
|
|
set => this.SetP811(x => x.DelPamAll = value);
|
|
}
|
|
|
|
public byte[] Data
|
|
{
|
|
get => this.request.Payload;
|
|
set => this.request.Payload = value;
|
|
}
|
|
|
|
public byte DebugLength { get; set; }
|
|
|
|
public byte SemiLength { get; set; }
|
|
|
|
public byte PamStatusIX { get; set; }
|
|
|
|
public bool AnyTelegramReceived { get; set; }
|
|
|
|
public Queue<SIRTMessage> MessageQueue { get; set; } = new Queue<SIRTMessage>();
|
|
|
|
public override void Receive(SIRTMessage response)
|
|
{
|
|
if (this.UseEncryption(response))
|
|
{
|
|
this.DecriptResponse(response);
|
|
}
|
|
|
|
this.MessageQueue.Enqueue(response);
|
|
|
|
if (response.Command == SIRTConstants.ACKN_ANSW)
|
|
{
|
|
this.AKNReceived?.Invoke(response);
|
|
}
|
|
else if (response.Command == SIRTConstants.FROM_AIR)
|
|
{
|
|
var payload = response?.Payload;
|
|
|
|
if (payload != null && payload.Length > 0)
|
|
{
|
|
var type = payload[0];
|
|
|
|
if (type == SIRTConstants.BUP)
|
|
{
|
|
this.AnyTelegramReceived = true;
|
|
this.BUPReceived?.Invoke(response);
|
|
}
|
|
else if (type == SIRTConstants.LAT)
|
|
{
|
|
this.latReceived = true;
|
|
this.AnyTelegramReceived = true;
|
|
this.LATReceived?.Invoke(response);
|
|
}
|
|
else if (type == SIRTConstants.DEBUG)
|
|
{
|
|
this.debugReceived = true;
|
|
this.AnyTelegramReceived = true;
|
|
this.DEBUGReceived?.Invoke(response);
|
|
}
|
|
else if (type == SIRTConstants.SEMI)
|
|
{
|
|
this.AnyTelegramReceived = true;
|
|
this.SEMIReceived?.Invoke(response);
|
|
}
|
|
else
|
|
{
|
|
this.UnknownReceived?.Invoke(response);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.UnknownReceived?.Invoke(response);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.UnknownReceived?.Invoke(response);
|
|
}
|
|
|
|
this.MessageReceived?.Invoke(response);
|
|
}
|
|
|
|
public override byte[] Start()
|
|
{
|
|
this.latReceived = false;
|
|
this.debugReceived = false;
|
|
var message = new SIRTMessage
|
|
{
|
|
Direction = this.request.Direction,
|
|
Command = this.request.Command,
|
|
P1 = this.request.P1,
|
|
P2 = this.request.P2,
|
|
Address = this.request.Address,
|
|
Payload = this.EncryptRequest(),
|
|
Frequency = this.Frequency,
|
|
SirtId = this.SirtId,
|
|
};
|
|
|
|
this.MessageSent?.Invoke(this.request);
|
|
this.SetRunning();
|
|
|
|
return message.GetBytes();
|
|
}
|
|
|
|
protected virtual void OnMessageSent(SIRTMessage request)
|
|
{
|
|
|
|
}
|
|
|
|
protected virtual void OnAKNReceived(SIRTMessage akn)
|
|
{
|
|
|
|
}
|
|
|
|
protected virtual void OnBUPReceived(SIRTMessage bup)
|
|
{
|
|
|
|
}
|
|
|
|
protected virtual void OnLATReceived(SIRTMessage lat)
|
|
{
|
|
this.latReceived = true;
|
|
}
|
|
|
|
protected virtual void OnDEBUGReceived(SIRTMessage debug)
|
|
{
|
|
this.debugReceived = true;
|
|
|
|
if (this.RequireLAT && !this.latReceived)
|
|
{
|
|
this.SetPending();
|
|
}
|
|
}
|
|
|
|
protected virtual void OnSEMIReceived(SIRTMessage semi)
|
|
{
|
|
if ((this.RequireLAT && !this.latReceived) || (this.RequireDEBUG && !this.debugReceived) || semi.Payload[this.PamStatusIX] != 0)
|
|
{
|
|
this.SetPending();
|
|
}
|
|
else
|
|
{
|
|
this.SetCompleted();
|
|
}
|
|
}
|
|
|
|
protected virtual void OnUnknownReceived(SIRTMessage unknown)
|
|
{
|
|
|
|
}
|
|
|
|
protected virtual bool UseEncryption(SIRTMessage response)
|
|
{
|
|
if (response is null || this.EncryptionKeyI is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var payload = response.Payload;
|
|
|
|
if (payload is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var payloadLength = payload.Length;
|
|
|
|
if (payloadLength == 0 || payloadLength == this.DebugLength || payloadLength == this.SemiLength)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.IsEncrypted = payload.GetCrc() != 0;
|
|
|
|
return this.IsEncrypted;
|
|
}
|
|
|
|
private byte[] EncryptRequest()
|
|
{
|
|
var requestPayload = this.request.Payload;
|
|
var payloadLength = requestPayload.Length;
|
|
var payload = new byte[payloadLength];
|
|
|
|
if (payloadLength > 0)
|
|
{
|
|
Array.Copy(requestPayload, 0, payload, 0, payloadLength);
|
|
|
|
if (this.IsEncrypted)
|
|
{
|
|
payload = payload.EncryptRequest(this.EncryptionKeyI, this.RequestAddress);
|
|
}
|
|
}
|
|
|
|
return payload;
|
|
}
|
|
|
|
private void DecriptResponse(SIRTMessage response)
|
|
{
|
|
var payload = new byte[response.Length];
|
|
Array.Copy(response.Payload, 0, payload, 0, payload.Length);
|
|
|
|
response.Payload = payload.DecryptResponse(this.EncryptionKeyI);
|
|
|
|
if (response.Payload[this.PamStatusIX] != 0 && this.EncryptionKeyII != null)
|
|
{
|
|
response.Payload = payload.DecryptResponse(this.EncryptionKeyII);
|
|
|
|
if (response.Payload[this.PamStatusIX] == 0)
|
|
{
|
|
var oldEncryptionKey = this.EncryptionKeyI;
|
|
this.EncryptionKeyI = this.EncryptionKeyII;
|
|
this.EncryptionKeyII = oldEncryptionKey;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetP811(Action<P811> p811Setter)
|
|
{
|
|
p811Setter.Invoke(this.p811);
|
|
|
|
this.request.P1 = this.p811;
|
|
}
|
|
}
|
|
}
|