ProductionUiCordonel: - restore listed registers after reboot which didn't survive the reboot
This commit is contained in:
parent
fc9f20814c
commit
8dd636922b
@ -47,6 +47,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// </summary>
|
||||
public List<RecoveryRegisterItem> RecoveryRegisters;
|
||||
|
||||
/// <summary>
|
||||
/// Name of registers which should be restored after reboot if the compare failed.
|
||||
/// </summary>
|
||||
private List<RecoveryRegisterItem> _restoreRegistersAfterReboot;
|
||||
|
||||
/// <summary>
|
||||
/// Marker for restore after reboot parameters
|
||||
/// </summary>
|
||||
public Boolean HasRestoreRegistersAfterRebootIfCompareFailed;
|
||||
|
||||
/// <summary>
|
||||
/// Register content on initial connect to keep those during update
|
||||
/// </summary>
|
||||
@ -100,6 +110,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
"SENSUSRADIO_UpgFWVersion" // After a FW-Update the FW version has changed
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Registers manually explicit marked to be restored after reboot if compare failed. Those registers will
|
||||
/// 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>
|
||||
private static readonly List<String> _restoreAfterRebootIfCompareFailed = new List<String>
|
||||
{
|
||||
"CUSTOMER_AlarmEnableMask" // Restored to hard coded value up to FW R1.4.22
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Registers manually explicit excluded for in-field updatable parameters for the CUST to prevent inadvertent
|
||||
/// modifications resulting in potential MID violations.
|
||||
@ -120,7 +140,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
"FLEXNETSERIAL_FwdlState",
|
||||
"FLEXNETSERIAL_UpgState",
|
||||
|
||||
|
||||
"GENESISFLOW_AmplitudePeakDetectEnd", // 1
|
||||
"GENESISFLOW_ArrowThreshold", // 2
|
||||
"GENESISFLOW_CalFactor1", // 3
|
||||
@ -206,7 +226,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
"PERIODICLOG_PeriodicLogLifeTimeCounter",
|
||||
"PERIODICLOG_ResetCounter",
|
||||
|
||||
"POWERMON_TotalUsedCharge",
|
||||
"POWERMON_TotalUsedCharge",
|
||||
"POWERMON_TotalUsedSeconds",
|
||||
|
||||
"SENSUSRADIO_AverageFlowPeriod", // 1
|
||||
@ -360,6 +380,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
_currentGenesis = currentGenesis;
|
||||
RecoveryRegisters = null;
|
||||
RecoveryRegisters = new List<RecoveryRegisterItem>();
|
||||
_restoreRegistersAfterReboot = new List<RecoveryRegisterItem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -556,7 +577,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fill DEBUG lists START with all registers even if they are multiple assigned
|
||||
// Fill DEBUG lists START with all registers even if they are multiple assigned
|
||||
sortableRegisterList.Add(proPar.RegisterName);
|
||||
|
||||
switch (proPar.Source)
|
||||
@ -572,21 +593,21 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
break;
|
||||
}
|
||||
|
||||
// Take this parameter as is
|
||||
//TODO THW take configuration.json and use for String and Array type, see RegisterConverter
|
||||
//take the register properties from configuration.json
|
||||
//get the pre-defined dictionary
|
||||
//var meterRegisters = MockGenesis based on FW version .GetConfigRegistersDefinitions();
|
||||
//var regDef = meterRegisters.GetRegisterDefinitionByName(proPar.RegisterName);
|
||||
//if (regDef.DataType.Name.Equals("Int32"))
|
||||
//{
|
||||
// Add parameter if it is not in the list
|
||||
//if (sortableProgrammingParameters.All(a => !proPar.RegisterName.Equals(a.RegisterName)))
|
||||
//{
|
||||
// sortableProgrammingParameters.Add(proPar);
|
||||
// continue;
|
||||
//}
|
||||
//}
|
||||
// Take this parameter as is
|
||||
//TODO THW take configuration.json and use for String and Array type, see RegisterConverter
|
||||
//take the register properties from configuration.json
|
||||
//get the pre-defined dictionary
|
||||
//var meterRegisters = MockGenesis based on FW version .GetConfigRegistersDefinitions();
|
||||
//var regDef = meterRegisters.GetRegisterDefinitionByName(proPar.RegisterName);
|
||||
//if (regDef.DataType.Name.Equals("Int32"))
|
||||
//{
|
||||
// Add parameter if it is not in the list
|
||||
//if (sortableProgrammingParameters.All(a => !proPar.RegisterName.Equals(a.RegisterName)))
|
||||
//{
|
||||
// sortableProgrammingParameters.Add(proPar);
|
||||
// continue;
|
||||
//}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@ -780,7 +801,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
return RawProgrammingParametersFilterAndSort(programmingParameters, recoveryRegistersDb, out errorMsg,
|
||||
return RawProgrammingParametersFilterAndSort(programmingParameters, recoveryRegistersDb, out errorMsg,
|
||||
fieldUpdate);
|
||||
}
|
||||
catch (Exception)
|
||||
@ -819,7 +840,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2025-Apr-07" author="Thomas Wiedebusch">
|
||||
/// - CancellationToken.
|
||||
/// </remarks>
|
||||
public StatusReturn EolProgrammingRegisters(List<RecoveryRegisterItem> recoveryRegistersDb,
|
||||
public StatusReturn EolProgrammingRegisters(List<RecoveryRegisterItem> recoveryRegistersDb,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// Mark field update as false to set EOL as true to force accu reset
|
||||
@ -926,7 +947,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// - Remove '_fieldUpdateBlacklist' parameters for the CUST to prevent inadvertent modifications resulting in potential
|
||||
/// MID violations.
|
||||
/// </remarks>
|
||||
public StatusReturn WriteRegisters(List<RecoveryRegisterItem> recoveryRegistersDb, CancellationToken cancellationToken,
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - Login/Logout moved to <see cref="WriteRegisterParameterSet"/>.
|
||||
/// </remarks>
|
||||
public StatusReturn WriteRegisters(List<RecoveryRegisterItem> recoveryRegistersDb, CancellationToken cancellationToken,
|
||||
Boolean fieldUpdate)
|
||||
{
|
||||
if (_currentGenesis == null ||
|
||||
@ -952,11 +976,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
_dbParameterRegisterList = recoveryRegistersDb.Select(register => register.RegisterIdent).ToList();
|
||||
_dbParameterRegisterList.Sort();
|
||||
|
||||
// write values to Genesis
|
||||
_currentGenesis.ReLogin();
|
||||
if (!_currentGenesis.IsLoggedOn)
|
||||
return StatusReturn.Failed;
|
||||
|
||||
// get the pre-defined dictionary
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
|
||||
@ -991,11 +1010,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryPreparation,
|
||||
actualProcessMessage: Resources.StrRegisterRecoveryPreparation));
|
||||
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(_prepareProgramming, recRegistersCount, meterRegisters,
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(_prepareProgramming, recRegistersCount, meterRegisters,
|
||||
cancellationToken, fieldUpdate))
|
||||
{
|
||||
// the logout will force the radio app to activate the settings
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
@ -1003,32 +1020,25 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryExec,
|
||||
actualProcessMessage: Resources.StrRegisterRecoveryExec));
|
||||
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(recoveryRegistersDb, recRegistersCount, meterRegisters,
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(recoveryRegistersDb, recRegistersCount, meterRegisters,
|
||||
cancellationToken, fieldUpdate))
|
||||
{
|
||||
// the logout will force the radio app to activate the settings
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
// finalize recovery
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(Resources.StrRegisterRecoveryFinalization,
|
||||
actualProcessMessage: Resources.StrRegisterRecoveryFinalization));
|
||||
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(finalizeProgrammingAll, recRegistersCount, meterRegisters,
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(finalizeProgrammingAll, recRegistersCount, meterRegisters,
|
||||
cancellationToken, fieldUpdate))
|
||||
{
|
||||
// the logout will force the radio app to activate the settings
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
// remind pcbId of this run to avoid endless repetition
|
||||
_pcbIdWriteRegisters = _currentGenesis.PcbId;
|
||||
|
||||
// the logout will force the radio app to activate the settings
|
||||
_currentGenesis?.Logout();
|
||||
|
||||
// Wait for completion as storing may need a certain time
|
||||
Thread.Sleep(1000);
|
||||
|
||||
@ -1062,19 +1072,20 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2025-Jul-22" author="Thomas Wiedebusch">
|
||||
/// - Excluded un-comparable registers from write turned back on ('blind' writing enabled again).
|
||||
/// </remarks>
|
||||
private StatusReturn WriteRegisterParameterSet(List<RecoveryRegisterItem> recoveryRegistersDb, Int32 recRegistersCount,
|
||||
MeterRegisters meterRegisters, CancellationToken cancellationToken, Boolean fieldUpdate)
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - Login/Logout moved here.
|
||||
/// </remarks>
|
||||
private StatusReturn WriteRegisterParameterSet(List<RecoveryRegisterItem> recoveryRegistersDb,
|
||||
Int32 recRegistersCount, MeterRegisters meterRegisters, CancellationToken cancellationToken, Boolean fieldUpdate)
|
||||
{
|
||||
_currentGenesis.ReLogin();
|
||||
if (!_currentGenesis.IsLoggedOn)
|
||||
return StatusReturn.Failed;
|
||||
|
||||
foreach (var recReg in recoveryRegistersDb)
|
||||
{
|
||||
//TODO THW Check
|
||||
// Temporary excluded un-comparable registers from write as this make no sense to write them blind being
|
||||
// unable to read the correct value back.
|
||||
//if (_excludedFromCompareParameters.Any( regName => recReg.RegisterIdent.Equals(regName)))
|
||||
// continue;
|
||||
|
||||
// Remove all parameters from parameter list if used for field update
|
||||
if (fieldUpdate && _fieldUpdateBlacklist.Any( regName => recReg.RegisterIdent.Equals(regName)))
|
||||
if (fieldUpdate && _fieldUpdateBlacklist.Any(regName => recReg.RegisterIdent.Equals(regName)))
|
||||
continue;
|
||||
|
||||
_actualRegisterCtr++;
|
||||
@ -1099,6 +1110,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
$@"{Resources.StrWriteRegister} {_actualRegisterCtr} / {recRegistersCount}",
|
||||
overallProcessCtrPercent, Resources.StrErrorMsgRegisterNotFound + " Register: " +
|
||||
recReg.RegisterIdent));
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
@ -1115,6 +1127,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(
|
||||
$@"{Resources.StrWriteRegister} {_actualRegisterCtr} / {recRegistersCount}",
|
||||
overallProcessCtrPercent, Resources.StrRegisterValueOutOfRange + " " + errorMessage));
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
}
|
||||
|
||||
@ -1124,6 +1137,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
$@"{Resources.StrWriteRegister} {_actualRegisterCtr} / {recRegistersCount}",
|
||||
overallProcessCtrPercent, Resources.StrErrorMsgRegisterWrite + " Register: " +
|
||||
recReg.RegisterIdent));
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
|
||||
}
|
||||
@ -1149,10 +1163,63 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
break;
|
||||
}
|
||||
|
||||
_currentGenesis?.Logout();
|
||||
return StatusReturn.Okay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore and compare all registers which did not survive a reboot and are listed in the
|
||||
/// <see cref="_restoreAfterRebootIfCompareFailed"/>
|
||||
/// - This is a workaround for a FW-bug in R1.4.22 and below.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - Initial.
|
||||
/// </remarks>
|
||||
public Boolean RestoreAndCompareRegistersAfterReboot(CancellationToken cancellationToken)
|
||||
{
|
||||
if (!HasRestoreRegistersAfterRebootIfCompareFailed)
|
||||
return false;
|
||||
|
||||
HasRestoreRegistersAfterRebootIfCompareFailed = false;
|
||||
|
||||
// Use preset recovery registers for check
|
||||
RecoveryRegisters.Clear();
|
||||
RecoveryRegisters.AddRange(_restoreRegistersAfterReboot);
|
||||
_failedComparisonRegisters.Clear();
|
||||
|
||||
// get the pre-defined dictionary
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
|
||||
_actualRegisterCtr = 0;
|
||||
// Expected access counter is 3 times the content for write, read and compare
|
||||
var maxCounter = 3 * RecoveryRegisters.Count;
|
||||
|
||||
// Write after reboot
|
||||
if (StatusReturn.Failed == WriteRegisterParameterSet(RecoveryRegisters, maxCounter,
|
||||
meterRegisters, cancellationToken, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// executes login read logout
|
||||
if (!ReadPresetRegisters(cancellationToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare register content
|
||||
if (!CompareRegisters(cancellationToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Wait for completion as storing may need a certain time
|
||||
Thread.Sleep(1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare all registers which can be restored without new access to meter.
|
||||
/// Precondition:
|
||||
@ -1203,6 +1270,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2025-Aug-12" author="Thomas Wiedebusch">
|
||||
/// - Take 'null' in readBack into account due to communication error.
|
||||
/// </remarks>
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - _restoreAfterRebootIfCompareFailed.
|
||||
/// </remarks>
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - Made method static.
|
||||
/// </remarks>
|
||||
public Boolean CompareRegisters(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_pcbIdFinalRegisterRead != _pcbIdWriteRegisters ||
|
||||
@ -1214,6 +1287,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
|
||||
// DEBUG
|
||||
_failedComparisonRegisters?.Clear();
|
||||
_restoreRegistersAfterReboot.Clear();
|
||||
|
||||
// build a string list of the registers being able to sort those
|
||||
var registerNames = RecoveryRegisters.Select(register => register.RegisterIdent).ToList();
|
||||
@ -1263,14 +1337,14 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
var writtenValue = recReg.WriteValue;
|
||||
var readBackValue = recReg.ReadBackValue;
|
||||
var strRequiredRegisterValue = "";
|
||||
var isApproximated = false;
|
||||
var isIdentical = false;
|
||||
|
||||
try
|
||||
{
|
||||
// ATTENTION: The size of the writtenValue and readBackValue may deviate!
|
||||
var dataSize = writtenValue.Length;
|
||||
var isApproximated = false;
|
||||
var isIdentical = false;
|
||||
|
||||
|
||||
// Process values only if not 'null'
|
||||
if (writtenValue != null && readBackValue != null)
|
||||
{
|
||||
@ -1331,15 +1405,21 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
}
|
||||
}// Process register values only if not 'null'
|
||||
|
||||
// convert register content to text with raw and converted value depending on data type
|
||||
strRequiredRegisterValue =
|
||||
RegisterConverter.GetRegisterContentText(regDef, writtenValue);
|
||||
// Convert register content to text with raw and converted value depending on data type
|
||||
strRequiredRegisterValue = RegisterConverter.GetRegisterContentText(regDef, writtenValue);
|
||||
|
||||
if (readBackValue != null && (isIdentical || isApproximated))
|
||||
{
|
||||
strRequiredRegisterValue += $" - {Resources.StrRegisterCompareSucceeded}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check registers which should be restored after reboot if failed
|
||||
if (_restoreAfterRebootIfCompareFailed.Any(reg => reg.Equals(regName)))
|
||||
{
|
||||
HasRestoreRegistersAfterRebootIfCompareFailed = true;
|
||||
_restoreRegistersAfterReboot.Add(recReg);
|
||||
}
|
||||
var encryptRawData = regName.Contains("EncryptionKey") || regName.Contains("Password");
|
||||
|
||||
var strReadBackRegisterValue = RegisterConverter.GetRegisterRawText(regDef, readBackValue,
|
||||
@ -1366,7 +1446,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
{
|
||||
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrRegisterCompare}" +
|
||||
$@" {_actualRegisterCtr} / {registersCount}",
|
||||
overallProcessCtrPercent, actualProcessMsg));
|
||||
overallProcessCtrPercent, actualProcessMsg,
|
||||
statusReturn: isIdentical || isApproximated ? StatusReturn.Okay : StatusReturn.Failed));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1427,7 +1508,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
Boolean retVal;
|
||||
try
|
||||
{
|
||||
|
||||
// create a dictionary for final read being able to compare those with the initial read and restored
|
||||
if (!BuildReadableRegisterDictionary(ref _finalRegisters))
|
||||
return false;
|
||||
@ -1525,8 +1605,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
// remind the PCB ID before update for comparison
|
||||
_pcbIdInitialRegisterRead = _currentGenesis.PcbId;
|
||||
|
||||
// create the dictionaries out of the configuration.json
|
||||
if (!BuildReadableRegisterDictionary(ref _initialRegisters))
|
||||
// create a dictionary for final read being able to compare those with the initial read and restored
|
||||
if (!BuildReadableRegisterDictionary(ref _finalRegisters))
|
||||
return false;
|
||||
|
||||
// log to report file the initial register read string
|
||||
@ -1559,14 +1639,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2024-Feb-23" author="Thomas Wiedebusch">
|
||||
/// - Excluded registers which do not contain useful information.
|
||||
/// </remarks>
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - Sequence resorted.
|
||||
/// </remarks>
|
||||
public Boolean BuildReadableRegisterDictionary(ref List<RecoveryRegisterItem> registers)
|
||||
{
|
||||
if (_currentGenesis == null || registers == null)
|
||||
return false;
|
||||
|
||||
registers.Clear();
|
||||
_readableRegisterList.Clear();
|
||||
|
||||
// get the pre-defined dictionary
|
||||
var meterRegisters = _currentGenesis.GetConfigRegistersDefinitions();
|
||||
// extract all registers which can be read and create two dictionaries for before update to safe program
|
||||
@ -1579,11 +1660,14 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
{
|
||||
var registerIdent = reg.Key.GetIdent();
|
||||
registers.Add(new RecoveryRegisterItem(registerIdent, reg.Value));
|
||||
_readableRegisterList.Add(registerIdent);
|
||||
}
|
||||
|
||||
_readableRegisterList.Sort();
|
||||
registers.Sort((a, b) => String.Compare(a.RegisterIdent, b.RegisterIdent, StringComparison.Ordinal));
|
||||
|
||||
// DEBUG information
|
||||
_readableRegisterList.Clear();
|
||||
_readableRegisterList.AddRange(_finalRegisterList);
|
||||
|
||||
return registers.Count > 0;
|
||||
}
|
||||
|
||||
@ -1612,7 +1696,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
// temporary list of registers just for read and log without keeping them alive
|
||||
var registers = new List<RecoveryRegisterItem>();
|
||||
|
||||
if (!BuildReadableRegisterDictionary(ref registers))
|
||||
// create a dictionary for final read being able to compare those with the initial read and restored
|
||||
if (!BuildReadableRegisterDictionary(ref _finalRegisters))
|
||||
return false;
|
||||
|
||||
// log to report file the initial register read string
|
||||
@ -1692,7 +1777,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// <remarks date="2025-Oct-13" author="Thomas Wiedebusch">
|
||||
/// - Date size directly from register object.
|
||||
/// </remarks>
|
||||
private Boolean ReadRegistersSet(ref List<RecoveryRegisterItem> registers, CancellationToken cancellationToken)
|
||||
private Boolean ReadRegistersSet(ref List<RecoveryRegisterItem> registers, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_currentGenesis == null)
|
||||
return false;
|
||||
|
||||
@ -520,10 +520,27 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses
|
||||
/// <remarks date="2024-Jan-17" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
/// <remarks date="2025-Nov-17" author="Thomas Wiedebusch">
|
||||
/// - StatusReturn.
|
||||
/// </remarks>
|
||||
protected void ProcessUpdate_Handler(Object sender, ProcessExecEventArgs e)
|
||||
{
|
||||
ActualProcessProgress++;
|
||||
LogNewStatusMsg(e.ActualProcessMessage);
|
||||
switch (e.StatusReturn)
|
||||
{
|
||||
case StatusReturn.Okay:
|
||||
SuccessMsgDispatcher(e.ActualProcessMessage);
|
||||
break;
|
||||
case StatusReturn.Warning:
|
||||
WarningMsgDispatcher(e.ActualProcessMessage);
|
||||
break;
|
||||
case StatusReturn.Failed:
|
||||
ErrorMsgDispatcher(e.ActualProcessMessage);
|
||||
break;
|
||||
default:
|
||||
LogNewStatusMsg(e.ActualProcessMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -49,6 +49,9 @@ 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">
|
||||
/// - Restore registers after reboot if failed - temporary workaround for FW-bug.
|
||||
/// </remarks>
|
||||
public override StatusReturn ExecuteProcess()
|
||||
{
|
||||
// Uncheck executed process to leave the result open needed for retries
|
||||
@ -98,6 +101,24 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr
|
||||
Meter?.Logout();
|
||||
return StatusReturn.Okay;
|
||||
}
|
||||
|
||||
// Restore registers after reboot if failed
|
||||
if (RegisterRestorer.HasRestoreRegistersAfterRebootIfCompareFailed)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// No chance to repair anything
|
||||
EolProgress.ParametrizationCompareChecked = EOLStatus.FAIL;
|
||||
Meter?.Logout();
|
||||
return StatusReturn.Failed;
|
||||
|
||||
@ -2509,7 +2509,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to WARNING: Inspect results.
|
||||
/// Looks up a localized string similar to WARNING: Parameter restored after reboot as it does not survive it.
|
||||
/// </summary>
|
||||
internal static string StrWarningMsgParameterCompare {
|
||||
get {
|
||||
return ResourceManager.GetString("StrWarningMsgParameterCompare", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to WARNING: Result needs inspection! Process.
|
||||
/// </summary>
|
||||
internal static string StrWarningMsgProcess {
|
||||
get {
|
||||
|
||||
@ -660,6 +660,9 @@
|
||||
</data>
|
||||
<data name="StrErrorMsgParameterCompare" xml:space="preserve">
|
||||
<value>FEHLER: Parametervergleich fehlgeschlagen</value>
|
||||
</data>
|
||||
<data name="StrWarningMsgParameterCompare" xml:space="preserve">
|
||||
<value>WARNUNG: Parameter überlebte den Neustart nicht und wurde danach wiederhergestellt</value>
|
||||
</data>
|
||||
<data name="StrErrorMsgParameterWrite" xml:space="preserve">
|
||||
<value>FEHLER: Parameterschreiben fehlgeschlagen</value>
|
||||
@ -677,7 +680,7 @@
|
||||
<value>WARNUNG</value>
|
||||
</data>
|
||||
<data name="StrWarningMsgProcess" xml:space="preserve">
|
||||
<value>WARNUNG: Ergebnis manuell überprüfen</value>
|
||||
<value>WARNUNG: Ergebnis muß überprüft werden! Prozeß </value>
|
||||
</data>
|
||||
<data name="StrProcessStateAttention" xml:space="preserve">
|
||||
<value>ACHTUNG</value>
|
||||
|
||||
@ -660,6 +660,9 @@
|
||||
</data>
|
||||
<data name="StrErrorMsgParameterCompare" xml:space="preserve">
|
||||
<value>ERROR: Parameter compare failed</value>
|
||||
</data>
|
||||
<data name="StrWarningMsgParameterCompare" xml:space="preserve">
|
||||
<value>WARNING: Parameter restored after reboot as it does not survive it</value>
|
||||
</data>
|
||||
<data name="StrErrorMsgParameterWrite" xml:space="preserve">
|
||||
<value>ERROR: Parameter write failed</value>
|
||||
@ -675,12 +678,12 @@
|
||||
</data>
|
||||
<data name="StrProcessStateWarning" xml:space="preserve">
|
||||
<value>WARNING</value>
|
||||
</data>
|
||||
<data name="StrWarningMsgProcess" xml:space="preserve">
|
||||
<value>WARNING: Result needs inspection! Process</value>
|
||||
</data>
|
||||
<data name="StrProcessStateAttention" xml:space="preserve">
|
||||
<value>ATTENTION</value>
|
||||
</data>
|
||||
<data name="StrWarningMsgProcess" xml:space="preserve">
|
||||
<value>WARNING: Inspect results</value>
|
||||
</data>
|
||||
<data name="StrLblSpecialRequirement" xml:space="preserve">
|
||||
<value>SPECIAL APPROVAL</value>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Xylem.Common.CommonCore.Consts;
|
||||
|
||||
namespace Xylem.Common.Utils.ProcessExec.EventArguments
|
||||
{
|
||||
@ -28,6 +29,11 @@ namespace Xylem.Common.Utils.ProcessExec.EventArguments
|
||||
/// </summary>
|
||||
public Double? ActualProcessPercent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Single process percentage 0..100
|
||||
/// </summary>
|
||||
public StatusReturn StatusReturn { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Ctor
|
||||
/// </summary>
|
||||
@ -35,9 +41,10 @@ namespace Xylem.Common.Utils.ProcessExec.EventArguments
|
||||
/// <param name="overallProcessPercent"></param>
|
||||
/// <param name="actualProcessMessage"></param>
|
||||
/// <param name="actualProcessPercent"></param>
|
||||
/// <param name="statusReturn"></param>
|
||||
public ProcessExecEventArgs(String overallProcessMessage,
|
||||
Double? overallProcessPercent = null, String actualProcessMessage = null,
|
||||
Double? actualProcessPercent = null)
|
||||
Double? actualProcessPercent = null, StatusReturn statusReturn = StatusReturn.Unknown)
|
||||
{
|
||||
OverallProcessMessage = overallProcessMessage;
|
||||
ActualProcessMessage = actualProcessMessage;
|
||||
@ -45,6 +52,7 @@ namespace Xylem.Common.Utils.ProcessExec.EventArguments
|
||||
OverallProcessPercent = OverallProcessPercent < 0 ? 0 : OverallProcessPercent;
|
||||
ActualProcessPercent = actualProcessPercent > 100.0 ? 100.0 : actualProcessPercent;
|
||||
ActualProcessPercent = ActualProcessPercent < 0 ? 0 : ActualProcessPercent;
|
||||
StatusReturn = statusReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user