diff --git a/Common/Common.sln.DotSettings b/Common/Common.sln.DotSettings index 9421a131..77a48996 100644 --- a/Common/Common.sln.DotSettings +++ b/Common/Common.sln.DotSettings @@ -48,6 +48,7 @@ True True True + True True True @@ -59,6 +60,7 @@ True True True + True True True True @@ -70,6 +72,7 @@ True True True + True True True True diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs index eebd89ba..d7f940f1 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs @@ -115,6 +115,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// temporary setup values which do not survive a reboot. This is done to overcome a FW-bug which overwrites /// those values after the reboot procedure! /// + /// + /// - Initial to restore values which do not survive the reboot as workaround for R1.4.22 and below. + /// private static readonly List _restoreAfterRebootIfCompareFailed = new List { "CUSTOMER_AlarmEnableMask" // Restored to hard coded value up to FW R1.4.22 @@ -129,6 +132,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// All commands defined here will not be accepted from 'external' to adjust. Program internally, those /// commands are potentially allowed if those do not change any MID dependent 'values'. /// + /// + /// - SENSUSRADIO_WakeupInterval added to keep radio active after field update if it was active before. + /// private static readonly List _fieldUpdateBlacklist = new List { "CUSTOMER_AlarmVisualMask", @@ -252,6 +258,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore "SENSUSRADIO_Tfx_Structure", //21 "SENSUSRADIO_UpgFWVersion", //22 "SENSUSRADIO_UtcTimeOffset", //23 + "SENSUSRADIO_WakeupInterval", //24 "SYSTEM_CalendarSeconds", // 1 "SYSTEM_CheckPresence", // 2 diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs index 2a29ebca..c422336a 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterResetPsu.cs @@ -74,7 +74,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile // position of version string private const Int32 FlexVersionStringIndex = 0x66; - private Int32 _processRetryCtr; private IGenesisMeter _genesisMeter; @@ -101,6 +100,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// public Boolean StoreConfigEnable = true; + /// + /// Threshold to waste the HW if reboots too high + /// + public const Int32 MAX_REBOOTS_FOR_HEALTHY_HW = 4; + #endregion #region Events diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs index f21ab7c6..ecda626e 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckFinalParametrization.cs @@ -14,7 +14,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// Ctor /// - public CheckFinalParametrization(String name) : base( name) + public CheckFinalParametrization(String name) : base(name) { } @@ -49,7 +49,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - CancellationToken. /// - /// + /// /// - Restore registers after reboot if failed - temporary workaround for FW-bug. /// public override StatusReturn ExecuteProcess() @@ -86,7 +86,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr RegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler; var retValBol = RegisterRestorer.FinalReadRegisters(CancellationToken); RegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler; - + // Exit if meanwhile cancellation is required if (CancellationToken.IsCancellationRequested) return CancellationProcedure(); @@ -105,13 +105,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Restore registers after reboot if failed if (RegisterRestorer.HasRestoreRegistersAfterRebootIfCompareFailed) { + WarningMsgDispatcher(Resources.StrWarningMsgParameterCompare); // Write and compare those registers RegisterRestorer.OnProcessUpdate += ProcessUpdate_Handler; retValBol = RegisterRestorer.RestoreAndCompareRegistersAfterReboot(CancellationToken); RegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler; if (retValBol) { - WarningMsgDispatcher(Resources.StrWarningMsgParameterCompare); EolProgress.ParametrizationCompareChecked = EOLStatus.OK; Meter?.Logout(); return StatusReturn.Warning; diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs index c102fe5a..6d35f68c 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecRebootCordonel.cs @@ -51,6 +51,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Accumulator reset if setting to zero failed as defined by A.F. as workaround for FW bug. /// + /// + /// - Threshold for allowed reboots to detect erroneous hardware. + /// public override StatusReturn ExecuteProcess() { // Uncheck executed process to leave the result open needed for retries @@ -77,7 +80,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr return StatusReturn.Failed; } } - var ale = Meter.ReadRegister("CUSTOMER_AlarmEnableMask"); + // Read and automatically log it to database if logging is active + Meter.ReadRegister("CUSTOMER_AlarmEnableMask"); + #region ----------------------------------- Reboot ---------------------------------------------------- // reboot the meter and avoid doubled storage of configurations var _meterResetPsu = new MeterResetPsu(Meter) @@ -107,6 +112,18 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr } } ActualProcessProgress++; + #endregion + #region ----------------------------------- Check reboot count ---------------------------------------- + // Read reboot count and compare with hardcoded maximum value + var rebootCount = + RegisterConverter.ByteArrayToValue(Meter.ReadRegister("CUSTOMER_RebootCount")); + if (rebootCount >= MeterResetPsu.MAX_REBOOTS_FOR_HEALTHY_HW) + { + ErrorMsgDispatcher(Resources.StrErrorMsgTooManyReboots); + EolProgress.RebootDoneChecked = EOLStatus.FAIL; + return StatusReturn.Failed; + } + #endregion #region ----------------------------------- Set Time and Reset Counters ------------------------------- // Get the time in UTC to program the time for the Cordonel in seconds since 01. Jan 2000 @@ -123,7 +140,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr ProgrammingSource.ProgramInternal)); ActualProcessProgress++; // Reset reboot counter - retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("CUSTOMER_RebootCount", + retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("CUSTOMER_RebootCount", new Byte[] { 0x00 }, ProgrammingSource.ProgramInternal)); // Reset alarms Customer retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("CUSTOMER_TriggerAlarmCancel", @@ -173,11 +190,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr var retryCtr = 2; // Check all values for 0 after reset and followed reboot which may use the - var readBackScaledBilling = + var readBackScaledBilling = RegisterConverter.ByteArrayToValue(Meter.ReadRegister("GENESISFLOW_ScaledBilling")); - var readBackUnscaledFwd = + var readBackUnscaledFwd = RegisterConverter.ByteArrayToValue(Meter.ReadRegister("GENESISFLOW_UnscaledFwd")); - var readBackUnscaledRev = + var readBackUnscaledRev = RegisterConverter.ByteArrayToValue(Meter.ReadRegister("GENESISFLOW_UnscaledRev")); while (retryCtr-- > 0 && @@ -186,11 +203,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Backup sealing state as for the NA region it may be unsealed var displaySealingState = RegisterConverter.ByteArrayToValue(Meter.ReadRegister("GENESISFLOW_SealDisplay")); - + // Unseal accumulator reset capability retValBol = WriteRegisterLogAndProcessCtr(new ProgrammingParameters("GENESISFLOW_SealDisplay", new Byte[] { 0x00 }, ProgrammingSource.ProgramInternal)); - + // Reset accumulators again retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("GENESISFLOW_ResetAccumulators", new Byte[] { 0x01 }, ProgrammingSource.ProgramInternal)); @@ -201,7 +218,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // it doesn't have to be a change. retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("GENESISFLOW_ForwardArrow", new[] { forwardArrow }, ProgrammingSource.ProgramInternal)); - + // Seal accumulator reset capability // ReSharper disable once RedundantAssignment as it is used for DEBUG retValBol &= WriteRegisterLogAndProcessCtr(new ProgrammingParameters("GENESISFLOW_SealDisplay", @@ -224,7 +241,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr EolProgress.RebootDoneChecked = EOLStatus.FAIL; return StatusReturn.Failed; } -#endregion + #endregion SuccessMsgDispatcher(Resources.StrSuccessMsgAlarmReset); EolProgress.RebootDoneChecked = EOLStatus.OK; return StatusReturn.Okay; diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs b/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs index 9e1c3880..c7e5eb18 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs @@ -1050,6 +1050,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to ERROR: Hardware reboots higher than allowed threshold. + /// + internal static string StrErrorMsgTooManyReboots { + get { + return ResourceManager.GetString("StrErrorMsgTooManyReboots", resourceCulture); + } + } + /// /// Looks up a localized string similar to ERROR: Firmware is not supported. /// diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx b/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx index 3feb62b5..944704e0 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx @@ -681,6 +681,9 @@ WARNUNG: Ergebnis muß überprüft werden! Prozeß + + + FEHLER: Hardwareneustarts über der erlaubten Grenze ACHTUNG diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.resx b/Common/Production/ProductionUiCordonel/Properties/Resources.resx index c7247541..83b62502 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.resx +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.resx @@ -681,6 +681,9 @@ WARNING: Result needs inspection! Process + + + ERROR: Hardware reboots higher than allowed threshold ATTENTION diff --git a/Common/Ui/GenesisToolBox/FrmFwUpdate.cs b/Common/Ui/GenesisToolBox/FrmFwUpdate.cs index a4d21598..d8d9088b 100644 --- a/Common/Ui/GenesisToolBox/FrmFwUpdate.cs +++ b/Common/Ui/GenesisToolBox/FrmFwUpdate.cs @@ -1486,33 +1486,6 @@ namespace Xylem.Common.Ui.GenesisToolBox { return; } - - - - //_currentGenesis.WriteRegister("POWERMON_BatteryQuantity", 2, true, true); - //_currentGenesis.WriteRegister("POWERMON_StoreConfiguration", 1, true, true); - //var genesisStatus = new GenesisStatus(); - //if (GenesisStatusHandler.BuildLifeTimeInformation(_currentGenesis, genesisStatus)) - //{ - - // var sbMSG = new StringBuilder(); - // sbMSG.AppendLine($"Pcb = {_currentGenesis.PcbId}"); - - // sbMSG.AppendLine($"POWERMON_TotalUsedSeconds = {genesisStatus.ExceededLifeTime_s}"); - // sbMSG.AppendLine($"POWERMON_TotalUsedCharge = {genesisStatus.DrainedBatteryLoad_uAs}"); - // sbMSG.AppendLine($"POWERMON_BatteryQuantity = {genesisStatus.BatteryQuantity}"); - // sbMSG.AppendLine($"POWERMON_BatteryMilliAHrRating = {genesisStatus.InitialBatteryLoad_mAh}"); - // sbMSG.AppendLine(""); - // sbMSG.AppendLine($"Remaining lifetime in years {genesisStatus.RemainingLifeTimeYears:F2}"); - // sbMSG.AppendLine($"Totally drained battery load in % {genesisStatus.DrainedBatteryLoadPercent:F2}"); - // _currentGenesis.WriteLog(sbMSG.ToString()); - // MessageBox.Show(sbMSG.ToString(), $"Battery for {_currentGenesis.PcbId} has remaining life " + - // $"time of {genesisStatus.RemainingLifeTimeYears:F2} years"); - //} - //else - //{ - // MessageBox.Show("Failed to get life time information"); - //} _currentGenesis.RequestProtocol.AdditionalRetryTimeoutMs = addRetryTimeoutMs; Task.Factory.StartNew(() =>