LUT update improvements
This commit is contained in:
@@ -1052,6 +1052,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// </summary>
|
||||
public String FwVersion;
|
||||
|
||||
/// <summary>
|
||||
/// This is the Metrology Lookup Table CRC.
|
||||
/// </summary>
|
||||
public String LutCrc;
|
||||
|
||||
/// <summary>
|
||||
/// This is the meter size.
|
||||
/// </summary>
|
||||
public String MeterSize;
|
||||
|
||||
/// <summary>
|
||||
/// Region (EMEA or NA) and Radio frequency (433 or 868 or null).
|
||||
/// </summary>
|
||||
@@ -1107,8 +1117,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
//build the version string, because e.g. FLEXNETVERSION is one application which does not
|
||||
//follow the same rule. After the upper conversion, the hexadecimal outline will be lost
|
||||
versionString = BuildFwVersionString(readFwVersionBytes[1], readFwVersionBytes[0]);
|
||||
if (appVersionToRead.AppName == "FLEXNETVERSION")
|
||||
FwVersion = versionString;
|
||||
if (appVersionToRead.AppName == "FLEXNETVERSION") FwVersion = versionString;
|
||||
|
||||
if (readFwVersion != 0)
|
||||
{
|
||||
@@ -1139,6 +1148,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
MetrologyUpgradePermission = RegisterConverter.ConvertTo<Byte>(
|
||||
ReadRegister(Register.System.MetrologyUpgradePermission));
|
||||
|
||||
//read metrology lookup table CRC
|
||||
var lutCrc = RegisterConverter.ConvertTo<UInt32>(ReadRegister(Register.Genesisflow.LookupFileCrc));
|
||||
LutCrc = $@"0x{lutCrc:X4}";
|
||||
|
||||
|
||||
//read meter size
|
||||
MeterSize = MeterSizeConverter.ConvertMeterSizeEnumToSizeName((MeterSize)RegisterConverter.ConvertTo<Byte>(
|
||||
ReadRegister(Register.Genesisflow.MeterSize)));
|
||||
|
||||
//read core revision
|
||||
var coreRegisterRead = RegisterConverter.ConvertTo<String>(ReadRegister(Register.System.CoreRevision, 16));
|
||||
var coreRevision = coreRegisterRead?.Split('\0');
|
||||
|
||||
@@ -560,7 +560,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
//set extended timeout for file operations
|
||||
_currentGenesis.TransmitProtocol.SetResponseTimeout(ExtendedFileIoTimeoutMs);
|
||||
CommunicationConfig.RequestRetries = 0;
|
||||
//write "remove-command" to meter, wait for result and read back (read back returns false because of unreadable content)
|
||||
//write "remove-command" to meter, wait for result and read back
|
||||
//ATTENTION: read back returns FALSE because of unreadable content
|
||||
_currentGenesis.WriteRegister(Register.Configexchange.FileRemove, fileName, true, true);
|
||||
//set timeout back to default value
|
||||
_currentGenesis.TransmitProtocol.SetDefaultResponseTimeout();
|
||||
|
||||
@@ -67,13 +67,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
private const String StrProcessLut = "Processing metrology lookup table";
|
||||
|
||||
//trigger update retries
|
||||
private const Int32 RegisterWriteRetries = 2;
|
||||
private const Int32 RegisterWriteRetries = 0;
|
||||
|
||||
//update reties for files
|
||||
private const Int32 FileWriteRetries = 0;
|
||||
|
||||
//retry of entire update procedure
|
||||
private const Int32 UpdateProcedureRetries = 5;
|
||||
private const Int32 UpdateProcedureRetries = 0;
|
||||
|
||||
//threshold to increase the file write timing
|
||||
private const Int32 IncreaseTimeoutUpdateProcedureRetries = 4;
|
||||
@@ -87,17 +87,22 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
private String _actualOperation;
|
||||
private LutUpdateState _lutUpdateState;
|
||||
|
||||
// Process counter for caller to monitor actual progress
|
||||
private Int32 _processedBytesCtr;
|
||||
private Int32 _overallBytesCtr;
|
||||
|
||||
// Look up table file
|
||||
public MeterLutFile LutFile;
|
||||
|
||||
// actual processed file
|
||||
private String _actualFileName;
|
||||
|
||||
// list of names of installed meter files on drive 1
|
||||
private List<String> _meterFilesDrive1;
|
||||
|
||||
// number of operations for over all access
|
||||
private const Int32 NumberOfOperations = 11;
|
||||
private Int32 _operationCtr;
|
||||
|
||||
|
||||
// error message for display of error reason
|
||||
public String ErrorMessage;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
@@ -124,18 +129,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
/// <summary>
|
||||
/// Process counter in percent
|
||||
/// </summary>
|
||||
/// <remarks date="2019-Jun-20" author="Thomas Wiedebusch">
|
||||
/// <remarks date="2022-Mar-03" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
public Double OverallProcessCtrPercent
|
||||
{
|
||||
get
|
||||
{
|
||||
var processFileBytes = _meterFile?.ProcessedBytesCtr ?? 0;
|
||||
return 100.0 * (processFileBytes + _processedBytesCtr) /
|
||||
(_overallBytesCtr > 0 ? _overallBytesCtr : 1);
|
||||
}
|
||||
}
|
||||
public Double OverallProcessCtrPercent => 100.0 * _operationCtr / NumberOfOperations;
|
||||
|
||||
/// <summary>
|
||||
/// Single file process counter in percent
|
||||
@@ -211,7 +208,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
/// </remarks>
|
||||
public String GetLutUpdateStateOperation()
|
||||
{
|
||||
return _lutUpdateState == LutUpdateState.Idle ? "" : $"Downloading {_actualFileName}...";
|
||||
return _lutUpdateState == LutUpdateState.Idle ? "" : "Processing...";
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -270,6 +267,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
return false;
|
||||
}
|
||||
|
||||
_operationCtr = 0;
|
||||
_actualOperation = "";
|
||||
ErrorMessage = "";
|
||||
_lutUpdateState = LutUpdateState.StartInitial;
|
||||
while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess)
|
||||
{
|
||||
@@ -308,13 +308,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
StopUpdateProcess = false;
|
||||
|
||||
//reset all counters
|
||||
_processedBytesCtr = 0;
|
||||
_overallBytesCtr = 0;
|
||||
_updateProcedureRetryCtr = 0;
|
||||
|
||||
//set state machine for automatic FW update
|
||||
_lutUpdateState = LutUpdateState.Idle;
|
||||
_actualOperation = "";
|
||||
_operationCtr = 0;
|
||||
|
||||
//logout/login/auto-login
|
||||
ReestablishMeterFileSystem();
|
||||
@@ -402,8 +401,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
break;
|
||||
|
||||
case LutUpdateState.StepFailed:
|
||||
_processedBytesCtr = 0;
|
||||
_overallBytesCtr = 0;
|
||||
|
||||
_lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries
|
||||
? LutUpdateState.RepeatLutUpdate
|
||||
@@ -411,8 +408,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
break;
|
||||
|
||||
case LutUpdateState.RepeatLutUpdate:
|
||||
_processedBytesCtr = 0;
|
||||
_overallBytesCtr = 0;
|
||||
_lutUpdateState = LutUpdateState.DownloadLutFile;
|
||||
if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries)
|
||||
{
|
||||
@@ -422,8 +417,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
break;
|
||||
|
||||
case LutUpdateState.UpdateFailed:
|
||||
_processedBytesCtr = 0;
|
||||
_overallBytesCtr = 0;
|
||||
StopUpdateProcess = true;
|
||||
_lutUpdateState = LutUpdateState.Idle;
|
||||
break;
|
||||
@@ -457,7 +450,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
private Boolean ValidateLutFile()
|
||||
{
|
||||
// check if LUT file contains data
|
||||
if (LutFile?.BinData == null || LutFile.BinData.Count < SizeLutFile) return false;
|
||||
if (LutFile?.BinData == null || LutFile.BinData.Count < SizeLutFile)
|
||||
{
|
||||
ErrorMessage += "File size mismatch!";
|
||||
return false;
|
||||
}
|
||||
|
||||
LutFile.IsValid = false;
|
||||
// extract the identifier and check, if this is a LUT file
|
||||
@@ -478,13 +475,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
var payload = new List<Byte>();
|
||||
payload.AddRange(entireFile.GetRange(IndexVersion, LutFileDataLength + LengthVersion));
|
||||
var calculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray());
|
||||
if (calculatedCrc == LutFile.FileCrc)
|
||||
if (calculatedCrc != LutFile.FileCrc)
|
||||
{
|
||||
LutFile.CalculatedCrc = calculatedCrc;
|
||||
LutFile.IsValid = true;
|
||||
return true;
|
||||
ErrorMessage += "CRC Mismatch!";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
LutFile.CalculatedCrc = calculatedCrc;
|
||||
LutFile.IsValid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -496,21 +495,44 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
/// </remarks>
|
||||
private Boolean PrepareLutDownload()
|
||||
{
|
||||
Boolean returnValue;
|
||||
_actualOperation = "Write Meter Size";
|
||||
|
||||
var returnValue = true;
|
||||
|
||||
var retryCtr = 0;
|
||||
if (LutFile == null || _genesisMeter == null || _meterFile == null) return false;
|
||||
//set extended timeout for trigger upgrade response delay
|
||||
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
|
||||
do
|
||||
{
|
||||
_actualOperation = "Write Meter Size";
|
||||
returnValue = _genesisMeter.WriteRegister(Register.Genesisflow.MeterSize, (Byte)LutFile.MeterSize);
|
||||
_actualOperation = "Write CRC";
|
||||
returnValue &= _genesisMeter.WriteRegister<UInt32>(Register.Genesisflow.LookupFileCrc, LutFile.FileCrc);
|
||||
_actualOperation = "Store calibration";
|
||||
returnValue &= _genesisMeter.WriteRegister<Byte>(Register.Genesisflow.StoreCalibration, 1);
|
||||
_actualOperation = "Write meter size";
|
||||
_operationCtr++;
|
||||
if (!_genesisMeter.WriteRegister(Register.Genesisflow.MeterSize, (Byte)LutFile.MeterSize))
|
||||
{
|
||||
ErrorMessage = "Meter size could not be set!\n";
|
||||
_operationCtr--;
|
||||
returnValue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_operationCtr++;
|
||||
_actualOperation = "Write Lut CRC to meter";
|
||||
if (!_genesisMeter.WriteRegister<UInt32>(Register.Genesisflow.LookupFileCrc, LutFile.FileCrc))
|
||||
{
|
||||
ErrorMessage += "Meter LUT CRC could not be set!\n";
|
||||
_operationCtr--;
|
||||
returnValue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_operationCtr++;
|
||||
_actualOperation = "Store calibration to meter";
|
||||
if (!_genesisMeter.WriteRegister(Register.Genesisflow.StoreCalibration, 1))
|
||||
{
|
||||
ErrorMessage += "Meter store calibration failed!\n";
|
||||
_operationCtr--;
|
||||
returnValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!returnValue)
|
||||
{
|
||||
@@ -525,7 +547,36 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the metrology lookup table files
|
||||
/// Erase file and check if done!
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks date="2022-Mar-03" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
private Boolean EraseFile(String fileDriveName)
|
||||
{
|
||||
var returnValue = _meterFile.UnlockEraseWriteMeterFile(fileDriveName);
|
||||
//erase returns always TRUE, even if the erasure failed! Check with catalogue
|
||||
_meterFile.EraseMeterFile(fileDriveName);
|
||||
_meterFilesDrive1.Clear();
|
||||
if (_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1,
|
||||
MeterFile.WildcardAll.ToString()))
|
||||
{
|
||||
_meterFilesDrive1.AddRange(meterFilesDrive1);
|
||||
if (_meterFilesDrive1.Contains(fileDriveName))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the metrology lookup table files and read the catalog of drive 1
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
|
||||
@@ -535,32 +586,97 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
{
|
||||
|
||||
//counters for actual process information
|
||||
_processedBytesCtr = 0;
|
||||
_overallBytesCtr = 0;
|
||||
var retryCtr = 0;
|
||||
Boolean returnValue;
|
||||
|
||||
if (LutFile == null) return false;
|
||||
|
||||
//set extended timeout for trigger upgrade response delay
|
||||
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
|
||||
var returnValue = true;
|
||||
//write file portion and retry if not successful
|
||||
do
|
||||
{
|
||||
// read all files which are already installed
|
||||
_actualOperation = "Read installed meter files drive 1";
|
||||
_operationCtr++;
|
||||
if (_meterFilesDrive1 == null)
|
||||
{
|
||||
_meterFilesDrive1 = new List<String>();
|
||||
}
|
||||
_meterFilesDrive1.Clear();
|
||||
if (_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1,
|
||||
MeterFile.WildcardAll.ToString()))
|
||||
{
|
||||
_meterFilesDrive1.AddRange(meterFilesDrive1);
|
||||
}
|
||||
|
||||
// erase file
|
||||
_operationCtr++;
|
||||
_actualFileName = StrLutMeterFileName;
|
||||
// unlock, erase and write original
|
||||
returnValue = _meterFile.UnlockEraseWriteMeterFile(_actualFileName);
|
||||
_actualOperation = $"Erase {_actualFileName}";
|
||||
returnValue &= _meterFile.EraseMeterFile(_actualFileName);
|
||||
if (!EraseFile(_actualFileName))
|
||||
{
|
||||
ErrorMessage += $"LUT file {_actualFileName} not erased!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
_operationCtr++;
|
||||
_actualOperation = $"Write {_actualFileName}";
|
||||
returnValue &= _meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray());
|
||||
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
|
||||
{
|
||||
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
// erase file
|
||||
_operationCtr++;
|
||||
_actualFileName = StrLutBackupMeterFileName;
|
||||
// write backup
|
||||
returnValue &= _meterFile.UnlockEraseWriteMeterFile(_actualFileName);
|
||||
_actualOperation = $"Erase {_actualFileName}";
|
||||
returnValue &= _meterFile.EraseMeterFile(_actualFileName);
|
||||
if (!EraseFile(_actualFileName))
|
||||
{
|
||||
ErrorMessage += $"LUT file {_actualFileName} not erased!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
_operationCtr++;
|
||||
_actualOperation = $"Write {_actualFileName}";
|
||||
returnValue &= _meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray());
|
||||
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
|
||||
{
|
||||
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
|
||||
_operationCtr++;
|
||||
_actualOperation = $"Write {_actualFileName}";
|
||||
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
|
||||
{
|
||||
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
_operationCtr++;
|
||||
_actualOperation = "Read installed meter files drive 1";
|
||||
_meterFilesDrive1.Clear();
|
||||
if (!_meterFile.ReadMeterFileCatalog(out meterFilesDrive1, MeterFile.StrMeterDrive1,
|
||||
MeterFile.WildcardAll.ToString()))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_meterFilesDrive1.AddRange(meterFilesDrive1);
|
||||
if (!_meterFilesDrive1.Contains(StrLutMeterFileName))
|
||||
{
|
||||
ErrorMessage += $"LUT file {StrLutMeterFileName} not installed!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
if (!_meterFilesDrive1.Contains(StrLutBackupMeterFileName))
|
||||
{
|
||||
ErrorMessage += $"LUT file {StrLutBackupMeterFileName} not installed!\n";
|
||||
returnValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!returnValue)
|
||||
{
|
||||
@@ -568,10 +684,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
}
|
||||
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
|
||||
|
||||
returnValue &= retryCtr <= FileWriteRetries;
|
||||
|
||||
//update information for process bar
|
||||
_processedBytesCtr += LutFile.BinData.Count;
|
||||
//set timeout back to default value
|
||||
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
|
||||
|
||||
return !StopUpdateProcess && returnValue;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
public static readonly String NumFirePulses = "GENESISFLOW_NumFirePulses";
|
||||
public static readonly String LookupFileCrc = "GENESISFLOW_LookupFileCrc";
|
||||
|
||||
|
||||
};
|
||||
|
||||
public static class Powermon
|
||||
@@ -122,6 +121,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
Configexchange.FileClose,
|
||||
Configexchange.FileWrite,
|
||||
Configexchange.FileRead,
|
||||
Configexchange.Catalogue,
|
||||
Configexchange.GetFilePointerOffset,
|
||||
Configexchange.SetFilePointerOffset,
|
||||
Configexchange.FileRemove,
|
||||
@@ -136,6 +136,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
Genesisflow.TriggerIdle,
|
||||
Genesisflow.LedMode,
|
||||
Genesisflow.SampleRate,
|
||||
Genesisflow.MeterSize,
|
||||
Genesisflow.LookupFileCrc,
|
||||
Genesisflow.StoreCalibration,
|
||||
|
||||
Sensusradio.WakeupInterval,
|
||||
Sensusradio.FrequencyIndicator
|
||||
|
||||
Reference in New Issue
Block a user