From b22994fc67d3bee32c406c701460f2f7e6cdbddd Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Mon, 13 Feb 2023 11:39:12 +0100 Subject: [PATCH] GenesisMeter: - Removed retries on "ReadMeterFwAndAssignRegisters" as the reties will be handled by the RequestProtocol --- Common/.vs/config/applicationhost.config | 2 +- Common/Common.sln.DotSettings.user | 1 + .../Genesis/GenesisCore/GenesisMeter.cs | 56 +++++++++---------- .../RequestProtocol/RequestProtocol.cs | 49 +++++++++------- ...erRegisters.csproj.CoreCompileInputs.cache | 2 +- ...ToXlsHelper.csproj.CoreCompileInputs.cache | 2 +- 6 files changed, 58 insertions(+), 54 deletions(-) diff --git a/Common/.vs/config/applicationhost.config b/Common/.vs/config/applicationhost.config index 40cde372..1b9332b4 100644 --- a/Common/.vs/config/applicationhost.config +++ b/Common/.vs/config/applicationhost.config @@ -155,7 +155,7 @@ - + diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index 2ad4797a..dd1608cc 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -27,6 +27,7 @@ True NewVersion True + C:\Users\Thomas\AppData\Local\Temp\JetBrains\ReSharperPlatformVs15\vAny_33007af5\CoverageData\_Common.-1885154465\Snapshot\snapshot.utdcvr diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index ce057f06..d8d635bd 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -1263,7 +1263,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore try { var radioFrequencyRaw = ReadRegister(Register.Sensusradio.FrequencyIndicator); - if (radioFrequencyRaw != null ) + if (radioFrequencyRaw != null) { Region = "EMEA"; RadioFrequencyMhz = RegisterConverter.ConvertTo(radioFrequencyRaw); @@ -1283,7 +1283,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore LutCrc = "?"; } } - + /// /// Reading all applications which can be found in the configuration.json and have been stored /// to the meter register dictionary in advance. @@ -1313,6 +1313,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// /// - Checked meter size string for "DN", than it cannot be an EMEA version. /// + /// + /// - Removed retry as this will be handled by the . + /// private void ReadMeterFirmwareAndAssignRegisters() { //avoid overwriting of list if this already exits @@ -1329,39 +1332,32 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore UInt16 readFwCrc = 0; var isInstalled = false; var versionString = ""; - var recount = 4; - while (recount > 0) + if (WriteRegister(Register.System.CheckFwPresence, appVersionToRead.AppId)) { - recount -= 1; + //read version, skip retries on SYSTEM 0x04-> FW nor present is a valid feedback + var readFwVersionBytes = ReadRegister(Register.System.CheckFwPresence, 4); - if (WriteRegister(Register.System.CheckFwPresence, appVersionToRead.AppId)) + //the FW version as Uint32 will be used for comparison with the configuration.json + if (readFwVersionBytes != null && readFwVersionBytes.Length > 0) { - //read version, skip retries on SYSTEM 0x04-> FW nor present is a valid feedback - var readFwVersionBytes = ReadRegister(Register.System.CheckFwPresence, 4); + readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 + + (readFwVersionBytes[1] & 0x0F)) * 100; + readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 + + (readFwVersionBytes[0] & 0x0F)); + //build the version string, because e.g. FLEXNETVERSION is one application which does not + //follow the same rule. After the upper conversion, the hexadecimal outline will be lost + versionString = BuildFwVersionString(readFwVersionBytes[1], readFwVersionBytes[0]); + if (appVersionToRead.AppName == "FLEXNETVERSION") + FwVersion = versionString; - //the FW version as Uint32 will be used for comparison with the configuration.json - if (readFwVersionBytes != null && readFwVersionBytes.Length > 0) + if (readFwVersion != 0) { - readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 + - (readFwVersionBytes[1] & 0x0F)) * 100; - readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 + - (readFwVersionBytes[0] & 0x0F)); - //build the version string, because e.g. FLEXNETVERSION is one application which does not - //follow the same rule. After the upper conversion, the hexadecimal outline will be lost - versionString = BuildFwVersionString(readFwVersionBytes[1], readFwVersionBytes[0]); - if (appVersionToRead.AppName == "FLEXNETVERSION") - FwVersion = versionString; - if (readFwVersion != 0) + isInstalled = true; + //write application Id to CRC register + if (WriteRegister(Register.System.CheckFwCrc, appVersionToRead.AppId)) { - - isInstalled = true; - //write application Id to CRC register - if (WriteRegister(Register.System.CheckFwCrc, appVersionToRead.AppId)) - { - readFwCrc = RegisterConverter.ConvertTo(ReadRegister(Register.System.CheckFwCrc)); - } - break; + readFwCrc = RegisterConverter.ConvertTo(ReadRegister(Register.System.CheckFwCrc)); } } } @@ -1381,7 +1377,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } CheckRegionSizeLutCrc(); - + //read metrology upgrade permission MetrologyUpgradePermission = RegisterConverter.ConvertTo( ReadRegister(Register.System.MetrologyUpgradePermission)); @@ -1491,7 +1487,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore { var registerAddForOldConfigs = registerToPotentialAdd.GroupBy(item => item.GetIdent()) .Select(grp => grp.Aggregate((max, cur) => - (max == null || cur.RegisterDetail.Version.Last > max.RegisterDetail.Version.Last) ? + (max == null || cur.RegisterDetail.Version.Last > max.RegisterDetail.Version.Last) ? cur : max)); foreach (var registerAddOldConfig in registerAddForOldConfigs) diff --git a/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs b/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs index 73d044e7..18ee618d 100644 --- a/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs +++ b/Common/Hardware/WaterMeter/Genesis/Protocols/RequestProtocol/RequestProtocol.cs @@ -109,7 +109,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol /// public Int32 AdditionalRetryTimeoutMs; - private Int32 _timeOutMs; + private Int32 _maxTimeOutMs; private readonly String _ident; @@ -215,38 +215,41 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol //set timeout for one communication trial adding the transmit protocol specific timeout and //increase the timeout with each retry - _timeOutMs = _recordInProcess.ResponseTimeoutMs + AdditionalRetryTimeoutMs + + _maxTimeOutMs = _recordInProcess.ResponseTimeoutMs + AdditionalRetryTimeoutMs + CommunicationConfig.ResponseTimeoutMs * (_recordInProcess.RetryCtr + 1); //start initial communication or retry OnRecordReadyToSend?.Invoke(this, new ListBytePortDataEventArgs(_recordInProcess.EncodedRequestData)); + + //time reminder of request record var requestTimeUtc = DateTimeOffset.UtcNow; - Int32 responseTimeMs; + Int32 actualResponseWaitTimeMs; //wait for communication acknowledge or until timeout, this also handles the inter record send delay do { //minimum delay is the inter record send delay Thread.Sleep(interRecordSendDelayMs); - var timeoutTimeUtc = DateTimeOffset.UtcNow; - var timeSpan = timeoutTimeUtc - requestTimeUtc; + var actualTimeUtc = DateTimeOffset.UtcNow; + //actual time difference from request to now + var timeSpan = actualTimeUtc - requestTimeUtc; //avoid total milliseconds below zero at time overflow if (timeSpan.TotalMilliseconds < 0) { requestTimeUtc = DateTimeOffset.UtcNow; } - responseTimeMs = (Int32)timeSpan.TotalMilliseconds; + actualResponseWaitTimeMs = (Int32)timeSpan.TotalMilliseconds; } while (_recordInProcess.Acknowledge != RequestAcknowledgeState.Ok && _recordInProcess.SkipRetryErrorCode != _recordInProcess.ResponseErrorCode && - _timeOutMs > responseTimeMs); + _maxTimeOutMs > actualResponseWaitTimeMs); //if timeout value reaches zero, the response hasn't been received or the delay until //next communication needed to be hold - if (_timeOutMs <= responseTimeMs) + if (_maxTimeOutMs <= actualResponseWaitTimeMs) { _logger.Error(_recordInProcess.Acknowledge == RequestAcknowledgeState.NoResponse - ? $"{_ident} Response timeout({responseTimeMs}ms)" - : $"{_ident} Communication delay({responseTimeMs}ms)"); + ? $"{_ident} Response timeout({actualResponseWaitTimeMs}ms)" + : $"{_ident} Communication delay({actualResponseWaitTimeMs}ms)"); } //skip loop to handle re-authorization @@ -395,28 +398,32 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol /// /// - On wakeup message exit this routine. /// + /// + /// - Early exit on _recordInProcess == null, + /// - Wakeup message retries from 5 to 2, + /// - Removed error base from error code decision as error base is only the AppId + /// public override void DecodeRecord(IPortDataEventArgs data) { + if (_recordInProcess == null) return; //new request has to be analyzed _recordInProcess.Acknowledge = RequestAcknowledgeState.NotDecoded; //the request response record covers the entire request protocol var responseRecord = GetTransmitProtocol().DecodeDataForLogicLayer((List)data.GetData()); - //if the current record is invalid or on protocol decoding failure - if (null == _recordInProcess || responseRecord.Count == 0) + //on protocol decoding failure + if (responseRecord.Count == 0) { - if (_recordInProcess != null) - _recordInProcess.Acknowledge = RequestAcknowledgeState.DecodingError; + _recordInProcess.Acknowledge = RequestAcknowledgeState.DecodingError; _logger.Debug($"{_ident} Message decoding error."); //reset timeout to a normal value if timeout is extremely high but response received - if (_timeOutMs > CommunicationConfig.BusyTimeoutMs) - _timeOutMs = CommunicationConfig.BusyTimeoutMs; + if (_maxTimeOutMs > CommunicationConfig.BusyTimeoutMs) + _maxTimeOutMs = CommunicationConfig.BusyTimeoutMs; return; } //avoid wakeup retry on acknowledged record if (responseRecord.Count == WakeupMessage.Length - && null != _recordInProcess && RequestAcknowledgeState.Ok != _recordInProcess.Acknowledge) { // check for wakeup message @@ -431,7 +438,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol { _recordInProcess.Acknowledge = RequestAcknowledgeState.WakeupMessage; //initiate a single retry on wakeup message response - if ( _recordInProcess.WakeupMessageRetryCtr < 5) + if ( _recordInProcess.WakeupMessageRetryCtr < 2) { _recordInProcess.WakeupMessageRetryCtr++; _logger.Debug($"{_ident} Wakeup message({_recordInProcess.WakeupMessageRetryCtr}) received"); @@ -446,8 +453,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol // reset retry counter to get all required retries _recordInProcess.RetryCtr = -1; //reset timeout to a normal value if timeout is extremely high but response received - if (_timeOutMs > CommunicationConfig.BusyTimeoutMs) - _timeOutMs = CommunicationConfig.BusyTimeoutMs; + if (_maxTimeOutMs > CommunicationConfig.BusyTimeoutMs) + _maxTimeOutMs = CommunicationConfig.BusyTimeoutMs; return; } @@ -501,7 +508,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol } //examine error code, if base (AppId) is not 0 the reason 0 may be an error!!!! - if (_recordInProcess.ResponseErrorBase != 0 || _recordInProcess.ResponseErrorReason != 0) + if (/*_recordInProcess.ResponseErrorBase != 0 ||*/ _recordInProcess.ResponseErrorReason != 0) { _logger.Warn($"{_ident} Error code received(0x{_recordInProcess.ResponseErrorBase:X2}" + $"{_recordInProcess.ResponseErrorReason:X2})"); 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