Verification of LUT files, upload and verify binary content

This commit is contained in:
Thomas Wiedebusch
2022-03-04 08:16:14 +01:00
parent 4d9186a322
commit 63121d7c41
7 changed files with 289 additions and 87 deletions
@@ -0,0 +1,73 @@
using System;
using System.Linq;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Properties;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts
{
/// <summary>
/// Concatenation of state and string
/// </summary>
public static class LutUpdateStateInfo
{
/// <summary>
/// Build state information
/// </summary>
private static readonly LutUpdateStateText[] StateInfos;
/// <summary>
/// Ctor
/// </summary>
static LutUpdateStateInfo()
{
StateInfos = new LutUpdateStateText[(Int32)LutUpdateState.LutUpdateStateListDelimiter];
StateInfos[0].State = LutUpdateState.Idle;
StateInfos[0].Message = "";
StateInfos[1].State = LutUpdateState.StepFailed;
StateInfos[1].Message = "Processing Step Failed";
StateInfos[2].State = LutUpdateState.UpdateFailed;
StateInfos[2].Message = "LUT Update Failed";
StateInfos[3].State = LutUpdateState.StartInitial;
StateInfos[3].Message = "Initial start";
StateInfos[4].State = LutUpdateState.RepeatLutUpdate;
StateInfos[4].Message = "Repeat update";
StateInfos[5].State = LutUpdateState.UploadLutFile;
StateInfos[5].Message = "Upload LUT file from meter";
StateInfos[6].State = LutUpdateState.DownloadLutFile;
StateInfos[6].Message = "Download LUT file to meter";
StateInfos[7].State = LutUpdateState.CompareLutFile;
StateInfos[7].Message = "Compare LUT file";
StateInfos[8].State = LutUpdateState.PrepareLutDownload;
StateInfos[8].Message = "Init meter size and LUT file CRC";
StateInfos[9].State = LutUpdateState.EraseLutFile;
StateInfos[9].Message = "Erase LUT file in meter";
}
/// <summary>
/// Get the current information
/// </summary>
/// <param name="state">state to search for information text</param>
public static String GetTextFromState(LutUpdateState state)
{
return (from stateInfo in StateInfos
where stateInfo.State == state select stateInfo.Message).FirstOrDefault();
}
/// <summary>
/// Get the state of the text
/// </summary>
/// <param name="text">information text to search if state is assigned</param>
public static LutUpdateState GetStateFromText(String text)
{
return (from stateInfo in StateInfos
where stateInfo.Message == text select stateInfo.State).FirstOrDefault();
}
}
}
@@ -0,0 +1,19 @@
using System;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts
{
/// <summary>
/// Concatenation between lokup table update state and text
/// </summary>
public struct LutUpdateStateText
{
/// <summary>
/// The state of the firmware update
/// </summary>
public LutUpdateState State;
/// <summary>
/// The message text of the lookup table update state
/// </summary>
public String Message;
}
}
@@ -66,6 +66,8 @@
<Compile Include="..\..\..\..\.shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Consts\LutUpdateStateText.cs" />
<Compile Include="Consts\LutUpdateStateInfo.cs" />
<Compile Include="Consts\LutUpdateState.cs" />
<Compile Include="Consts\FwUpdateState.cs" />
<Compile Include="Consts\FwUpdateStateInfo.cs" />
@@ -5,7 +5,6 @@ using System.Text;
using Logic.ProductionToProductMapper.Cordonel;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Properties;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
using Xylem.Common.Utils.Crc16Ccitt;
@@ -89,9 +88,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
// Look up table file
public MeterLutFile LutFile;
// actual processed file
private String _actualFileName;
public MeterLutFile LutFileReadBack;
// list of names of installed meter files on drive 1
private List<String> _meterFilesDrive1;
@@ -208,7 +205,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// </remarks>
public String GetLutUpdateStateOperation()
{
return _lutUpdateState == LutUpdateState.Idle ? "" : "Processing...";
// search text assigned to current state
var text = LutUpdateStateInfo.GetTextFromState(_lutUpdateState);
if (_lutUpdateState == LutUpdateState.Idle)
{
return text;
}
text += _updateProcedureRetryCtr > 0 ? $"Retry {_updateProcedureRetryCtr}" : "";
return text;
}
#endregion
@@ -366,7 +371,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
return returnValue;
}
_actualOperation = Resources.StrWaiting;
_actualOperation = "";
return false;
}
@@ -393,18 +398,27 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
break;
case LutUpdateState.PrepareLutDownload:
_lutUpdateState = PrepareLutDownload() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed;
_lutUpdateState = PrepareLutDownload() ? LutUpdateState.EraseLutFile : LutUpdateState.StepFailed;
break;
case LutUpdateState.EraseLutFile:
_lutUpdateState = EraseLutFiles() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed;
break;
case LutUpdateState.DownloadLutFile:
_lutUpdateState = DownloadLutFile() ? LutUpdateState.Idle : LutUpdateState.StepFailed;
_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;
? LutUpdateState.RepeatLutUpdate : LutUpdateState.UpdateFailed;
break;
case LutUpdateState.RepeatLutUpdate:
@@ -421,19 +435,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
_lutUpdateState = LutUpdateState.Idle;
break;
case LutUpdateState.UploadLutFile:
break;
case LutUpdateState.CompareLutFile:
break;
case LutUpdateState.EraseLutFile:
case LutUpdateState.LutUpdateStateListDelimiter:
_lutUpdateState = LutUpdateState.Idle;
break;
default:
_lutUpdateState = LutUpdateState.Idle;
break;
}
}
@@ -477,7 +485,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
var calculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray());
if (calculatedCrc != LutFile.FileCrc)
{
ErrorMessage += "CRC Mismatch!";
ErrorMessage += "CRC mismatch!";
return false;
}
@@ -496,7 +504,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
private Boolean PrepareLutDownload()
{
var returnValue = true;
var retryCtr = 0;
if (LutFile == null || _genesisMeter == null || _meterFile == null) return false;
//set extended timeout for trigger upgrade response delay
@@ -546,11 +554,33 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
return returnValue && !StopUpdateProcess;
}
/// <summary>
/// Read meter files of drive 1
/// </summary>
/// <returns></returns>
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
/// - Initial
/// </remarks>
private Boolean ReadMeterFilesDrive1()
{
if (_meterFilesDrive1 == null)
{
_meterFilesDrive1 = new List<String>();
}
_meterFilesDrive1.Clear();
if (!_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1,
MeterFile.WildcardAll.ToString())) return false;
_meterFilesDrive1.AddRange(meterFilesDrive1);
return true;
}
/// <summary>
/// Erase file and check if done!
/// </summary>
/// <returns></returns>
/// <remarks date="2022-Mar-03" author="Thomas Wiedebusch">
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
/// - Initial
/// </remarks>
private Boolean EraseFile(String fileDriveName)
@@ -559,10 +589,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
//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()))
if (ReadMeterFilesDrive1())
{
_meterFilesDrive1.AddRange(meterFilesDrive1);
if (_meterFilesDrive1.Contains(fileDriveName))
{
returnValue = false;
@@ -576,15 +605,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
}
/// <summary>
/// Download the metrology lookup table files and read the catalog of drive 1
/// Erase old LUT files from meter
/// </summary>
/// <returns></returns>
/// <remarks date="2022-Feb-16" author="Thomas Wiedebusch">
/// - Initial
/// </remarks>
private Boolean DownloadLutFile()
public Boolean EraseLutFiles()
{
//counters for actual process information
var retryCtr = 0;
if (LutFile == null) return false;
@@ -592,90 +619,152 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
//set extended timeout for trigger upgrade response delay
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
var returnValue = true;
//write file portion and retry if not successful
//erase loop and retry if not successful
do
{
var filesToErase = new[] { StrLutMeterFileName, StrLutBackupMeterFileName};
// read all files which are already installed
_actualOperation = "Read installed meter files drive 1";
_operationCtr++;
if (_meterFilesDrive1 == null)
// read files on drive 1 to verify the LUT installation
if (ReadMeterFilesDrive1())
{
_meterFilesDrive1 = new List<String>();
foreach (var fileToErase in filesToErase)
{
if (!_meterFilesDrive1.Contains(fileToErase)) continue;
_operationCtr++;
_actualOperation = $"Erase {fileToErase}";
if (EraseFile(fileToErase)) continue;
ErrorMessage += $"LUT file {fileToErase} not erased!\n";
returnValue = false;
_operationCtr--;
}
}
_meterFilesDrive1.Clear();
if (_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1,
MeterFile.WildcardAll.ToString()))
if (!returnValue)
{
_meterFilesDrive1.AddRange(meterFilesDrive1);
ReestablishMeterFileSystem();
}
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
// erase file
_operationCtr++;
_actualFileName = StrLutMeterFileName;
_actualOperation = $"Erase {_actualFileName}";
if (!EraseFile(_actualFileName))
{
ErrorMessage += $"LUT file {_actualFileName} not erased!\n";
returnValue = false;
}
//set timeout back to default value
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
_operationCtr++;
_actualOperation = $"Write {_actualFileName}";
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
{
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
returnValue = false;
}
// erase file
_operationCtr++;
_actualFileName = StrLutBackupMeterFileName;
_actualOperation = $"Erase {_actualFileName}";
if (!EraseFile(_actualFileName))
{
ErrorMessage += $"LUT file {_actualFileName} not erased!\n";
returnValue = false;
}
return !StopUpdateProcess && returnValue;
}
_operationCtr++;
_actualOperation = $"Write {_actualFileName}";
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
{
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
returnValue = false;
}
/// <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">
/// - Initial
/// </remarks>
private Boolean DownloadLutFiles()
{
//counters for actual process information
var retryCtr = 0;
if (LutFile == null) return false;
//set extended timeout for trigger upgrade response delay
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
var returnValue = true;
//write LUT files and retry if not successful
do
{
_actualOperation = "Download LUT files to meter";
var filesToDownload = new[] { StrLutMeterFileName, StrLutBackupMeterFileName};
_operationCtr++;
_actualOperation = $"Write {_actualFileName}";
if (!_meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray()))
foreach (var fileToDownload in filesToDownload)
{
ErrorMessage += $"Writing of {_actualFileName} failed!\n";
_operationCtr++;
_actualOperation = $"Write {fileToDownload}";
if (_meterFile.WriteMeterFile(fileToDownload, LutFile.BinData.ToArray())) continue;
ErrorMessage += $"Writing of {fileToDownload} failed!\n";
returnValue = false;
_operationCtr--;
}
// read all files on drive 1
_operationCtr++;
_actualOperation = "Read installed meter files drive 1";
_meterFilesDrive1.Clear();
if (!_meterFile.ReadMeterFileCatalog(out meterFilesDrive1, MeterFile.StrMeterDrive1,
MeterFile.WildcardAll.ToString()))
if (ReadMeterFilesDrive1())
{
returnValue = false;
}
else
{
_meterFilesDrive1.AddRange(meterFilesDrive1);
if (!_meterFilesDrive1.Contains(StrLutMeterFileName))
foreach (var checkInstalledFile in filesToDownload)
{
if (_meterFilesDrive1.Contains(checkInstalledFile)) continue;
ErrorMessage += $"LUT file {StrLutMeterFileName} not installed!\n";
returnValue = false;
}
}
else
{
returnValue = false;
}
if (!returnValue)
{
ReestablishMeterFileSystem();
}
} while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess);
if (!_meterFilesDrive1.Contains(StrLutBackupMeterFileName))
//set timeout back to default value
_genesisMeter.TransmitProtocol.SetDefaultResponseTimeout();
return !StopUpdateProcess && returnValue;
}
/// <summary>
/// Upload the metrology lookup table files and read the catalog of drive 1
/// </summary>
/// <returns></returns>
/// <remarks date="2022-Mar-04" author="Thomas Wiedebusch">
/// - Initial
/// </remarks>
private Boolean UploadAndCompareLutFiles()
{
//counters for actual process information
var retryCtr = 0;
if (LutFile == null) return false;
//set extended timeout for trigger upgrade response delay
_genesisMeter.TransmitProtocol.SetResponseTimeout(5000);
var returnValue = true;
//write LUT files and retry if not successful
do
{
_actualOperation = "Upload LUT files to meter";
var filesToUpload = new[] { StrLutMeterFileName, StrLutBackupMeterFileName};
foreach (var fileToUpload in filesToUpload)
{
_operationCtr++;
_actualOperation = $"Read {fileToUpload}";
LutFileReadBack = new MeterLutFile(fileToUpload);
if (_meterFile.ReadMeterFile(fileToUpload, out LutFileReadBack.BinData, LutFile.BinData.Count))
{
ErrorMessage += $"LUT file {StrLutBackupMeterFileName} not installed!\n";
returnValue = false;
if (LutFileReadBack.BinData != LutFile.BinData)
{
ErrorMessage += $"Verification of {fileToUpload} failed!\n";
returnValue = false;
_operationCtr--;
}
continue;
}
ErrorMessage += $"Reading of {fileToUpload} failed!\n";
returnValue = false;
_operationCtr--;
}
if (!returnValue)