diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs
index c65257fc..1b6cbcf8 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
+using System.Threading;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
@@ -139,6 +140,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
// Text for caller to inform about actual process being carried out
private String _actualOperation;
private FwUpdateState _fwUpdateState;
+ private FwUpdateState _fwBackupUpdateState;
// Process counter for caller to monitor actual progress
private Int32 _processedBytesCtr;
@@ -713,6 +715,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
///
/// - Exit preparation added
///
+ ///
+ /// - Introduced lock for repeated execution of state machine
+ ///
public Boolean UpdateMeterFw()
{
if (!UpdatePreparation())
@@ -721,6 +726,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
}
_fwUpdateState = FwUpdateState.StartInitial;
+ _fwBackupUpdateState = FwUpdateState.Idle;
while (_fwUpdateState != FwUpdateState.Idle && !StopUpdateProcess)
{
FwUpdateStateMachine();
@@ -886,6 +892,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
//set state machine for automatic FW update
_fwUpdateState = FwUpdateState.Idle;
+ _fwBackupUpdateState = FwUpdateState.Idle;
_actualOperation = "";
//update file information
@@ -1040,97 +1047,110 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// useful as on increased size and number of applications needed to install in one run, the
/// file system is slowing down for write accesses.
///
+ ///
+ /// - Introduced lock for repeated execution of state machine
+ ///
private void FwUpdateStateMachine()
{
- switch (_fwUpdateState)
+ if (_fwBackupUpdateState == _fwUpdateState)
{
- case FwUpdateState.Idle:
- break;
-
- case FwUpdateState.StartInitial:
- _updateProcedureRetryCtr = 0;
- _fwUpdateState = FwUpdateState.BuildFileApps;
- break;
-
- case FwUpdateState.BuildFileApps:
- if (!SingleFilePartsRetryEnable && !ConsecutiveFilePartsRetryEnable)
- {
- _remainingFileAppsParts.Clear();
- }
-
- BuildFileApps();
- _fwUpdateState = FwUpdateState.DownloadFileApps;
- break;
-
- case FwUpdateState.DownloadFileApps:
- _fwUpdateState = DownloadFileApps()
- ? FwUpdateState.BuildUpgradeControlFile
- : FwUpdateState.StepFailed;
- break;
-
- case FwUpdateState.BuildUpgradeControlFile:
- //prepare the trigger to select all successfully downloaded applications
- PrepareTrigger();
- _fwUpdateState = BuildUpgradeCtrlFile()
- ? FwUpdateState.DownloadUpgradeControlFile
- : FwUpdateState.StepFailed;
- break;
-
- case FwUpdateState.DownloadUpgradeControlFile:
- _fwUpdateState = DownloadUpgradeCtrlFile()
- ? FwUpdateState.TriggerUpgrade
- : FwUpdateState.StepFailed;
- break;
-
- case FwUpdateState.TriggerUpgrade:
- _fwUpdateState = TriggerUpgrade() ? FwUpdateState.Idle : FwUpdateState.StepFailed;
- break;
-
- case FwUpdateState.StepFailed:
- _processedBytesCtr = 0;
- _overallBytesCtr = 0;
- //retry entire file if some partial file writes failed
- if (RetryEntireFileAfterFailedPartialRetries == _updateProcedureRetryCtr)
- {
- _remainingFileAppsParts.Clear();
- }
-
- _fwUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
- ? FwUpdateState.RepeatFwUpdate
- : FwUpdateState.UpdateFailed;
- break;
-
- case FwUpdateState.RepeatFwUpdate:
- _processedBytesCtr = 0;
- _overallBytesCtr = 0;
- _fwUpdateState = FwUpdateState.BuildFileApps;
- if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
- {
- _meterFile?.SetExtremeFileWriteTimeout();
- }
- break;
-
- case FwUpdateState.UpdateFailed:
- _processedBytesCtr = 0;
- _overallBytesCtr = 0;
- StopUpdateProcess = true;
- _fwUpdateState = FwUpdateState.Idle;
- break;
-
- case FwUpdateState.UploadFileApps:
- break;
-
- case FwUpdateState.CompareFileApps:
- break;
-
- case FwUpdateState.EraseUpdateFile:
- break;
-
- default:
- _fwUpdateState = FwUpdateState.Idle;
- break;
-
+ Thread.Sleep(1);
}
+ else
+ {
+ // remind backup state to avoid repeated execution and side effects
+ _fwBackupUpdateState = _fwUpdateState;
+ switch (_fwUpdateState)
+ {
+ case FwUpdateState.Idle:
+ break;
+
+ case FwUpdateState.StartInitial:
+ _updateProcedureRetryCtr = 0;
+ _fwUpdateState = FwUpdateState.BuildFileApps;
+ break;
+
+ case FwUpdateState.BuildFileApps:
+ if (!SingleFilePartsRetryEnable && !ConsecutiveFilePartsRetryEnable)
+ {
+ _remainingFileAppsParts.Clear();
+ }
+
+ BuildFileApps();
+ _fwUpdateState = FwUpdateState.DownloadFileApps;
+ break;
+
+ case FwUpdateState.DownloadFileApps:
+ _fwUpdateState = DownloadFileApps()
+ ? FwUpdateState.BuildUpgradeControlFile
+ : FwUpdateState.StepFailed;
+ break;
+
+ case FwUpdateState.BuildUpgradeControlFile:
+ //prepare the trigger to select all successfully downloaded applications
+ PrepareTrigger();
+ _fwUpdateState = BuildUpgradeCtrlFile()
+ ? FwUpdateState.DownloadUpgradeControlFile
+ : FwUpdateState.StepFailed;
+ break;
+
+ case FwUpdateState.DownloadUpgradeControlFile:
+ _fwUpdateState = DownloadUpgradeCtrlFile()
+ ? FwUpdateState.TriggerUpgrade
+ : FwUpdateState.StepFailed;
+ break;
+
+ case FwUpdateState.TriggerUpgrade:
+ _fwUpdateState = TriggerUpgrade() ? FwUpdateState.Idle : FwUpdateState.StepFailed;
+ break;
+
+ case FwUpdateState.StepFailed:
+ _processedBytesCtr = 0;
+ _overallBytesCtr = 0;
+ //retry entire file if some partial file writes failed
+ if (RetryEntireFileAfterFailedPartialRetries == _updateProcedureRetryCtr)
+ {
+ _remainingFileAppsParts.Clear();
+ }
+
+ _fwUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
+ ? FwUpdateState.RepeatFwUpdate
+ : FwUpdateState.UpdateFailed;
+ break;
+
+ case FwUpdateState.RepeatFwUpdate:
+ _processedBytesCtr = 0;
+ _overallBytesCtr = 0;
+ _fwUpdateState = FwUpdateState.BuildFileApps;
+ if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
+ {
+ _meterFile?.SetExtremeFileWriteTimeout();
+ }
+
+ break;
+
+ case FwUpdateState.UpdateFailed:
+ _processedBytesCtr = 0;
+ _overallBytesCtr = 0;
+ StopUpdateProcess = true;
+ _fwUpdateState = FwUpdateState.Idle;
+ break;
+
+ case FwUpdateState.UploadFileApps:
+ break;
+
+ case FwUpdateState.CompareFileApps:
+ break;
+
+ case FwUpdateState.EraseUpdateFile:
+ break;
+
+ default:
+ _fwUpdateState = FwUpdateState.Idle;
+ break;
+
+ }
+ }// lock repeated execution of identical state
}
#endregion
diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs
index f224d0f6..75dbd293 100644
--- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs
+++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
+using System.Threading;
using Logic.ProductionToProductMapper.Cordonel;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
+using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
@@ -85,6 +88,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
// Text for caller to inform about actual process being carried out
private String _actualOperation;
private LutUpdateState _lutUpdateState;
+ private LutUpdateState _lutBackupUpdateState;
// Look up table file
public MeterLutFile LutFile;
@@ -100,6 +104,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
// error message for display of error reason
public String ErrorMessage;
+
+ ///
+ /// Register subset needed to adjust for update performance content before update
+ ///
+ private readonly Dictionary _registersBeforeUpdate = new Dictionary();
+
+ ///
+ /// Register to restore after update
+ ///
+ private Dictionary _registersAfterUpdate = new Dictionary();
+
#endregion
#region Events
@@ -154,6 +169,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
{
if (genesisMeter == null) return;
AssignGenesis(genesisMeter);
+
+ if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "GENESISFLOW" && f.IsInstalled))
+ {
+ _registersBeforeUpdate.Add(Register.Genesisflow.LedMode, new[] {(Byte) LedMode.Off});
+ _registersBeforeUpdate.Add(Register.Genesisflow.SampleRate, new Byte[] {1});
+ }
+ if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "METROLOGYASST" && f.IsInstalled))
+ _registersBeforeUpdate.Add(Register.Mertrologyasst.PulseMode, new Byte[] { 0 });
+ //deny access if NA product, because this does not have the radio app installed
+ if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "SENSUSRADIO" && f.IsInstalled))
+ _registersBeforeUpdate.Add(Register.Sensusradio.WakeupInterval, new Byte[] { 6 });
}
///
@@ -276,6 +302,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
_actualOperation = "";
ErrorMessage = "";
_lutUpdateState = LutUpdateState.StartInitial;
+ _lutBackupUpdateState = LutUpdateState.Idle;
while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess)
{
LutUpdateStateMachine();
@@ -317,6 +344,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
//set state machine for automatic FW update
_lutUpdateState = LutUpdateState.Idle;
+ _lutBackupUpdateState = LutUpdateState.Idle;
_actualOperation = "";
_operationCtr = 0;
@@ -349,6 +377,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
//set default timeout for file write operation
_meterFile.SetDefaultFileWriteTimeout();
+ //switch LED off set sample rate to 1 -> 1Hz to slow down CPU load
+ _registersAfterUpdate = new Dictionary();
+ foreach (var item in _registersBeforeUpdate)
+ {
+ var writeBackValue = _genesisMeter.ReadRegister(item.Key);
+ _registersAfterUpdate.Add(item.Key, writeBackValue);
+ _genesisMeter.WriteRegister(item.Key, item.Value);
+
+ }
//remove the update stop action
StopUpdateProcess = false;
return true;
@@ -365,6 +402,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
if (_meterFile != null) _meterFile.OnProcessUpdate -= ProcessUpdate_Event;
_meterFile = null;
ReestablishMeterFileSystem();
+
+ foreach (var item in _registersAfterUpdate)
+ {
+ _genesisMeter.WriteRegister(item.Key, item.Value);
+ }
+
_genesisMeter?.Logout();
if (!StopUpdateProcess)
{
@@ -385,64 +428,78 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
///
/// - Initial
///
+ ///
+ /// - Introduced lock for repeated execution of state machine
+ ///
private void LutUpdateStateMachine()
{
- switch (_lutUpdateState)
+ if (_lutBackupUpdateState == _lutUpdateState)
{
- case LutUpdateState.Idle:
- break;
-
- case LutUpdateState.StartInitial:
- _updateProcedureRetryCtr = 0;
- _lutUpdateState = LutUpdateState.PrepareLutDownload;
- break;
-
- case LutUpdateState.PrepareLutDownload:
- _lutUpdateState = PrepareLutDownload() ? LutUpdateState.EraseLutFile : LutUpdateState.StepFailed;
- break;
-
- case LutUpdateState.EraseLutFile:
- _lutUpdateState = EraseLutFiles() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed;
- break;
-
- case LutUpdateState.DownloadLutFile:
- _lutUpdateState = DownloadLutFiles() ? LutUpdateState.UploadLutFile : LutUpdateState.StepFailed;
- break;
-
- case LutUpdateState.UploadLutFile:
- _lutUpdateState = UploadAndCompareLutFiles() ? LutUpdateState.Idle : LutUpdateState.StepFailed;
- break;
-
- case LutUpdateState.CompareLutFile:
- break;
-
- case LutUpdateState.StepFailed:
- _lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
- ? LutUpdateState.RepeatLutUpdate : LutUpdateState.UpdateFailed;
- break;
-
- case LutUpdateState.RepeatLutUpdate:
- _lutUpdateState = LutUpdateState.DownloadLutFile;
- if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
- {
- _meterFile?.SetExtremeFileWriteTimeout();
- }
-
- break;
-
- case LutUpdateState.UpdateFailed:
- StopUpdateProcess = true;
- _lutUpdateState = LutUpdateState.Idle;
- break;
-
- case LutUpdateState.LutUpdateStateListDelimiter:
- _lutUpdateState = LutUpdateState.Idle;
- break;
-
- default:
- _lutUpdateState = LutUpdateState.Idle;
- break;
+ Thread.Sleep(1);
}
+ else
+ {
+ // remind backup state to avoid repeated execution and side effects
+ _lutBackupUpdateState = _lutUpdateState;
+ switch (_lutUpdateState)
+ {
+ case LutUpdateState.Idle:
+ break;
+
+ case LutUpdateState.StartInitial:
+ _updateProcedureRetryCtr = 0;
+ _lutUpdateState = LutUpdateState.PrepareLutDownload;
+ break;
+
+ case LutUpdateState.PrepareLutDownload:
+ _lutUpdateState =
+ PrepareLutDownload() ? LutUpdateState.EraseLutFile : LutUpdateState.StepFailed;
+ break;
+
+ case LutUpdateState.EraseLutFile:
+ _lutUpdateState = EraseLutFiles() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed;
+ break;
+
+ case LutUpdateState.DownloadLutFile:
+ _lutUpdateState = DownloadLutFiles() ? LutUpdateState.UploadLutFile : LutUpdateState.StepFailed;
+ break;
+
+ case LutUpdateState.UploadLutFile:
+ _lutUpdateState = UploadAndCompareLutFiles() ? LutUpdateState.Idle : LutUpdateState.StepFailed;
+ break;
+
+ case LutUpdateState.CompareLutFile:
+ break;
+
+ case LutUpdateState.StepFailed:
+ _lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
+ ? LutUpdateState.RepeatLutUpdate
+ : LutUpdateState.UpdateFailed;
+ break;
+
+ case LutUpdateState.RepeatLutUpdate:
+ _lutUpdateState = LutUpdateState.DownloadLutFile;
+ if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
+ {
+ _meterFile?.SetExtremeFileWriteTimeout();
+ }
+
+ break;
+
+ case LutUpdateState.UpdateFailed:
+ StopUpdateProcess = true;
+ _lutUpdateState = LutUpdateState.Idle;
+ break;
+
+ case LutUpdateState.LutUpdateStateListDelimiter:
+ _lutUpdateState = LutUpdateState.Idle;
+ break;
+
+ default:
+ _lutUpdateState = LutUpdateState.Idle;
+ break;
+ }
+ }// lock for identical state
}
#endregion
@@ -752,9 +809,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
LutFileReadBack = new MeterLutFile(fileToUpload);
if (_meterFile.ReadMeterFile(fileToUpload, out LutFileReadBack.BinData, LutFile.BinData.Count))
{
- if (LutFileReadBack.BinData != LutFile.BinData)
+ // compare the entire buffer which also includes the header of the file
+ if (!LutFileReadBack.BinData.SequenceEqual(LutFile.BinData))
{
- ErrorMessage += $"Verification of {fileToUpload} failed!\n";
+ ErrorMessage += $"Meter LUT file is unequal to downloaded {fileToUpload}!\n";
returnValue = false;
_operationCtr--;