228 lines
7.1 KiB
C#
228 lines
7.1 KiB
C#
namespace Common.Hardware.WaterMeter.eRegister
|
|
{
|
|
using Common.Hardware.SIRT;
|
|
using Common.Hardware.SIRT.Parameters;
|
|
using Common.Hardware.WaterMeter.eRegister.Features;
|
|
using Common.Hardware.WaterMeter.eRegister.Models;
|
|
using Common.Hardware.WaterMeter.eRegister.Telegrams;
|
|
|
|
using System;
|
|
using System.Timers;
|
|
|
|
public class EregisterTask : SIRTTask
|
|
{
|
|
public EregisterTask(int frequency, int timeout = 6_000)
|
|
: base(frequency, timeout)
|
|
{
|
|
this.Cmd = SIRTMessage.W_PAM;
|
|
this.RSSI = new RSSI(0, frequency);
|
|
this.Label = nameof(SIRTTaskState.Pending);
|
|
}
|
|
|
|
public event Action<EregisterTask> Changed;
|
|
public event Action<object> Telegram;
|
|
|
|
public int SlotNr { get; internal set; }
|
|
|
|
public int PoNr { get; internal set; }
|
|
|
|
public int SerialNr { get; internal set; }
|
|
|
|
public string Name { get; internal set; }
|
|
|
|
public string Label { get; protected set; }
|
|
|
|
public string Info { get; private set; }
|
|
|
|
public string RSSI { get; private set; }
|
|
|
|
public P11 P11 { get; private set; }
|
|
|
|
public P12 P12 { get; private set; }
|
|
|
|
public BUP BUP { get; private set; }
|
|
|
|
public LAT LAT { get; private set; }
|
|
|
|
public DEBUG DEBUG { get; private set; }
|
|
|
|
public SEMI SEMI { get; protected set; }
|
|
|
|
public bool IsEncrypted { get; set; }
|
|
|
|
public byte[] EncryptionKey { get; set; }
|
|
|
|
public StateModes Mode { get; set; }
|
|
|
|
public override void UpdateFrom(SIRTTask task)
|
|
{
|
|
base.UpdateFrom(task);
|
|
|
|
if (task is EregisterTask etask)
|
|
{
|
|
this.Mode = etask.Mode;
|
|
this.IsEncrypted = etask.IsEncrypted;
|
|
|
|
if (this.Mode == StateModes.Shipment)
|
|
{
|
|
this.Data = new EregisterAvailableParametersParser(this.Data);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override byte[] ToByteArray()
|
|
{
|
|
var data = this.request.Data;
|
|
|
|
// if (this.SEMI?.PAMStatus?.WRONG_AUTH == true || this.Mode == StateModes.Shipment)
|
|
{
|
|
data = new EregisterAvailableParametersParser(data);
|
|
}
|
|
|
|
if (this.IsEncrypted || this.Mode == StateModes.Shipment)
|
|
{
|
|
data = data.EncryptRequest(this.EncryptionKey, this.RequestAddress);
|
|
}
|
|
|
|
return new SIRTMessage
|
|
{
|
|
Address = this.request.Address,
|
|
Cmd = this.request.Cmd,
|
|
Data = data,
|
|
P1 = this.request.P1,
|
|
P2 = this.request.P2,
|
|
|
|
}.ToByteArray();
|
|
}
|
|
|
|
protected override void OnTimeout(object sender, ElapsedEventArgs e)
|
|
{
|
|
this.NotifyTimeouted();
|
|
|
|
this.State = SIRTTaskState.Pending;
|
|
}
|
|
|
|
protected override void ProcessResponse(SIRTMessage response)
|
|
{
|
|
if (this.State == SIRTTaskState.Cancelled)
|
|
{
|
|
this.Label = nameof(SIRTTaskState.Cancelled);
|
|
|
|
return;
|
|
}
|
|
|
|
if (response.Cmd == SIRTMessage.FROMAIR)
|
|
{
|
|
var data = response.Data;
|
|
var dataLength = data?.Length ?? 0;
|
|
|
|
this.P11 = new P11(response.P1);
|
|
this.RSSI = new RSSI(response.P2, (ushort)this.Frequency);
|
|
|
|
if (dataLength > 0)
|
|
{
|
|
var type = data[0];
|
|
|
|
if (this.IsEncrypted)
|
|
{
|
|
data = data.DecryptResponse(this.EncryptionKey);
|
|
}
|
|
|
|
if (type == SIRTMessage.BUP)
|
|
{
|
|
this.Label = nameof(SIRTMessage.BUP);
|
|
this.BUP = new BUP(data, this.P11);
|
|
this.NotifyTelegram(this.BUP);
|
|
}
|
|
else if (type == SIRTMessage.LAT)
|
|
{
|
|
this.Label = nameof(SIRTMessage.LAT);
|
|
this.LAT = new LAT(data, this.P11);
|
|
this.NotifyTelegram(this.LAT);
|
|
}
|
|
else if (type == SIRTMessage.DEBUG)
|
|
{
|
|
this.Label = nameof(SIRTMessage.DEBUG);
|
|
this.DEBUG = new DEBUG(data, this.P11);
|
|
this.NotifyTelegram(this.DEBUG);
|
|
|
|
this.Mode = (StateModes)(this.DEBUG.FactoryState - 1);
|
|
this.IsEncrypted = this.Mode == StateModes.Shipment;
|
|
this.NotifyUpdated();
|
|
}
|
|
else if (type == SIRTMessage.SEMI)
|
|
{
|
|
this.ProcessSEMI(data);
|
|
|
|
if (this.State == SIRTTaskState.Completed || this.State == SIRTTaskState.Cancelled)
|
|
{
|
|
this.EndProcessResponse(response);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.Label = "NA";
|
|
}
|
|
}
|
|
}
|
|
else if (response.Cmd == SIRTMessage.ACKNANSW)
|
|
{
|
|
this.P12 = new P12(response.P1);
|
|
this.Label = "ACKN";
|
|
}
|
|
else
|
|
{
|
|
this.Label = "NA";
|
|
}
|
|
|
|
this.NotifyChanged();
|
|
}
|
|
|
|
protected virtual void EndProcessResponse(SIRTMessage response)
|
|
=> base.ProcessResponse(response);
|
|
|
|
protected void NotifyChanged() => this.Changed?.Invoke(this);
|
|
|
|
protected void NotifyTelegram(object value) => this.Telegram?.Invoke(value);
|
|
|
|
private void ProcessSEMI(byte[] data)
|
|
{
|
|
this.SEMI = new SEMI(data, this.Frequency, this.P11);
|
|
|
|
if (this.SEMI.PAMStatus == PAMStatus.OK)
|
|
{
|
|
this.State = SIRTTaskState.Completed;
|
|
this.Label = this.SEMI.PAMStatus.ToString();
|
|
}
|
|
else
|
|
{
|
|
var isEncrypted = this.IsEncrypted;
|
|
this.IsEncrypted = this.SEMI.Crc != 0;
|
|
|
|
if (this.IsEncrypted != isEncrypted)
|
|
{
|
|
data = data.DecryptResponse(this.EncryptionKey);
|
|
}
|
|
|
|
this.SEMI = new SEMI(data, this.Frequency, this.P11);
|
|
|
|
if (this.SEMI.PAMStatus == PAMStatus.OK)
|
|
{
|
|
this.State = SIRTTaskState.Completed;
|
|
this.Label = this.SEMI.PAMStatus.ToString();
|
|
}
|
|
else if (this.SEMI.PAMStatus == PAMStatus.EXPIREDAUTH)
|
|
{
|
|
this.State = SIRTTaskState.Cancelled;
|
|
this.Label = this.SEMI.PAMStatus.ToString();
|
|
this.timeoutTimer.Stop();
|
|
}
|
|
|
|
this.Label = this.SEMI.PAMStatus.ToString();
|
|
}
|
|
|
|
this.NotifyTelegram(this.SEMI);
|
|
this.NotifyUpdated();
|
|
}
|
|
}
|
|
} |