RegisterRestorer

This commit is contained in:
Thomas Wiedebusch 2024-02-08 14:38:30 +01:00
parent 6b3bef9bd1
commit 1fccafccac

View File

@ -59,7 +59,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <summary>
/// Register which shall be restored after change of FW or after register recovery
/// </summary>
private readonly MeterRegisters _restoreRegisters = new MeterRegisters();
private readonly MeterRegisters _recoveryRegisters = new MeterRegisters();
/// <summary>
/// Register access event for message dispatcher to caller
@ -80,8 +80,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// </summary>
private static readonly List<String> _excludedFromCompareParameters = new List<String>
{
"SENSUSRADIO_UpgFWVersion", // After a FW-Update the FW version has changed and the compare will fail
"IRDA_MfgDate" // After a FW-Update the date has changed and the compare will fail
"SENSUSRADIO_UpgFWVersion" // After a FW-Update the FW version has changed and the compare will fail
};
/// <summary>
/// Pre programming parameters for all devices defined here, will be filled with radio parameters
@ -94,11 +93,20 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
};
/// <summary>
/// Pre programming parameters for all devices defined here, will be filled with radio parameters
/// if meter has radio
///
/// </summary>
// ReSharper disable once CollectionNeverQueried.Global IS FOR DEBUG
public readonly List<RecoveryRegisterItem> FailedComparisonRegisters = new List<RecoveryRegisterItem>();
// ReSharper disable once CollectionNeverQueried.Local IS FOR DEBUG
private readonly List<RecoveryRegisterItem> _failedComparisonRegisters = new List<RecoveryRegisterItem>();
/// <summary>
///
/// </summary>
// ReSharper disable once CollectionNeverQueried.Local IS FOR DEBUG
private List<String> _dbParameterRegisterList = new List<String>();
private readonly List<String> _recoveryRegisterList = new List<String>();
private List<String> _initialRegisterList = new List<String>();
private List<String> _finalRegisterList = new List<String>();
/// <summary>
/// Post programming parameters for radio only
@ -106,6 +114,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
private static readonly List<RecoveryRegisterItem> _finalizeProgrammingRadioOnly = new List<RecoveryRegisterItem>
{
new RecoveryRegisterItem("LOGGER_TriggerLogFlush", new Byte[] { 0x01 }),
// set counter to 0 as this is a value how often the radio detected a reset
new RecoveryRegisterItem("PERIODICLOG_ResetCounter", new Byte[] { 0x00 }),
// System state 0xFF will force a storage of all parameters and reset, followed by system state 0x02
// for customer mode, the reset needs only a few milliseconds
@ -119,6 +128,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
private static readonly List<RecoveryRegisterItem> _finalizeProgramming = new List<RecoveryRegisterItem>
{
new RecoveryRegisterItem("GENESISFLOW_SealDisplay", new Byte[] { 0x01 }),
// trigger idle 0 releases the display to normal operation
new RecoveryRegisterItem("GENESISFLOW_TriggerIdle", new Byte[] { 0x00 }),
};
@ -128,7 +138,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
private static readonly List<RecoveryRegisterItem> _finalizeProgrammingEol = new List<RecoveryRegisterItem>
{
new RecoveryRegisterItem("GENESISFLOW_ResetAccumulators", new Byte[] { 0x01 }),
new RecoveryRegisterItem("NFC_EraseRMA", new Byte[] { 0x01 })
new RecoveryRegisterItem("NFC_EraseRMA", new Byte[] { 0x01 }),
new RecoveryRegisterItem("CUSTOMER_RebootCount", new Byte[] {0x00})
};
/// <summary>
@ -386,6 +397,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
StopRegisterAccess = false;
ActualRegisterCtr = 0;
// Build string list for debug
_dbParameterRegisterList.Clear();
_dbParameterRegisterList = recoveryRegistersDb.Select(register => register.RegisterIdent).ToList();
_dbParameterRegisterList.Sort();
// write values to Genesis
_currentGenesis.ReLogin();
if (!_currentGenesis.IsLoggedOn)
@ -400,7 +416,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
finalizeProgrammingAll.AddRange(_finalizeProgrammingRadioOnly);
}
// add EOL sequence if called
// add EOL (shipping reset of accumulators, alarms and setup of manufacturing date)
if (eolProgramming)
{
finalizeProgrammingAll.AddRange(_finalizeProgrammingEol);
@ -480,7 +496,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, recReg.WriteValue);
// replace value in _restoreRegister with the required recovery value
_restoreRegisters?.Set(regDef, recReg.WriteValue);
_recoveryRegisters?.Set(regDef, recReg.WriteValue);
}
catch (Exception ex)
@ -585,17 +601,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
public Boolean CompareRegisters()
{
if (_pcbIdFinalRegisterRead != _pcbIdInitialRegisterRead ||
_restoreRegisters == null ||
_recoveryRegisters == null ||
_finalReadRegisters == null)
return false;
StopRegisterAccess = false;
ActualRegisterCtr = 0;
var retVal = true;
FailedComparisonRegisters?.Clear();
_failedComparisonRegisters?.Clear();
// build a string list of the registers being able to sort those
var registerNames = _restoreRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
var registerNames = _recoveryRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
// Remove all excluded registers
foreach (var regName in _excludedFromCompareParameters.Where(regName => registerNames.Any(reg => reg == regName)))
{
@ -611,14 +627,14 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
{
ActualRegisterCtr++;
var regDef = _restoreRegisters.GetRegisterDefinitionByName(regName);
var regDef = _recoveryRegisters.GetRegisterDefinitionByName(regName);
var overallProcessCtrPercent = 100.0 * ActualRegisterCtr / registersCount;
try
{
// Get the raw byte array of this register
var restorableRawRegister = _restoreRegisters.Get(regName);
var restorableRawRegister = _recoveryRegisters.Get(regName);
var finalReadRawRegister = _finalReadRegisters.Get(regName);
// take the size into account as a read value will be filled up to a chunk of 4 bytes
@ -702,7 +718,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
strRequiredRegisterValue += $" - {Resources.StrMeterValue}: ({strReadBackRegisterValue})" +
$" - {Resources.StrRegisterCompareFailed}";
FailedComparisonRegisters?.Add(new RecoveryRegisterItem(regName, restorableRawRegister,
_failedComparisonRegisters?.Add(new RecoveryRegisterItem(regName, restorableRawRegister,
finalReadRawRegister));
retVal = false;
}
@ -779,6 +795,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
Resources.StrReadRegistersAfterUpdate));
// Build string list for debug
_finalRegisterList.Clear();
_finalRegisterList = _finalReadRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
_finalRegisterList.Sort();
// executes login read logout
return ReadRegistersSet(_finalReadRegisters);
}
@ -819,13 +840,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
// deny update of registers if already done
if (_pcbIdInitialRegisterRead == _currentGenesis.PcbId &&
_initialReadRegisters.MeterRegisterDic.Count > 0 &&
_restoreRegisters.MeterRegisterDic.Count > 0)
_recoveryRegisters.MeterRegisterDic.Count > 0)
return true;
// remind the PCB ID before update for comparison
_pcbIdInitialRegisterRead = _currentGenesis.PcbId;
_initialReadRegisters.MeterRegisterDic.Clear();
_restoreRegisters.MeterRegisterDic.Clear();
// create the dictionaries out of the configuration.json
if (!BuildInitialDictionaries())
@ -835,7 +854,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($@"{Resources.StrReadRegister}", 0,
Resources.StrReadRegistersBeforeUpdate));
return ReadRegistersSet(_initialReadRegisters, _restoreRegisters);
return ReadRegistersSet(_initialReadRegisters, _recoveryRegisters);
}
/// <summary>
@ -854,8 +873,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
if (_currentGenesis == null)
return false;
_initialReadRegisters.MeterRegisterDic.Clear();
_restoreRegisters.MeterRegisterDic.Clear();
_recoveryRegisters.MeterRegisterDic.Clear();
_recoveryRegisterList.Clear();
// create a dictionary for initial read being able to compare those with the final read and restored
if (!BuildReadableRegisterDictionary(ref _initialReadRegisters))
@ -867,10 +886,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
r.Key.RestoreCapability.CheckRestoreCapability() &&
r.Key.RegisterDetail.Privilege.Lvl8 == Access.RW))
{
_restoreRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
_recoveryRegisters.MeterRegisterDic.TryAdd(reg.Key, reg.Value);
_recoveryRegisterList.Add(reg.Key.GetIdent());
}
_recoveryRegisterList.Sort();
return _restoreRegisters.MeterRegisterDic.Count > 0 && _initialReadRegisters.MeterRegisterDic.Count > 0;
// Build string list for debug
_initialRegisterList.Clear();
_initialRegisterList = _initialReadRegisters.MeterRegisterDic.Select(register => register.Key.GetIdent()).ToList();
_initialRegisterList.Sort();
return _recoveryRegisters.MeterRegisterDic.Count > 0 && _initialReadRegisters.MeterRegisterDic.Count > 0;
}
/// <summary>
@ -885,7 +911,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <remarks date="2024-Jan-22" author="Thomas Wiedebusch">
/// - Initial from <see cref="InitialReadRegisters"/>.
/// </remarks>
public Boolean BuildReadableRegisterDictionary(ref MeterRegisters registers)
private Boolean BuildReadableRegisterDictionary(ref MeterRegisters registers)
{
if (_currentGenesis == null || registers?.MeterRegisterDic == null)
return false;