CUST: - FwUpdateSw: - LUT check and logging

Common/.../GenesisFile/MeterLutFile: - LUT file analyze function
This commit is contained in:
Thomas Wiedebusch
2023-11-13 13:49:06 +01:00
parent 54faa55355
commit 75cabb6f47
6 changed files with 170 additions and 106 deletions
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
using Xylem.Common.Utils.Crc16Ccitt;
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
{
@@ -93,6 +95,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// </summary>
public UInt16 CalculatedCrc;
/// <summary>
/// FileCRC and calculated CRC are different
/// </summary>
public Boolean CrcError;
/// <summary>
/// Validation of LUT file
/// </summary>
@@ -107,5 +114,48 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// Meter size
/// </summary>
public MeterSize MeterSize;
/// <summary>
/// Verifies the LUT format based on its contents
/// </summary>
/// <returns>true if valid</returns>
public Boolean ValidateLutFormat()
{
IsValid = false;
if (BinData == null || BinData.Count < SizeLutFile)
return false;
// extract the identifier and check, if this is a LUT file
StrLutFileId = Encoding.UTF8.GetString(BinData.ToArray(), MeterLutFile.IndexLutFileId,
MeterLutFile.IndexDataLength);
if (StrLutFileId != MeterLutFile.StrLutMeterFileId)
return false;
MeterSize = (MeterSize)BinData[MeterLutFile.IndexMeterSize];
FileCrc = (UInt16)(BinData[MeterLutFile.IndexCrc] +
(BinData[MeterLutFile.IndexCrc + 1] << 8));
Version = (UInt16)(BinData[MeterLutFile.IndexVersion] +
(BinData[MeterLutFile.IndexVersion + 1] << 8));
DataLength = (UInt32)(BinData[MeterLutFile.IndexDataLength]
+ (BinData[MeterLutFile.IndexDataLength + 1] << 8)
+ (BinData[MeterLutFile.IndexDataLength + 2] << 16)
+ (BinData[MeterLutFile.IndexDataLength + 3] << 24));
// calculate CRC and compare this with the file CRC
var entireFile = new List<Byte>();
entireFile.AddRange(BinData);
var payload = new List<Byte>();
payload.AddRange(entireFile.GetRange(MeterLutFile.IndexVersion,
MeterLutFile.LutFileDataLength + MeterLutFile.LengthVersion));
CalculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray());
if (CalculatedCrc != FileCrc)
{
CrcError = true;
return false;
}
CrcError = false;
IsValid = true;
return true;
}
}
}
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
@@ -10,7 +9,6 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts;
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
using Xylem.Common.Utils.Crc16Ccitt;
using Xylem.Common.Utils.ProcessExec;
using Xylem.Common.Utils.ProcessExec.EventArguments;
@@ -483,6 +481,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// <remarks date="2022-Feb-25" author="Thomas Wiedebusch">
/// - Initial
/// </remarks>
/// <remarks date="2023-Nov-13" author="Thomas Wiedebusch">
/// - LUT file validation exported to <see cref="MeterLutFile.ValidateLutFormat"/>
/// </remarks>
private Boolean ValidateLutFile()
{
// check if LUT file contains data
@@ -492,38 +493,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
return false;
}
LutFile.IsValid = false;
// extract the identifier and check, if this is a LUT file
LutFile.StrLutFileId = Encoding.UTF8.GetString(LutFile.BinData.ToArray(), MeterLutFile.IndexLutFileId,
MeterLutFile.IndexDataLength);
if (LutFile.StrLutFileId != MeterLutFile.StrLutMeterFileId)
return false;
LutFile.MeterSize = (MeterSize)LutFile.BinData[MeterLutFile.IndexMeterSize];
LutFile.FileCrc = (UInt16)(LutFile.BinData[MeterLutFile.IndexCrc] +
(LutFile.BinData[MeterLutFile.IndexCrc + 1] << 8));
LutFile.Version = (UInt16)(LutFile.BinData[MeterLutFile.IndexVersion] +
(LutFile.BinData[MeterLutFile.IndexVersion + 1] << 8));
LutFile.DataLength = (UInt32)(LutFile.BinData[MeterLutFile.IndexDataLength]
+ (LutFile.BinData[MeterLutFile.IndexDataLength + 1] << 8)
+ (LutFile.BinData[MeterLutFile.IndexDataLength + 2] << 16)
+ (LutFile.BinData[MeterLutFile.IndexDataLength + 3] << 24));
// calculate CRC and compare this with the file CRC
var entireFile = new List<Byte>();
entireFile.AddRange(LutFile.BinData);
var payload = new List<Byte>();
payload.AddRange(entireFile.GetRange(MeterLutFile.IndexVersion,
MeterLutFile.LutFileDataLength + MeterLutFile.LengthVersion));
var calculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray());
if (calculatedCrc != LutFile.FileCrc)
// Take the file content to validate the format based
var lutFileFormatValid = LutFile.ValidateLutFormat();
if (LutFile.CrcError)
{
ErrorMessage = "CRC mismatch!";
return false;
}
LutFile.CalculatedCrc = calculatedCrc;
LutFile.IsValid = true;
return true;
return lutFileFormatValid;
}
/// <summary>
@@ -24,6 +24,7 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.ProductionOrderCore.OrderData;
using Xylem.Common.Utils.Logging;
using Xylem.Common.Utils.ProcessExec;
using Xylem.Common.Utils.ProcessExec.EventArguments;
@@ -53,7 +54,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
private readonly MeterBatch _meterBatch;
private Byte[] _fwUpdateSafePwdFile;
private MeterLutFile _fwUpdateSafeLutFile;
private MeterLutFile _meterLutFile;
private String _passwordLvl8;
private String _skeletonKey;
@@ -1689,7 +1689,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// <summary>
/// Logging of LUT file read from meter.
/// </summary>
/// <remarks date="2023-Nov-10" author="Thomas Wiedebusch">
/// <remarks date="2023-Nov-13" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private Boolean ReadLogAndCompareMeterLutFile()
@@ -1702,66 +1702,56 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
{
// Read the meter LUT file
var meterFile = new MeterFile(_currentGenesis);
retVal = meterFile.ReadMeterFile(MeterLutFile.StrLutMeterFileName, out var meterLutFile);
var meterLutFile = new MeterLutFile();
retVal = meterFile.ReadMeterFile(MeterLutFile.StrLutMeterFileName, out meterLutFile.BinData);
// Separate to maximum line length of 16 bytes
// Extract information from read meter LUT file
var lutLineList = new List<String>();
if (retVal)
{
for (var idx = 0; idx < meterLutFile.Count; idx += 16)
// Validate the meter LUT file format
var lutFileFormatValid = meterLutFile.ValidateLutFormat();
var lutLine = $@"LUT Version: {meterLutFile.Version}";
lutLineList.Add(lutLine);
lutLine = $@"LUT {Resources.StrMessageMeterSize} " +
$@"{MeterSizeConverter.ConvertMeterSizeEnumToSizeName(meterLutFile.MeterSize)}";
lutLineList.Add(lutLine);
lutLine = $@"{Resources.StrMessageLutCrc} 0x{meterLutFile.FileCrc:X4}";
lutLineList.Add(lutLine);
if (lutFileFormatValid)
{
// limit the length at the end to the remaining bytes
var length = idx + 16 > meterLutFile.Count ? meterLutFile.Count - idx : 16;
var lutLine = BitConverter.ToString(meterLutFile.GetRange(idx, length).ToArray());
lutLineList.Add(lutLine);
}
}
if (_fwUpdateSafeLutFile == null || _fwUpdateSafeLutFile.BinData.Count != MeterLutFile.SizeLutFile)
{
LogStringList(Resources.StrMessageLutFile, lutLineList,
Resources.StrLutFileFromMeterValid);
}
else
{
for (var c = 0; c < MeterLutFile.SizeLutFile; c++)
{
// If one byte is different the comparison failed
if (_fwUpdateSafeLutFile.BinData[c] != meterLutFile.BinData[c])
{
LogStringList(Resources.StrMessageLutFile, lutLineList,
errorMessage: Resources.StrLutFileCompareFailed);
retVal = false;
}
}
// Analyze the read out of LUT file
if (meterLutFile == null || meterLutFile.Count == 0)
{
// Log information about LUT file is not installed
if (_fwUpdateSafeLutFile == null)
{
LogText(Resources.StrLutFileNotNeeded);
return true;
}
// Here the LUT file should be installed but is not
InfoProcessFailed(null, Resources.StrLutFileNotInstalled);
retVal = false;
}
// If the FW-Update safe does not contain a LUT file this cannot be compared
if (_fwUpdateSafeLutFile == null)
{
// If the FW-Update safe does not contain a LUT file just log the read out
if (lutLineList.Count != MeterLutFile.SizeLutFile )
{
LogStringList(Resources.StrMessageHashedPwdFile, lutLineList,
errorMessage: Resources.StrLutFileNotDelivered);
// Here all bytes are identical
if (!retVal)
{
LogStringList(Resources.StrMessageLutFile, lutLineList,
Resources.StrLutFileCompareSucceeded);
}
}
}
// Here the LUT file format is invalid
else
{
LogErrorText(Resources.StrLutFileNotDelivered);
}
}
else if (!_passwordFileIsCorrupted)
{
// Compare the installed LUT file with the LUT file from FW update safe
retVal = !meterFile.VerifyMeterFile(MeterLutFile.StrLutMeterFileName,
_fwUpdateSafeLutFile.BinData.ToArray());
if (!retVal)
{
LogStringList(Resources.StrMessageLutFile, lutLineList,
Resources.StrLutFileCompareSucceeded);
}
else
{
// LUT file is suspicious
LogStringList(Resources.StrMessageLutFile, lutLineList,
errorMessage: Resources.StrLutFileCompareFailed);
errorMessage: Resources.StrLutFileFromMeterInvalid);
retVal = false;
}
}
}
@@ -3269,7 +3259,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// the pulse mode OFF before reading all installed apps, which will be unpredictable on activated
// pulse module.
retVal = _currentGenesis.Login(password, skipReadMeterFwAndAssignRegisters: true);
if (!retVal)
{
return false;
@@ -3958,23 +3948,25 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// </summary>
/// <param name="successExitState"></param>
/// <param name="errorExitState"></param>
/// <remarks date="2023-Nov-09" author="Thomas Wiedebusch">
/// <remarks date="2023-Nov-13" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private void RestoreLutFile(ProcessState successExitState, ProcessState errorExitState = ProcessState.Error)
{
// Remind the invoker being able to generate error messages based on the last state
_invokerProcessState = _processState;
InfoProcessActive(lblLutFileCheck, Resources.StrLutFileRestoreActive);
//TODO THW implement the installation of the LUT
// If meter LUT CRC is not set and the meter files do not report the LUT, the meter does not have an
// installed LUT
// 1. LUT file NOT installed:
// If meter LUT CRC is not set and the meter files do not report the LUT, the meter does not have an
// installed LUT
if ((string.IsNullOrEmpty(_currentGenesis.LutCrc) ||
_currentGenesis.LutCrc.Equals(Constants.StrUnknown)) &&
_currentGenesis.LutCrc.Equals(Constants.StrUnknown)) &&
_readMeterFiles != null && !_readMeterFiles.Any(f => f.Contains(MeterLutFile.StrLutMeterFileName)))
{
// if the safe contains a LUT file, the installation of it has failed or it got lost during update
// 1. a) LUT file not installed but required by the FW update safe:
// If the safe contains a LUT file, the installation of it has failed or it got lost during
// update
if (_fwUpdateSafeLutFile != null)
{
LogErrorText(Resources.StrLutFileNotInstalled);
@@ -3982,15 +3974,29 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
return;
}
// this FW version does not require a LUT file
// 1. b) LUT file not installed and not delivered by the FW update safe
// This FW version does not require a LUT file
LogText(Resources.StrLutFileNotNeeded);
_processState = successExitState;
return;
}
// if the LUT is not in the safe it cannot be restored but can be logged
ReadLogAndCompareMeterLutFile();
_processState = errorExitState;
// 2. LUT file is installed:
// 2.a) Lut file is installed but NOT in the safe:
// If the LUT is not in the safe it cannot be restored or compared to the required content but can
// be analyzed and logged
// 2.b) LUT file is installed and delivered by the FW update safe:
// On validated installed LUT file in meter this can be compared with the required LUT file
if (!ReadLogAndCompareMeterLutFile())
{
InfoProcessFailed(lblLutFileCheck, Resources.StrLutFileFromMeterInvalid);
_processState = errorExitState;
}
else
{
InfoProcessSuccess(lblLutFileCheck, Resources.StrLutFileFromMeterValid);
_processState = successExitState;
}
// Change first the process state, otherwise the timer may switch the bar on again
SetOverallProgressDisplayOff();
@@ -601,6 +601,24 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to ERROR: LUT installed in meter is invalid!.
/// </summary>
internal static string StrLutFileFromMeterInvalid {
get {
return ResourceManager.GetString("StrLutFileFromMeterInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to LUT installed in meter is valid..
/// </summary>
internal static string StrLutFileFromMeterValid {
get {
return ResourceManager.GetString("StrLutFileFromMeterValid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ERROR: LUT from FW update safe invalid!.
/// </summary>
@@ -610,6 +628,15 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to LUT from FW update safe is valid..
/// </summary>
internal static string StrLutFileFromSafeValid {
get {
return ResourceManager.GetString("StrLutFileFromSafeValid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ERROR: LUT is not in FW updae safe!.
/// </summary>
@@ -700,15 +727,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to LUT successfully validated..
/// </summary>
internal static string StrLutFileValid {
get {
return ResourceManager.GetString("StrLutFileValid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Not installed.
/// </summary>
@@ -646,10 +646,16 @@
<data name="StrLutFileRestoreUnspecified" xml:space="preserve">
<value>LUT wiederherstellen.</value>
</data>
<data name="StrLutFileValid" xml:space="preserve">
<value>LUT ist gültig.</value>
<data name="StrLutFileFromMeterValid" xml:space="preserve">
<value>LUT installiert im Meter is gültig.</value>
</data>
<data name="StrMessageLutFile" xml:space="preserve">
<value>LUT:</value>
</data>
<data name="StrLutFileFromMeterInvalid" xml:space="preserve">
<value>FEHLER:LUT installiert im Meter ist ungültig!</value>
</data>
<data name="StrLutFileFromSafeValid" xml:space="preserve">
<value>LUT im FW Update Safe ist gültig.</value>
</data>
</root>
@@ -613,8 +613,8 @@
<data name="StrLutFileNotNeeded" xml:space="preserve">
<value>LUT not required for this FW.</value>
</data>
<data name="StrLutFileValid" xml:space="preserve">
<value>LUT successfully validated.</value>
<data name="StrLutFileFromMeterValid" xml:space="preserve">
<value>LUT installed in meter is valid.</value>
</data>
<data name="StrLutFileCompareFailed" xml:space="preserve">
<value>ERROR: Installed LUT is unequal to required!</value>
@@ -652,4 +652,10 @@
<data name="StrMessageLutFile" xml:space="preserve">
<value>LUT:</value>
</data>
<data name="StrLutFileFromMeterInvalid" xml:space="preserve">
<value>ERROR: LUT installed in meter is invalid!</value>
</data>
<data name="StrLutFileFromSafeValid" xml:space="preserve">
<value>LUT from FW update safe is valid.</value>
</data>
</root>