MeterFwUpdate and MeterLutUpdate:
- Introduced lock for repeated execution of state machine
This commit is contained in:
@@ -4,6 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
|
||||||
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const;
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const;
|
||||||
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
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
|
// Text for caller to inform about actual process being carried out
|
||||||
private String _actualOperation;
|
private String _actualOperation;
|
||||||
private FwUpdateState _fwUpdateState;
|
private FwUpdateState _fwUpdateState;
|
||||||
|
private FwUpdateState _fwBackupUpdateState;
|
||||||
|
|
||||||
// Process counter for caller to monitor actual progress
|
// Process counter for caller to monitor actual progress
|
||||||
private Int32 _processedBytesCtr;
|
private Int32 _processedBytesCtr;
|
||||||
@@ -713,6 +715,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
/// <remarks date="2019-Jun-29" author="Thomas Wiedebusch">
|
/// <remarks date="2019-Jun-29" author="Thomas Wiedebusch">
|
||||||
/// - Exit preparation added
|
/// - Exit preparation added
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
||||||
|
/// - Introduced lock for repeated execution of state machine
|
||||||
|
/// </remarks>
|
||||||
public Boolean UpdateMeterFw()
|
public Boolean UpdateMeterFw()
|
||||||
{
|
{
|
||||||
if (!UpdatePreparation())
|
if (!UpdatePreparation())
|
||||||
@@ -721,6 +726,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
}
|
}
|
||||||
|
|
||||||
_fwUpdateState = FwUpdateState.StartInitial;
|
_fwUpdateState = FwUpdateState.StartInitial;
|
||||||
|
_fwBackupUpdateState = FwUpdateState.Idle;
|
||||||
while (_fwUpdateState != FwUpdateState.Idle && !StopUpdateProcess)
|
while (_fwUpdateState != FwUpdateState.Idle && !StopUpdateProcess)
|
||||||
{
|
{
|
||||||
FwUpdateStateMachine();
|
FwUpdateStateMachine();
|
||||||
@@ -886,6 +892,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
|
|
||||||
//set state machine for automatic FW update
|
//set state machine for automatic FW update
|
||||||
_fwUpdateState = FwUpdateState.Idle;
|
_fwUpdateState = FwUpdateState.Idle;
|
||||||
|
_fwBackupUpdateState = FwUpdateState.Idle;
|
||||||
_actualOperation = "";
|
_actualOperation = "";
|
||||||
|
|
||||||
//update file information
|
//update file information
|
||||||
@@ -1040,8 +1047,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
/// useful as on increased size and number of applications needed to install in one run, the
|
/// useful as on increased size and number of applications needed to install in one run, the
|
||||||
/// file system is slowing down for write accesses.
|
/// file system is slowing down for write accesses.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
||||||
|
/// - Introduced lock for repeated execution of state machine
|
||||||
|
/// </remarks>
|
||||||
private void FwUpdateStateMachine()
|
private void FwUpdateStateMachine()
|
||||||
{
|
{
|
||||||
|
if (_fwBackupUpdateState == _fwUpdateState)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// remind backup state to avoid repeated execution and side effects
|
||||||
|
_fwBackupUpdateState = _fwUpdateState;
|
||||||
switch (_fwUpdateState)
|
switch (_fwUpdateState)
|
||||||
{
|
{
|
||||||
case FwUpdateState.Idle:
|
case FwUpdateState.Idle:
|
||||||
@@ -1108,6 +1126,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
{
|
{
|
||||||
_meterFile?.SetExtremeFileWriteTimeout();
|
_meterFile?.SetExtremeFileWriteTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FwUpdateState.UpdateFailed:
|
case FwUpdateState.UpdateFailed:
|
||||||
@@ -1131,6 +1150,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}// lock repeated execution of identical state
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using Logic.ProductionToProductMapper.Cordonel;
|
using Logic.ProductionToProductMapper.Cordonel;
|
||||||
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
|
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.GenesisFile.Consts;
|
||||||
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
|
||||||
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
|
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
|
// Text for caller to inform about actual process being carried out
|
||||||
private String _actualOperation;
|
private String _actualOperation;
|
||||||
private LutUpdateState _lutUpdateState;
|
private LutUpdateState _lutUpdateState;
|
||||||
|
private LutUpdateState _lutBackupUpdateState;
|
||||||
|
|
||||||
// Look up table file
|
// Look up table file
|
||||||
public MeterLutFile LutFile;
|
public MeterLutFile LutFile;
|
||||||
@@ -100,6 +104,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
|
|
||||||
// error message for display of error reason
|
// error message for display of error reason
|
||||||
public String ErrorMessage;
|
public String ErrorMessage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register subset needed to adjust for update performance content before update
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<String, Byte[]> _registersBeforeUpdate = new Dictionary<String, Byte[]>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register to restore after update
|
||||||
|
/// </summary>
|
||||||
|
private Dictionary<String, Byte[]> _registersAfterUpdate = new Dictionary<String, Byte[]>();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
#region Events
|
||||||
@@ -154,6 +169,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
{
|
{
|
||||||
if (genesisMeter == null) return;
|
if (genesisMeter == null) return;
|
||||||
AssignGenesis(genesisMeter);
|
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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -276,6 +302,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
_actualOperation = "";
|
_actualOperation = "";
|
||||||
ErrorMessage = "";
|
ErrorMessage = "";
|
||||||
_lutUpdateState = LutUpdateState.StartInitial;
|
_lutUpdateState = LutUpdateState.StartInitial;
|
||||||
|
_lutBackupUpdateState = LutUpdateState.Idle;
|
||||||
while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess)
|
while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess)
|
||||||
{
|
{
|
||||||
LutUpdateStateMachine();
|
LutUpdateStateMachine();
|
||||||
@@ -317,6 +344,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
|
|
||||||
//set state machine for automatic FW update
|
//set state machine for automatic FW update
|
||||||
_lutUpdateState = LutUpdateState.Idle;
|
_lutUpdateState = LutUpdateState.Idle;
|
||||||
|
_lutBackupUpdateState = LutUpdateState.Idle;
|
||||||
_actualOperation = "";
|
_actualOperation = "";
|
||||||
_operationCtr = 0;
|
_operationCtr = 0;
|
||||||
|
|
||||||
@@ -349,6 +377,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
//set default timeout for file write operation
|
//set default timeout for file write operation
|
||||||
_meterFile.SetDefaultFileWriteTimeout();
|
_meterFile.SetDefaultFileWriteTimeout();
|
||||||
|
|
||||||
|
//switch LED off set sample rate to 1 -> 1Hz to slow down CPU load
|
||||||
|
_registersAfterUpdate = new Dictionary<String, Byte[]>();
|
||||||
|
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
|
//remove the update stop action
|
||||||
StopUpdateProcess = false;
|
StopUpdateProcess = false;
|
||||||
return true;
|
return true;
|
||||||
@@ -365,6 +402,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
if (_meterFile != null) _meterFile.OnProcessUpdate -= ProcessUpdate_Event;
|
if (_meterFile != null) _meterFile.OnProcessUpdate -= ProcessUpdate_Event;
|
||||||
_meterFile = null;
|
_meterFile = null;
|
||||||
ReestablishMeterFileSystem();
|
ReestablishMeterFileSystem();
|
||||||
|
|
||||||
|
foreach (var item in _registersAfterUpdate)
|
||||||
|
{
|
||||||
|
_genesisMeter.WriteRegister(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
_genesisMeter?.Logout();
|
_genesisMeter?.Logout();
|
||||||
if (!StopUpdateProcess)
|
if (!StopUpdateProcess)
|
||||||
{
|
{
|
||||||
@@ -385,8 +428,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
||||||
/// - Initial
|
/// - Initial
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
|
||||||
|
/// - Introduced lock for repeated execution of state machine
|
||||||
|
/// </remarks>
|
||||||
private void LutUpdateStateMachine()
|
private void LutUpdateStateMachine()
|
||||||
{
|
{
|
||||||
|
if (_lutBackupUpdateState == _lutUpdateState)
|
||||||
|
{
|
||||||
|
Thread.Sleep(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// remind backup state to avoid repeated execution and side effects
|
||||||
|
_lutBackupUpdateState = _lutUpdateState;
|
||||||
switch (_lutUpdateState)
|
switch (_lutUpdateState)
|
||||||
{
|
{
|
||||||
case LutUpdateState.Idle:
|
case LutUpdateState.Idle:
|
||||||
@@ -398,7 +452,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LutUpdateState.PrepareLutDownload:
|
case LutUpdateState.PrepareLutDownload:
|
||||||
_lutUpdateState = PrepareLutDownload() ? LutUpdateState.EraseLutFile : LutUpdateState.StepFailed;
|
_lutUpdateState =
|
||||||
|
PrepareLutDownload() ? LutUpdateState.EraseLutFile : LutUpdateState.StepFailed;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LutUpdateState.EraseLutFile:
|
case LutUpdateState.EraseLutFile:
|
||||||
@@ -418,7 +473,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
|
|
||||||
case LutUpdateState.StepFailed:
|
case LutUpdateState.StepFailed:
|
||||||
_lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
|
_lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
|
||||||
? LutUpdateState.RepeatLutUpdate : LutUpdateState.UpdateFailed;
|
? LutUpdateState.RepeatLutUpdate
|
||||||
|
: LutUpdateState.UpdateFailed;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LutUpdateState.RepeatLutUpdate:
|
case LutUpdateState.RepeatLutUpdate:
|
||||||
@@ -443,6 +499,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
_lutUpdateState = LutUpdateState.Idle;
|
_lutUpdateState = LutUpdateState.Idle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}// lock for identical state
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -752,9 +809,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
|||||||
LutFileReadBack = new MeterLutFile(fileToUpload);
|
LutFileReadBack = new MeterLutFile(fileToUpload);
|
||||||
if (_meterFile.ReadMeterFile(fileToUpload, out LutFileReadBack.BinData, LutFile.BinData.Count))
|
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;
|
returnValue = false;
|
||||||
_operationCtr--;
|
_operationCtr--;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user