ProductionUiCoprdonel: - reboot threshold 4 in ExecRebootCOrdonel

This commit is contained in:
Thomas Wiedebusch 2025-11-18 12:17:43 +01:00
parent 8dd636922b
commit 2c6927cc65
9 changed files with 60 additions and 41 deletions

View File

@ -48,6 +48,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Flowrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fwdl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=GENESISFLOW/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Gensis/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=GENSISFLOW/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Irda/@EntryIndexedValue">True</s:Boolean>
@ -59,6 +60,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Milli/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Modbus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=MOXA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=naproduct/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=OPTICALINTERFACE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCBID/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=perc/@EntryIndexedValue">True</s:Boolean>
@ -70,6 +72,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pwds/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=restorable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=RFID/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=rowproduct/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sensus/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=SENSUSRADIO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sirt/@EntryIndexedValue">True</s:Boolean>

View File

@ -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!
/// </summary>
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
/// - Initial to restore values which do not survive the reboot as workaround for R1.4.22 and below.
/// </remarks>
private static readonly List<String> _restoreAfterRebootIfCompareFailed = new List<String>
{
"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'.
/// </summary>
/// <remarks date="2025-Nov-18" author="Thomas Wiedebusch">
/// - SENSUSRADIO_WakeupInterval added to keep radio active after field update if it was active before.
/// </remarks>
private static readonly List<String> _fieldUpdateBlacklist = new List<String>
{
"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

View File

@ -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
/// </summary>
public Boolean StoreConfigEnable = true;
/// <summary>
/// Threshold to waste the HW if reboots too high
/// </summary>
public const Int32 MAX_REBOOTS_FOR_HEALTHY_HW = 4;
#endregion
#region Events

View File

@ -14,7 +14,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
/// <summary>
/// Ctor
/// </summary>
public CheckFinalParametrization(String name) : base( name)
public CheckFinalParametrization(String name) : base(name)
{
}
@ -49,7 +49,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
/// <remarks date="2025-Apr-07" author="Thomas Wiedebusch">
/// - CancellationToken.
/// </remarks>
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
/// <remarks date="2025-Nov-17..18" author="Thomas Wiedebusch">
/// - Restore registers after reboot if failed - temporary workaround for FW-bug.
/// </remarks>
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;

View File

@ -51,6 +51,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
/// <remarks date="2025-Sep-22" author="Thomas Wiedebusch">
/// - Accumulator reset if setting to zero failed as defined by A.F. as workaround for FW bug.
/// </remarks>
/// <remarks date="2025-Nov-18" author="Thomas Wiedebusch">
/// - Threshold for allowed reboots to detect erroneous hardware.
/// </remarks>
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<UInt32>(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<Int64>(Meter.ReadRegister("GENESISFLOW_ScaledBilling"));
var readBackUnscaledFwd =
var readBackUnscaledFwd =
RegisterConverter.ByteArrayToValue<UInt64>(Meter.ReadRegister("GENESISFLOW_UnscaledFwd"));
var readBackUnscaledRev =
var readBackUnscaledRev =
RegisterConverter.ByteArrayToValue<UInt64>(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<Byte>(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;

View File

@ -1050,6 +1050,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to ERROR: Hardware reboots higher than allowed threshold.
/// </summary>
internal static string StrErrorMsgTooManyReboots {
get {
return ResourceManager.GetString("StrErrorMsgTooManyReboots", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ERROR: Firmware is not supported.
/// </summary>

View File

@ -681,6 +681,9 @@
</data>
<data name="StrWarningMsgProcess" xml:space="preserve">
<value>WARNUNG: Ergebnis muß überprüft werden! Prozeß </value>
</data>
<data name="StrErrorMsgTooManyReboots" xml:space="preserve">
<value>FEHLER: Hardwareneustarts über der erlaubten Grenze</value>
</data>
<data name="StrProcessStateAttention" xml:space="preserve">
<value>ACHTUNG</value>

View File

@ -681,6 +681,9 @@
</data>
<data name="StrWarningMsgProcess" xml:space="preserve">
<value>WARNING: Result needs inspection! Process</value>
</data>
<data name="StrErrorMsgTooManyReboots" xml:space="preserve">
<value>ERROR: Hardware reboots higher than allowed threshold</value>
</data>
<data name="StrProcessStateAttention" xml:space="preserve">
<value>ATTENTION</value>

View File

@ -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(() =>