309 lines
13 KiB
C#
309 lines
13 KiB
C#
namespace Common.Hardware.WaterMeter.eRegister
|
|
{
|
|
using Common.Hardware.SIRT;
|
|
using Common.Hardware.SIRT.Tasks;
|
|
using Common.Hardware.WaterMeter.eRegister.Features;
|
|
using Common.Hardware.WaterMeter.eRegister.Models;
|
|
using Common.Hardware.WaterMeter.eRegister.Telegrams;
|
|
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
|
|
public class Eregister
|
|
{
|
|
const string SENSUS_STANDARD = "E6C88800DEB868C0D6A84880CE982840";
|
|
|
|
private readonly ICollection<EregisterTask> runningTasks;
|
|
private readonly EregisterProgrammingParameters parameters;
|
|
private readonly EregisterHistory history;
|
|
private readonly EregisterState state;
|
|
private readonly SIRTHub sirtHub;
|
|
|
|
private string executionType;
|
|
|
|
public uint Adresse { get; set; }
|
|
|
|
public uint TempAdresse { get; set; }
|
|
|
|
public Eregister(EregisterProgrammingParameters parameters, SIRTHub sirtHub)
|
|
{
|
|
this.parameters = parameters;
|
|
this.sirtHub = sirtHub;
|
|
this.state = new EregisterState();
|
|
this.history = new EregisterHistory();
|
|
this.runningTasks = new List<EregisterTask>();
|
|
}
|
|
|
|
public void Clear() => this.runningTasks.Clear();
|
|
|
|
internal IEnumerable<EregisterTask> LoadInspectionInitializationTasks()
|
|
{
|
|
this.executionType = nameof(LoadInspectionInitializationTasks);
|
|
var features = this.parameters.LoadInspectionInitializationFeatures();
|
|
|
|
if (features.RequestAddress > 0 && features.ResponseAddress > 0)
|
|
{
|
|
this.LoadProgrammingParameters(features);
|
|
|
|
if (this.runningTasks.Any())
|
|
{
|
|
this.runningTasks.Add(new EregisterChangeMeterTypeTask(features.Frequency)
|
|
{
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
Name = "Change Meter Type"
|
|
});
|
|
}
|
|
}
|
|
|
|
return this.runningTasks.ToArray();
|
|
}
|
|
|
|
internal IEnumerable<EregisterTask> LoadInspectionFinalizationTasks()
|
|
{
|
|
this.executionType = nameof(LoadInspectionFinalizationTasks);
|
|
var features = this.parameters.LoadInspectionFinalizationFeatures();
|
|
|
|
if (features.RequestAddress > 0 && features.ResponseAddress > 0)
|
|
{
|
|
// this.LoadProgrammingParameters(features);
|
|
|
|
if (this.parameters.StatusFertigung == 30)
|
|
{
|
|
//this.runningTasks.Add(new EregisterCheckFinalizationTask(this.parameters, features.Frequency)
|
|
//{
|
|
// WakeUpModul = true,
|
|
// SlotNr = features.SlotNr,
|
|
// PoNr = features.PoNr,
|
|
// SerialNr = features.SerialNr,
|
|
// RequestAddress = features.RequestAddress,
|
|
// ResponseAddress = features.ResponseAddress,
|
|
// EncryptionKeyI = features.EncryptionKey,
|
|
// EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
//});
|
|
|
|
this.runningTasks.Add(new EregisterTask(this.parameters.Frequency)
|
|
{
|
|
Name = "WUP",
|
|
WakeUpCmd = true,
|
|
WakeUpModul = true,
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
Data = new ChangeWakeUp(WakeUpMode.StayAwake)
|
|
.Append(new ChangeNumberOfLatWindows(this.parameters.LatWindowsInitialization))
|
|
.Append(new ChangeTransmissionInterval(this.parameters.TransmissionIntervalInitialization))
|
|
.Append(new ChangeSensusRFEncryptionKey(features.EncryptionKey))
|
|
.Append(new ProvidePin(AuthLevel.II)),
|
|
Timeout = 10_000
|
|
});
|
|
|
|
|
|
this.runningTasks.Add(new EregisterTask(this.parameters.Frequency)
|
|
{
|
|
WakeUpModul = true,
|
|
Name = "0, 2, 16",
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
Data = new ChangeWakeUp((WakeUpMode)this.parameters.Wake_Up_Interval)
|
|
.Append(new ChangeNumberOfLatWindows(this.parameters.LAT_Interval))
|
|
.Append(new ChangeTransmissionInterval(this.parameters.Transmission_Intervall))
|
|
.Append(new ProvidePin(AuthLevel.II)),
|
|
});
|
|
|
|
this.LoadProgrammingParameters(features);
|
|
}
|
|
}
|
|
|
|
return this.runningTasks.AsEnumerable();
|
|
}
|
|
|
|
internal EregisterHistory GetHistory() => this.history;
|
|
|
|
internal EregisterState GetState() => this.state;
|
|
|
|
internal void StartProgramming(CancellationToken cancellationToken)
|
|
{
|
|
this.history.SerienNr = this.parameters.SerienNr;
|
|
this.history.Adresse = this.parameters.Adresse;
|
|
this.history.TempAdresse = this.parameters.TempAdresse;
|
|
|
|
var tasks = new ConcurrentQueue<EregisterTask>(this.runningTasks);
|
|
var factoryState = FactoryState.Production;
|
|
var lat = default(LAT);
|
|
var debug = default(DEBUG);
|
|
var semi = default(SEMI);
|
|
|
|
while (!cancellationToken.IsCancellationRequested && tasks.TryDequeue(out var task))
|
|
{
|
|
task.MessageReceived += this.history.Push;
|
|
|
|
var next = 0;
|
|
|
|
while (task.State != SIRTTaskState.Completed && task.State != SIRTTaskState.Cancelled && !cancellationToken.IsCancellationRequested && next < 30)
|
|
{
|
|
if (this.sirtHub.Start(task))
|
|
{
|
|
this.history.Push(task);
|
|
task.Wait();
|
|
next++;
|
|
}
|
|
|
|
if (task.ErrorMessage != null)
|
|
{
|
|
this.state.Bemerkung += task.ErrorMessage.Title + Environment.NewLine;
|
|
this.state.Bemerkung += task.ErrorMessage.Text + Environment.NewLine;
|
|
}
|
|
}
|
|
|
|
task.MessageReceived -= this.history.Push;
|
|
|
|
if (task.State != SIRTTaskState.Completed)
|
|
{
|
|
break;
|
|
}
|
|
|
|
this.UpdateTasksStateInTheQueue(task);
|
|
|
|
lat = task.LATMessage ?? lat;
|
|
debug = task.DEBUGMessage ?? debug;
|
|
semi = task.SEMIMessage ?? semi;
|
|
factoryState = task.FactoryState;
|
|
|
|
if (task.DEBUGMessage != null)
|
|
{
|
|
this.state.SemiDebugDatum = DateTime.Now;
|
|
}
|
|
|
|
if (task.RequestAddress == this.parameters.Adresse)
|
|
{
|
|
this.state.FunkadresseDatum = DateTime.Now;
|
|
}
|
|
|
|
if (factoryState == FactoryState.Shipment)
|
|
{
|
|
this.state.GeschlossenDatum = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
this.state.ShouldUpdate = true;
|
|
this.state.Bemerkung += this.executionType;
|
|
this.state.Fabrikationsnummer = debug?.PCBID;
|
|
this.state.BUP = lat?.ToString()?.Replace('-', '\t');
|
|
this.state.DEBUG = debug?.ToString()?.Replace('-', '\t');
|
|
this.state.SEMI = semi?.ToString()?.Replace('-', '\t');
|
|
this.state.Seriennummer = this.parameters.SerienNr;
|
|
this.state.TempAdresse = this.parameters.TempAdresse;
|
|
}
|
|
|
|
private void UpdateTasksStateInTheQueue(EregisterTask task)
|
|
{
|
|
var cultureInfo = CultureInfo.InvariantCulture;
|
|
var numberStyles = NumberStyles.HexNumber | NumberStyles.AllowHexSpecifier;
|
|
|
|
foreach (var eregisterTask in this.runningTasks.AsEnumerable())
|
|
{
|
|
if (eregisterTask.State == SIRTTaskState.Completed)
|
|
{
|
|
continue;
|
|
}
|
|
else if (task.State == SIRTTaskState.Cancelled)
|
|
{
|
|
eregisterTask.SetCancelled();
|
|
}
|
|
|
|
eregisterTask.AnyTelegramReceived = task.AnyTelegramReceived;
|
|
eregisterTask.RequestAddress = task.RequestAddress;
|
|
eregisterTask.ResponseAddress = task.ResponseAddress;
|
|
eregisterTask.FactoryState = task.FactoryState;
|
|
eregisterTask.IsEncrypted = task.IsEncrypted;
|
|
eregisterTask.EncryptionKeyI = task.EncryptionKeyI;
|
|
eregisterTask.EncryptionKeyII = task.EncryptionKeyII;
|
|
|
|
if (task.DEBUGMessage != null)
|
|
{
|
|
eregisterTask.RadioFWHex = task.DEBUGMessage.RadioFWVersion;
|
|
|
|
if (int.TryParse($"{eregisterTask.RadioFWHex}", numberStyles, cultureInfo, out var radioFWVersion))
|
|
{
|
|
eregisterTask.RadioFWVersion = radioFWVersion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadProgrammingParameters(EregisterFeatures features, [CallerMemberName] string caller = "")
|
|
{
|
|
this.Clear();
|
|
|
|
var frequency = this.parameters.Frequency;
|
|
|
|
this.runningTasks.Add(new EregisterTask(frequency)
|
|
{
|
|
Name = "WUP",
|
|
WakeUpCmd = true,
|
|
WakeUpModul = true,
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
Data = new ChangeWakeUp(WakeUpMode.StayAwake)
|
|
.Append(new ChangeNumberOfLatWindows(this.parameters.LatWindowsInitialization))
|
|
.Append(new ChangeTransmissionInterval(this.parameters.TransmissionIntervalInitialization))
|
|
// .Append(new ChangeSensusRFEncryptionKey(features.EncryptionKey))
|
|
.Append(new ProvidePin(AuthLevel.II)),
|
|
Timeout = 10_000
|
|
});
|
|
|
|
this.runningTasks.Add(new EregisterCheckInitializationTask(this.parameters, frequency)
|
|
{
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
});
|
|
|
|
foreach (var pam in features.BuildPams())
|
|
{
|
|
this.runningTasks.Add(new EregisterTask(frequency)
|
|
{
|
|
SlotNr = features.SlotNr,
|
|
PoNr = features.PoNr,
|
|
SerialNr = features.SerialNr,
|
|
RequestAddress = features.RequestAddress,
|
|
ResponseAddress = features.ResponseAddress,
|
|
EncryptionKeyI = features.EncryptionKey,
|
|
EncryptionKeyII = SENSUS_STANDARD.GetEncryptionKey(),
|
|
Data = pam.Value,
|
|
Name = pam.Key
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|