Initial version of LUT file write GTB2.2.0
This commit is contained in:
@@ -1047,6 +1047,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
|
||||
/// </summary>
|
||||
public String CoreRevision;
|
||||
|
||||
/// <summary>
|
||||
/// This is the FLEXNET version which describes the entire packet.
|
||||
/// </summary>
|
||||
public String FwVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Region (EMEA or NA) and Radio frequency (433 or 868 or null).
|
||||
/// </summary>
|
||||
@@ -1102,6 +1107,8 @@ 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 (readFwVersion != 0)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
<Compile Include="Consts\FwUpdateState.cs" />
|
||||
<Compile Include="Consts\FwUpdateStateInfo.cs" />
|
||||
<Compile Include="Consts\FwUpdateStateText.cs" />
|
||||
<Compile Include="MeterLutFile.cs" />
|
||||
<Compile Include="MeterFileRestore.cs" />
|
||||
<Compile Include="MeterFilesEraseRestore.cs" />
|
||||
<Compile Include="MeterLutUpdate.cs" />
|
||||
@@ -91,6 +92,14 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\Logic.PrdoctionToProductMapper\Logic.ProductionToProductMapper.csproj">
|
||||
<Project>{D0C859D9-D55E-4E85-AC50-0FF31B1CE50D}</Project>
|
||||
<Name>Logic.ProductionToProductMapper</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\Utils\Crc16Ccitt\Crc16Ccitt.csproj">
|
||||
<Project>{91DEF0C0-AA4F-40AE-8F18-CB717FDE7E7F}</Project>
|
||||
<Name>Crc16Ccitt</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\Utils\Logging\Logging.csproj">
|
||||
<Project>{4B88B0D3-E791-4774-9521-EABEACDC420E}</Project>
|
||||
<Name>Logging</Name>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Logic.ProductionToProductMapper.Cordonel;
|
||||
|
||||
namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
{
|
||||
/// <summary>
|
||||
/// File for metrology look up table
|
||||
/// </summary>
|
||||
public class MeterLutFile
|
||||
{
|
||||
/// <summary>
|
||||
/// File name of the file on PC
|
||||
/// </summary>
|
||||
public String LutPcFileName;
|
||||
|
||||
/// <summary>
|
||||
/// Ctor file applications
|
||||
/// </summary>
|
||||
/// <param name="lutPcFileName"></param>
|
||||
public MeterLutFile(String lutPcFileName)
|
||||
{
|
||||
LutPcFileName = lutPcFileName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File ID for LUT file
|
||||
/// </summary>
|
||||
public String StrLutFileId;
|
||||
|
||||
/// <summary>
|
||||
/// Data length
|
||||
/// </summary>
|
||||
public UInt32 DataLength;
|
||||
|
||||
/// <summary>
|
||||
/// Version of LUT file
|
||||
/// </summary>
|
||||
public UInt16 Version;
|
||||
|
||||
/// <summary>
|
||||
/// Check of LUT file for verification and register write, read from file
|
||||
/// </summary>
|
||||
public UInt16 FileCrc;
|
||||
|
||||
/// <summary>
|
||||
/// Calculated during file processing for verification
|
||||
/// </summary>
|
||||
public UInt16 CalculatedCrc;
|
||||
|
||||
/// <summary>
|
||||
/// Validation of LUT file
|
||||
/// </summary>
|
||||
public Boolean IsValid;
|
||||
|
||||
/// <summary>
|
||||
/// Binary file content
|
||||
/// </summary>
|
||||
public List<Byte> BinData = new List<Byte>();
|
||||
|
||||
/// <summary>
|
||||
/// Meter size
|
||||
/// </summary>
|
||||
public MeterSize MeterSize;
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications;
|
||||
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;
|
||||
using Xylem.Common.Utils.ProcessExec;
|
||||
using Xylem.Common.Utils.ProcessExec.EventArguments;
|
||||
|
||||
@@ -26,14 +27,43 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
public event EventHandler<ProcessExecEventArgs> OnProcessUpdate;
|
||||
|
||||
//disk and name of lookup file
|
||||
private const String StrLutFileName = "1\\mettbl";
|
||||
private const String StrLutMeterFileName = "1\\mettbl";
|
||||
|
||||
//disk and name of lookup file
|
||||
private const String StrLutBackupFileName = "1\\mettbl_b";
|
||||
private const String StrLutBackupMeterFileName = "1\\mettbl_b";
|
||||
|
||||
// string as identifier for Genesis lookup table
|
||||
private const String TablesFileMagic = "GEN_LUT";
|
||||
// identifier for Genesis lookup table
|
||||
private const String StrLutFileId = "GEN_LUT\0";
|
||||
private const Int32 IndexLutFileId = 0;
|
||||
private const UInt32 LengthLutFileId = 8;
|
||||
|
||||
// data length, calculated from version field to the end of the data section
|
||||
private const Int32 IndexDataLength = 8;
|
||||
private const Int32 LengthDataLength = 4;
|
||||
|
||||
// CCITT-CRC-16 , calculated from version field to the end of the data section
|
||||
private const Int32 IndexCrc = 12;
|
||||
private const UInt32 LengthCrc = 2;
|
||||
|
||||
// version
|
||||
private const Int32 IndexVersion = 14;
|
||||
private const Int32 LengthVersion = 2;
|
||||
|
||||
// meter size as enumeration
|
||||
private const Int32 IndexMeterSize = 16;
|
||||
|
||||
// header size of file
|
||||
private const UInt32 LutFileHeaderLength =
|
||||
LengthLutFileId + LengthDataLength + LengthCrc + LengthVersion;
|
||||
|
||||
// data size of file
|
||||
private const Int32 LutFileDataLength = 730;
|
||||
|
||||
// LUT file entire file size
|
||||
private const UInt32 SizeLutFile = LutFileHeaderLength + LutFileDataLength;
|
||||
|
||||
|
||||
// process display message
|
||||
private const String StrProcessLut = "Processing metrology lookup table";
|
||||
|
||||
//trigger update retries
|
||||
@@ -62,9 +92,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
private Int32 _overallBytesCtr;
|
||||
|
||||
// Look up table file
|
||||
private Int32 _lutCrc;
|
||||
private Byte _meterSize;
|
||||
public FileApplications LutFile;
|
||||
public MeterLutFile LutFile;
|
||||
|
||||
// actual processed file
|
||||
private String _actualFileName;
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -142,7 +173,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
{
|
||||
_genesisMeter = genesisMeter;
|
||||
_actualOperation = "";
|
||||
LutFile = null;
|
||||
_lutUpdateState = LutUpdateState.Idle;
|
||||
}
|
||||
|
||||
@@ -181,7 +211,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
/// </remarks>
|
||||
public String GetLutUpdateStateOperation()
|
||||
{
|
||||
return _lutUpdateState == LutUpdateState.Idle ? "" : "Downloading...";
|
||||
return _lutUpdateState == LutUpdateState.Idle ? "" : $"Downloading {_actualFileName}...";
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -299,7 +329,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
/// </remarks>
|
||||
public Boolean UpdatePreparation()
|
||||
{
|
||||
_actualOperation = "";
|
||||
_actualOperation = "Update preparation";
|
||||
_lutUpdateState = LutUpdateState.Idle;
|
||||
|
||||
_meterFile = new MeterFile(_genesisMeter);
|
||||
@@ -418,41 +448,43 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
|
||||
#region LutFile
|
||||
/// <summary>
|
||||
/// Check the content of the metrology lookup table file:
|
||||
/// - begins with "APP>",
|
||||
/// - Application ID at position 0x28,
|
||||
/// - CRC at position 0x04 LSB, 0x05 MSB
|
||||
/// - Version at position 0x06 and 0x07 decimal
|
||||
/// - Build upgrade meter file name
|
||||
/// Check the content of the metrology lookup table file
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks date="2022-Feb-25" author="Thomas Wiedebusch">
|
||||
/// - Initial
|
||||
/// </remarks>
|
||||
private static Boolean ValidateLutFile()
|
||||
private Boolean ValidateLutFile()
|
||||
{
|
||||
//var fileApp = new FileApplications();
|
||||
//fileApp.AppId = fileApp.BinData[FileAppAppIdIndex];
|
||||
//fileApp.Crc = (UInt16)(fileApp.BinData[FileAppCrcIndex] + (fileApp.BinData[FileAppCrcIndex + 1] << 8));
|
||||
//fileApp.Version = (UInt32)((fileApp.BinData[FileAppVersionIndex] & 0x0F)
|
||||
// + ((fileApp.BinData[FileAppVersionIndex] & 0xF0) >> 4) * 10
|
||||
// + (fileApp.BinData[FileAppVersionIndex + 1] & 0x0F) * 100
|
||||
// + ((fileApp.BinData[FileAppVersionIndex + 1] & 0xF0) >> 4) * 1000);
|
||||
// check if LUT file contains data
|
||||
if (LutFile?.BinData == null || LutFile.BinData.Count < SizeLutFile) return false;
|
||||
|
||||
//fileApp.StrVersion = GenesisMeter.BuildFwVersionString(fileApp.BinData[FileAppVersionIndex + 1],
|
||||
// fileApp.BinData[FileAppVersionIndex]);
|
||||
//var fileAppStartId = Encoding.UTF8.GetString(fileApp.BinData.ToArray(), 0, 4);
|
||||
////check update file start identifier
|
||||
//if (fileAppStartId != StrFileAppStartId)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
LutFile.IsValid = false;
|
||||
// extract the identifier and check, if this is a LUT file
|
||||
LutFile.StrLutFileId =
|
||||
Encoding.UTF8.GetString(LutFile.BinData.ToArray(), IndexLutFileId, IndexDataLength);
|
||||
if (LutFile.StrLutFileId != StrLutFileId) return false;
|
||||
|
||||
////TODO THW check CRC
|
||||
////TODO THW check upgrade file name against content to select a valid package
|
||||
////the meter file name is needed for writing the file to the meter or reading it back
|
||||
//fileApp.MeterFilename = StrUpgradeAppPartialFileName + $"{fileApp.AppId:X2}";
|
||||
return true;
|
||||
LutFile.MeterSize = (MeterSize)LutFile.BinData[IndexMeterSize];
|
||||
LutFile.FileCrc = (UInt16)(LutFile.BinData[IndexCrc] + (LutFile.BinData[IndexCrc + 1] << 8));
|
||||
LutFile.Version = (UInt16)(LutFile.BinData[IndexVersion] + (LutFile.BinData[IndexVersion + 1] << 8));
|
||||
LutFile.DataLength = (UInt32)(LutFile.BinData[IndexDataLength]
|
||||
+ (LutFile.BinData[IndexDataLength + 1] << 8)
|
||||
+ (LutFile.BinData[IndexDataLength + 2] << 16)
|
||||
+ (LutFile.BinData[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(IndexVersion, LutFileDataLength + LengthVersion));
|
||||
var calculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray());
|
||||
if (calculatedCrc == LutFile.FileCrc)
|
||||
{
|
||||
LutFile.CalculatedCrc = calculatedCrc;
|
||||
LutFile.IsValid = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -465,15 +497,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
private Boolean PrepareLutDownload()
|
||||
{
|
||||
Boolean returnValue;
|
||||
_actualOperation = "Write Meter Size";
|
||||
|
||||
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
|
||||
{
|
||||
returnValue = _genesisMeter.WriteRegister<Byte>(Register.Genesisflow.MeterSize, _meterSize);
|
||||
returnValue &= _genesisMeter.WriteRegister<Int32>(Register.Genesisflow.LookupFileCrc, _lutCrc);
|
||||
_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);
|
||||
|
||||
if (!returnValue)
|
||||
@@ -504,11 +540,27 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
var retryCtr = 0;
|
||||
Boolean returnValue;
|
||||
|
||||
if (LutFile == null) return false;
|
||||
|
||||
//write file portion and retry if not successful
|
||||
do
|
||||
{
|
||||
returnValue = _meterFile.WriteMeterFile(StrLutFileName, LutFile.BinData.ToArray());
|
||||
returnValue &= _meterFile.WriteMeterFile(StrLutBackupFileName, LutFile.BinData.ToArray());
|
||||
|
||||
_actualFileName = StrLutMeterFileName;
|
||||
// unlock, erase and write original
|
||||
returnValue = _meterFile.UnlockEraseWriteMeterFile(_actualFileName);
|
||||
_actualOperation = $"Erase {_actualFileName}";
|
||||
returnValue &= _meterFile.EraseMeterFile(_actualFileName);
|
||||
_actualOperation = $"Write {_actualFileName}";
|
||||
returnValue &= _meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray());
|
||||
|
||||
_actualFileName = StrLutBackupMeterFileName;
|
||||
// write backup
|
||||
returnValue &= _meterFile.UnlockEraseWriteMeterFile(_actualFileName);
|
||||
_actualOperation = $"Erase {_actualFileName}";
|
||||
returnValue &= _meterFile.EraseMeterFile(_actualFileName);
|
||||
_actualOperation = $"Write {_actualFileName}";
|
||||
returnValue &= _meterFile.WriteMeterFile(_actualFileName, LutFile.BinData.ToArray());
|
||||
|
||||
if (!returnValue)
|
||||
{
|
||||
@@ -540,7 +592,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
|
||||
}
|
||||
|
||||
LutFile = null;
|
||||
LutFile = new FileApplications(filePathName)
|
||||
LutFile = new MeterLutFile(filePathName)
|
||||
{
|
||||
BinData = new List<Byte>(File.ReadAllBytes(filePathName))
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user