diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisConfig/ProcessConfig.cs b/Common/Hardware/WaterMeter/Genesis/GenesisConfig/ProcessConfig.cs index 18512614..ddf3bb89 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisConfig/ProcessConfig.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisConfig/ProcessConfig.cs @@ -27,7 +27,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig /// public ProcessConfig(String file) { - // chack for AppRoaming + // check for AppRoaming var configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(Genesis), file); if (!File.Exists(configFile)) diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisConfigReader.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisConfigReader.cs index d6ff7392..1a00dd47 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisConfigReader.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisConfigReader.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes; @@ -62,208 +61,218 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore try { //extract information of every application - foreach (var currentApplication in applicationGroups) - { - var o = (JObject)currentApplication.Value; - var application = new ApplicationDefinition(); - Byte applicationAddress = 0; - - foreach (var groupProp in o) + if (applicationGroups != null) + foreach (var currentApplication in applicationGroups) { - try + var o = (JObject)currentApplication.Value; + var application = new ApplicationDefinition(); + Byte applicationAddress = 0; + + foreach (var groupProp in o) { - if (groupProp.Key == "id") + try { - applicationAddress = groupProp.Value.Value(); - application.AppName = currentApplication.Key; - application.AppId = applicationAddress; - ConfigApplicationDefinitions.Add(application); - } - else if (groupProp.Key == "registers") - { - foreach (var registers in groupProp.Value) + if (groupProp.Key == "id") { - var register = ((JProperty)registers); - - try + applicationAddress = groupProp.Value.Value(); + application.AppName = currentApplication.Key; + application.AppId = applicationAddress; + ConfigApplicationDefinitions.Add(application); + } + else if (groupProp.Key == "registers") + { + foreach (var registers in groupProp.Value) { - foreach (var registerJ in register.Value) + var register = (JProperty)registers; + + try { - JProperty reg = ((JProperty)registerJ); - - Byte? registerAddress = null; - if (reg.Name == "id") + foreach (var registerJ in register.Value) { - registerAddress = (Byte)reg.Value; - } + var reg = (JProperty)registerJ; - if (reg.Name == "details") - { - - var details = ((JArray)reg.Value); - - foreach (var jdetail in details.Children()) + Byte? registerAddress = null; + if (reg.Name == "id") { - var actualRegister = new RegisterDefinition(); - var idTag = reg.Parent.First(f => ((JProperty)f).Name == "id"); - var id = (Byte)(JProperty)idTag;//.Value(); + registerAddress = (Byte)reg.Value; + } - if (registerAddress.HasValue) - { - throw new Exception("invalid json cast"); - } - actualRegister.RegAddressInApp = id; - actualRegister.AppName = currentApplication.Key; - actualRegister.AppAddress = applicationAddress; - actualRegister.RegisterDetail = new RegisterDetail(); - actualRegister.RegisterName = register.Name; - var detailO = (JObject)jdetail; - JProperty detail; - detail = detailO.Property("privilege"); - if (detail.Name == "privilege") - { - actualRegister.RegisterDetail.Privilege = JsonConvert.DeserializeObject(detail.Value.ToString(), Settings); - } - detail = detailO.Property("type"); - if (detail.Name == "type") - { + if (reg.Name == "details") + { + var details = ((JArray)reg.Value); - actualRegister.DataType = typeof(String);// detail.Value.ToString(); + foreach (var jdetail in details.Children()) + { + var actualRegister = new RegisterDefinition(); + var idTag = reg.Parent.First(f => ((JProperty)f).Name == "id"); + var id = (Byte)(JProperty)idTag; //.Value(); - switch (detail.Value.ToString().ToLower()) + if (registerAddress.HasValue) { - case "bool_t": - actualRegister.DataType = typeof(Boolean); - break; - case "rpc": - actualRegister.DataType = typeof(Rpc); - break; - case "string": - actualRegister.DataType = typeof(String); - break; - case "uint32_t": - actualRegister.DataType = typeof(UInt32); - break; - case "time_t": - actualRegister.DataType = typeof(TimeT); - break; - case "status_t": - actualRegister.DataType = typeof(StatusT); - break; - case "uint16_t": - actualRegister.DataType = typeof(UInt16); - break; - case "uint8_t": - actualRegister.DataType = typeof(byte); - break; - case "enum8": - actualRegister.DataType = typeof(Enum8); - break; - case "uint64_t": - actualRegister.DataType = typeof(UInt64); - break; - case "uint96_t": - actualRegister.DataType = typeof(UInt96); - break; - case "int8_t": - actualRegister.DataType = typeof(sbyte); - break; - case "int32_t": - actualRegister.DataType = typeof(Int32); - break; - case "int64_t": - actualRegister.DataType = typeof(Int64); - break; - case "int16_t": - actualRegister.DataType = typeof(Int16); - break; + throw new Exception("invalid json cast"); } - } - detail = detailO.Property("description"); - if (detail.Name == "description") - { - actualRegister.RegisterDetail.Description = detail.Value.ToString(); - } - detail = detailO.Property("version"); - if (detail.Name == "version") - { - actualRegister.RegisterDetail.Version = JsonConvert.DeserializeObject(detail.Value.ToString()); - } - detail = detailO.Property("values"); - if (detail != null && detail.Name == "values") - { - foreach (var dValues in detail.Children().First()) + actualRegister.RegAddressInApp = id; + actualRegister.AppName = currentApplication.Key; + actualRegister.AppAddress = applicationAddress; + actualRegister.RegisterDetail = new RegisterDetail(); + actualRegister.RegisterName = register.Name; + var detailO = (JObject)jdetail; + JProperty detail; + detail = detailO.Property("privilege"); + if (detail.Name == "privilege") { - switch (((JProperty)dValues).Name) + actualRegister.RegisterDetail.Privilege = + JsonConvert.DeserializeObject( + detail.Value.ToString(), Settings); + } + + detail = detailO.Property("type"); + if (detail.Name == "type") + { + actualRegister.DataType = + typeof(String); // detail.Value.ToString(); + + switch (detail.Value.ToString().ToLower()) { - case "default": - actualRegister.Default = (Int64)((JProperty)dValues).Value; + case "bool_t": + actualRegister.DataType = typeof(Boolean); break; - case "maximum": - actualRegister.Maximum = (Int64)((JProperty)dValues).Value; + case "rpc": + actualRegister.DataType = typeof(Rpc); break; - case "minimum": - actualRegister.Minimum = (Int64)((JProperty)dValues).Value; + case "string": + actualRegister.DataType = typeof(String); + break; + case "uint32_t": + actualRegister.DataType = typeof(UInt32); + break; + case "time_t": + actualRegister.DataType = typeof(TimeT); + break; + case "status_t": + actualRegister.DataType = typeof(StatusT); + break; + case "uint16_t": + actualRegister.DataType = typeof(UInt16); + break; + case "uint8_t": + actualRegister.DataType = typeof(byte); + break; + case "enum8": + actualRegister.DataType = typeof(Enum8); + break; + case "uint64_t": + actualRegister.DataType = typeof(UInt64); + break; + case "uint96_t": + actualRegister.DataType = typeof(UInt96); + break; + case "int8_t": + actualRegister.DataType = typeof(sbyte); + break; + case "int32_t": + actualRegister.DataType = typeof(Int32); + break; + case "int64_t": + actualRegister.DataType = typeof(Int64); + break; + case "int16_t": + actualRegister.DataType = typeof(Int16); break; } } - } - detail = detailO.Property(StaticType.StaticTypeFieldIdentifier); - if (detail != null && detail.Name == StaticType.StaticTypeFieldIdentifier) - { - actualRegister.RestoreCapability = new StaticType(detail.Value.ToString()); + detail = detailO.Property("description"); + if (detail.Name == "description") + { + actualRegister.RegisterDetail.Description = + detail.Value.ToString(); + } + + detail = detailO.Property("version"); + if (detail.Name == "version") + { + actualRegister.RegisterDetail.Version = + JsonConvert.DeserializeObject( + detail.Value.ToString()); + } + + detail = detailO.Property("values"); + if (detail != null && detail.Name == "values") + { + foreach (var dValues in detail.Children().First()) + { + switch (((JProperty)dValues).Name) + { + case "default": + actualRegister.Default = + (Int64)((JProperty)dValues).Value; + break; + case "maximum": + actualRegister.Maximum = + (Int64)((JProperty)dValues).Value; + break; + case "minimum": + actualRegister.Minimum = + (Int64)((JProperty)dValues).Value; + break; + } + } + } + + detail = detailO.Property(StaticType.StaticTypeFieldIdentifier); + if (detail != null && detail.Name == + StaticType.StaticTypeFieldIdentifier) + { + actualRegister.RestoreCapability = + new StaticType(detail.Value.ToString()); + } + + ConfigRegistersDefinitions.Add(actualRegister); } - ConfigRegistersDefinitions.Add(actualRegister); } } } - } - catch (Exception e) - { - //todo log ex + catch (Exception ) + { + //todo log ex + } } } } - } - catch (Exception e) - { - //todo log ex + catch (Exception ) + { + //todo log ex + } } } - } } - catch (Exception ex) + catch (Exception ) { - - + // ignored } - + ////tofile - var sb = new StringBuilder(); - var lsitOfRegisters = new List(); + var listOfRegisters = new List(); foreach (var item in ConfigRegistersDefinitions) { - if (item is RegisterDefinition Reg) + if (item is RegisterDefinition reg) { - if (lsitOfRegisters.Any(a => a.GetIdent() == Reg.GetIdent())) + if (listOfRegisters.Any(a => a.GetIdent() == reg.GetIdent())) { - var oldItem = lsitOfRegisters.First(a => a.GetIdent() == Reg.GetIdent()); - if (oldItem.RegisterDetail.Version.Last < Reg.RegisterDetail.Version.Last) + var oldItem = listOfRegisters.First(a => a.GetIdent() == reg.GetIdent()); + if (oldItem.RegisterDetail.Version.Last < reg.RegisterDetail.Version.Last) { - lsitOfRegisters.Remove(oldItem); - lsitOfRegisters.Add(Reg); + listOfRegisters.Remove(oldItem); + listOfRegisters.Add(reg); } } else { - lsitOfRegisters.Add(Reg); + listOfRegisters.Add(reg); } - - - } } //#region create a file for my american friends @@ -439,6 +448,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore public static readonly LvlConverter Singleton = new LvlConverter(); } + /// + /// Settings + /// public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings { MetadataPropertyHandling = MetadataPropertyHandling.Ignore, diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeterStreamingQuality.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeterStreamingQuality.cs index a536f1e1..de95bfe7 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeterStreamingQuality.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeterStreamingQuality.cs @@ -7,26 +7,42 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.StreamingProtocol; namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore { + /// + /// Check the positioning of the streaming LED to validate the quality of the communication line + /// public class GenesisMeterStreamingQuality : GenesisMeter { + /// + /// Backup of last quality + /// public QualityResult LastQualityResult; - private StreamingDecoder sd; + + private StreamingDecoder _sd; + /// + /// Quality check is active + /// public Boolean IsRunning; private DateTimeOffset? _startTime; private DateTimeOffset? _stopTime; private List _collectedRecords; - private int? TillDecodedCount = null; - public void StartStreamingQualityCheck(int? tillDecodedCount = null) + + private Int32? _tillDecodedCount; + /// + /// Kick off the streaming quality check. + /// + /// + /// + public void StartStreamingQualityCheck(Int32? tillDecodedCount = null) { if (IsRunning) { return; } - TillDecodedCount = tillDecodedCount; - if (TillDecodedCount.HasValue) + _tillDecodedCount = tillDecodedCount; + if (_tillDecodedCount.HasValue) { - sd = new StreamingDecoder(false); + _sd = new StreamingDecoder(false); } if (StreamingPort == null || !(StreamingPort is LedSerialPort)) { @@ -36,7 +52,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore _stopTime = null; _collectedRecords = new List(); - SyncStreamingBuffer(SyncMarkRecord.FlushBuffer); SyncStreamingBuffer(SyncMarkRecord.DecodeEveryPackage); ((LedSerialPort)StreamingPort).OnRawRecordReceived += GenesisMeterStreamingQuality_OnRawRecordReceived; _startTime = DateTimeOffset.UtcNow; @@ -47,21 +62,27 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore private void GenesisMeterStreamingQuality_OnRawRecordReceived(Object sender, BasePortDataEventArgs e) { _collectedRecords.Add(e.GetData().ToString()); - if (TillDecodedCount.HasValue) + if (_tillDecodedCount.HasValue) { - if (sd.DecodeMsg(e.GetData().ToString())) + if (_sd.DecodeMsg(e.GetData().ToString())) { - TillDecodedCount = TillDecodedCount.Value - 1; - if (TillDecodedCount <= 0) + _tillDecodedCount = _tillDecodedCount.Value - 1; + if (_tillDecodedCount <= 0) { IsRunning = false; LastQualityResult = StopStreamingQualityCheck(10); } } - + } } + /// + /// Stop the streaming check. + /// + /// + /// + /// public QualityResult StopStreamingQualityCheck(Int32 sampleRateHz) { _stopTime = DateTimeOffset.UtcNow; @@ -79,24 +100,56 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore ((LedSerialPort)StreamingPort).OnRawRecordReceived -= GenesisMeterStreamingQuality_OnRawRecordReceived; SyncStreamingBuffer(SyncMarkRecord.SkipDecoding); IsRunning = false; - return new QualityResult(_collectedRecords, _stopTime.Value - _startTime.Value, sampleRateHz); + if (_stopTime != null && _startTime != null) + return new QualityResult(_collectedRecords, _stopTime.Value - _startTime.Value, sampleRateHz); + return new QualityResult(); } + /// + /// + /// public class QualityResult { + /// + /// Number of records received (read line for LED message) + /// public readonly Int32 TotalLinesCount; + /// + /// Total records decoded + /// public readonly Int32 TotalDecodedCount; + /// + /// Total errors + /// public readonly Int32 TotalTransportErrorCount; + /// + /// Validated without errors + /// public readonly Int32 TotalValidationWithoutErrorsCount; + /// + /// Expected lines + /// public readonly Int32 ExpectedLinesCount; + /// + /// Time + /// public readonly TimeSpan TotalTime; + /// + /// Error counter + /// public readonly Dictionary ErrorOccurredCounter; + /// + /// The real result of quality check + /// + /// + /// + /// public QualityResult(List collectedRecords, TimeSpan ts, Int32 sampleRateHz) { TotalLinesCount = collectedRecords.Count; TotalTime = ts; - ExpectedLinesCount = (Int32)(Math.Round( ts.TotalSeconds * sampleRateHz, 0)); + ExpectedLinesCount = (Int32)(Math.Round(ts.TotalSeconds * sampleRateHz, 0)); ErrorOccurredCounter = new Dictionary(); foreach (var rawText in collectedRecords) { @@ -140,6 +193,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } } + /// + /// The quality result as dummy zero + /// public QualityResult() { TotalLinesCount = 0; diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/_GenesisMeterMeasurement.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/_GenesisMeterMeasurement.cs index 104ac3c9..c20aea24 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/_GenesisMeterMeasurement.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/_GenesisMeterMeasurement.cs @@ -23,7 +23,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// All channels required to process /// public Boolean AllChannelsRequired = true; - private const bool QualityWatchMode = false; + + /// + /// Quality watch mode can be used to decode intermediate records and check + /// for actual quality of the measurements. + /// + public Boolean QualityWatchMode; @@ -69,7 +74,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore displayStateString = ByteStyler.ToString(displayState); if (displayStateString != "00-00-00-00") { - WriteRegister(Register.Genesisflow.TriggerActive, 1, true); + WriteRegister(Register.Genesisflow.TriggerActive, 1); } } @@ -79,9 +84,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } - WriteRegister("GENESISFLOW_DisplayPow10", (new Byte[] { 0x00, 0x00, 0x00, 0xFA }).Reverse().ToArray(), true, false); - WriteRegister(Register.Genesisflow.StoreCalibration, 1, true); - WriteRegister(Register.Genesisflow.StoreConfiguration, 1, true); + WriteRegister("GENESISFLOW_DisplayPow10", (new Byte[] { 0x00, 0x00, 0x00, 0xFA }).Reverse().ToArray()); + WriteRegister(Register.Genesisflow.StoreCalibration, 1); + WriteRegister(Register.Genesisflow.StoreConfiguration, 1); //} @@ -233,15 +238,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore if (_listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsRunning) || _listOfIMeasurement.All(m => m.MeasurementState == MeasurementStates.IsCompleted)) { - if (QualityWatchMode) - { - SyncStreamingBuffer(SyncMarkRecord.DecodeIntermediateQuality); - } - else - { - SyncStreamingBuffer(SyncMarkRecord.SkipDecoding); - } - + SyncStreamingBuffer(QualityWatchMode + ? SyncMarkRecord.DecodeIntermediateQuality + : SyncMarkRecord.SkipDecoding); } } @@ -263,35 +262,27 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore if (onlyChannelNr.HasValue) { var measurement = _listOfIMeasurement.First(f => f.GetChannel() == onlyChannelNr.Value); - if (measurement == null) - { - return MeasurementStates.NotStarted; - } - return measurement.GetMeasurementState(); } return _listOfIMeasurement.Min(m => m.MeasurementState); } - - /// - public bool RequestIntermediateMeasurementState(Int32? onlyChannelNr = null) + public Boolean RequestIntermediateMeasurementState(Int32? onlyChannelNr = null) { _logger.Trace($"Slot:{Slot} - Get measurement state"); if (!_listOfIMeasurement.Any()) { return false; } - bool? ret = null; + Boolean? ret = null; foreach (var item in _listOfIMeasurement) { if (!onlyChannelNr.HasValue || item.GetChannel() == onlyChannelNr.Value) { - var measurement = _listOfIMeasurement.First(f => f.GetChannel() == onlyChannelNr.Value); - if (measurement != null && - (measurement.MeasurementState == MeasurementStates.IsRunning - || measurement.MeasurementState == MeasurementStates.IsWaitingForIntermediateData)) + var measurement = _listOfIMeasurement.First(f => onlyChannelNr != null && f.GetChannel() == onlyChannelNr.Value); + if ((measurement.MeasurementState == MeasurementStates.IsRunning + || measurement.MeasurementState == MeasurementStates.IsWaitingForIntermediateData)) { measurement.RequestIntermediateRecord(); if (!ret.HasValue) @@ -307,8 +298,5 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } return ret.HasValue ? ret.Value : false; } - - - } } diff --git a/Common/Hardware/WaterMeter/WaterMeterCore/IMeter.cs b/Common/Hardware/WaterMeter/WaterMeterCore/IMeter.cs index bbd0e215..bb6f85b4 100644 --- a/Common/Hardware/WaterMeter/WaterMeterCore/IMeter.cs +++ b/Common/Hardware/WaterMeter/WaterMeterCore/IMeter.cs @@ -172,6 +172,13 @@ namespace Xylem.Common.Hardware.WaterMeter.WaterMeterCore /// MeasurementStates GetMeasurementState(Int32? onlyChannelNr = null ); + /// + /// Request for intermediate measurement state. + /// + /// + /// + Boolean RequestIntermediateMeasurementState(Int32? onlyChannelNr = null); + /// /// set up calibration parameter (calibration factor to default) and set meter into calibration mode /// diff --git a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache index f22623aa..d8b5c8f6 100644 --- a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache +++ b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -5ed75d99ee45ff67821090f1b3dbb001dd9e4fe3 +1a3d4919c9c702245832d925951f2b7cb72fc333 diff --git a/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache b/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache index 133b97f0..0028f628 100644 --- a/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache +++ b/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -0d85a5b3a7561b41163c20e5dc7713bcd0d65555 +f64d563def603c89cafafa61a3219ba97e1e344c