CUST: - FwUpdateSw tuned, GenesisMeter: - StoreAllConfigurations modified: first store all in a bulk, then read all back

This commit is contained in:
Thomas Wiedebusch 2023-11-22 08:22:56 +01:00
parent 19868e9eed
commit 3784287ffa
9 changed files with 2630 additions and 114 deletions

View File

@ -485,7 +485,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <param name="slot"></param>
/// <param name="ignoreCorruptedData"></param>
/// <exception cref="ApplicationException"></exception>
public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData = true )
public void SetupFromConfigFile(Int32 slot, Boolean ignoreCorruptedData = true)
{
SetupFromConfigFile(slot, ignoreCorruptedData, true, true);
}
@ -579,7 +579,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
var tmpUrl = $"http://10.49.40.25/MeterProcessState/api/TestBench/SetMeterLogPathInfo?SerialNumber={SerialNumber}&TestRunId={testRunString}&BasePath={basePath}&MainLogName={pathMain}&LEDName={pathRaw}";
_logger.Debug($"Request Url: { tmpUrl}");
//ToDO: Update to service URl
LocalWebRequest.GetRequest(tmpUrl,5000);
LocalWebRequest.GetRequest(tmpUrl, 5000);
}
}
@ -1844,7 +1844,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
var command = data.Length > RegisterDefinition.ChunkSize ?
Commands.MultipleWriteData : Commands.WriteData;
var responseRecord = RequestProtocol.CommandToMeter(command, regDef, data,
var responseRecord = RequestProtocol.CommandToMeter(command, regDef, data,
hideDataInLog: hideDataInLog, skipRetryErrorCode: skipRetryErrorCode);
if (!waitForResult && !checkRegister)
@ -1973,7 +1973,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// - Initial
/// </remarks>
// ReSharper disable once InconsistentNaming UI1236 is a naming forced by the caller
public Byte[] SendUI1236Command(Byte[] ui1236Frame, Boolean waitForResult = true, Boolean checkRegister = false,
public Byte[] SendUI1236Command(Byte[] ui1236Frame, Boolean waitForResult = true, Boolean checkRegister = false,
UInt16 skipRetryErrorCode = 4)
{
var requestIdent = $"Slot:{Slot} - Sending Ui-1236 frame";
@ -2171,12 +2171,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// <remarks date="2022-Jul-22" author="Thomas Wiedebusch">
/// - Removed temporary NA2ALARMS read back as this has no handler in the FW.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - Stored first all configurations for ever app, then read it back.
/// </remarks>
public Boolean StoreAllConfigurations()
{
var allConfigRegisters = _configRegister.MeterRegisterDic.Count(a =>
a.Key.RegisterName.ToLower() == "storeconfiguration" ||
a.Key.RegisterName.ToLower() == "storecalibration");
var retVal = true;
try
{
@ -2184,69 +2185,75 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
a.Key.RegisterName.ToLower() == "storeconfiguration" ||
a.Key.RegisterName.ToLower() == "storecalibration"))
{
if (!MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).Any() || !MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).First().IsInstalled)
if (!MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).Any() ||
!MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).First().IsInstalled)
{
//Skip because ap is not install
allConfigRegisters -= 1;
}
else
{
var done = false;
//retries for each register access
var retryLeft = 3;
while (retryLeft > 0 && !done)
// retries for each register access
var retriesLeft = 2;
Boolean result;
do
{
Thread.Sleep(50);
var result = WriteRegister(a.Key.GetIdent(), 1);
if (!result)
{
retryLeft -= 1;
if (retryLeft == 0)
{
return false;
}
Thread.Sleep(150);
result = WriteRegister(a.Key.GetIdent(), 1);
continue;
} while (!result && retriesLeft-- > 0);
}
// Wait for storing
Thread.Sleep(500);
//TODO enable this for R1.2.x take the version of FW
if (a.Key.AppName == "SENSUSRADIO" || a.Key.AppName == "NA2WALARMS")
{
done = true;
allConfigRegisters -= 1;
continue;
}
var resultRead = ReadRegister(a.Key.GetIdent());
if (resultRead == null || resultRead.ToList().Any(ra => ra != 0x00))
{
retryLeft -= 1;
if (retryLeft == 0)
{
return false;
}
continue;
}
done = true;
allConfigRegisters -= 1;
if (!result)
{
retVal = false;
}
}
}
}
catch (Exception)
{
return false;
retVal = false;
}
return allConfigRegisters == 0;
// check loop
try
{
foreach (var a in _configRegister.MeterRegisterDic.Where(a =>
a.Key.RegisterName.ToLower() == "storeconfiguration" ||
a.Key.RegisterName.ToLower() == "storecalibration"))
{
if (!MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).Any() ||
!MeterAppListVersion.Where(v => v.AppId == a.Key.AppAddress).First().IsInstalled)
{
}
else
{
//TODO enable this for R1.2.x take the version of FW
if (a.Key.AppName == "SENSUSRADIO" || a.Key.AppName == "NA2WALARMS")
{
continue;
}
// retries for each register access
var retriesLeft = 2;
Boolean result;
do
{
var readResult = ReadRegister(a.Key.GetIdent());
result = readResult != null && readResult.ToList().All(array => array == 0x00);
} while (!result && retriesLeft-- > 0);
if (!result)
{
retVal = false;
}
}
}
}
catch (Exception)
{
retVal = false;
}
return retVal;
}

View File

@ -195,9 +195,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
/// - Return true if already recovered,
/// - replace _restoreRegisters with new value.
/// </remarks>
/// <remarks date="2023-10-25" author="Thomas Wiedebusch">
/// <remarks date="2023-Oct-25" author="Thomas Wiedebusch">
/// - Added preparation and finalization of register recovery giving the ability to log this in the report.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - Moved register dictionary value set to inner try catch loop to avoid early exit if one register is
/// unknown.
/// </remarks>
public Boolean RecoverRegisters(List<RecoveryRegisterItem> recoveryRegisters)
{
if (_currentGenesis == null ||
@ -293,13 +297,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
// if this call does not throw an exception, the register is present
var regDef = meterRegisters.GetRegisterDefinitionByName(recReg.RegisterIdent);
// replace value in _restoreRegister with the required recovery value
_restoreRegisters?.Set(regDef, recReg.WriteValue);
var strRawAndConvertedValue = "";
try
{
strRawAndConvertedValue = RegisterConverter.GetRegisterContentText(regDef, recReg.WriteValue);
// replace value in _restoreRegister with the required recovery value
_restoreRegisters?.Set(regDef, recReg.WriteValue);
}
catch (Exception)
{
@ -437,8 +441,12 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore
}
else
{
var strReadBackRegisterValue =
RegisterConverter.GetRegisterRawText(regDef, finalReadRawRegister);
var strReadBackRegisterValue = "*****";
if (!regName.Contains("EncryptionKey") && !regName.Contains("Password"))
{
strReadBackRegisterValue = RegisterConverter.GetRegisterRawText(regDef, finalReadRawRegister);
}
strRequiredRegisterValue += $" - {Resources.StrMeterValue}: ({strReadBackRegisterValue})" +
$" - {Resources.StrRegisterCompareFailed}";
retVal = false;

View File

@ -11,6 +11,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile
/// </summary>
public class MeterLutFile
{
/// <summary>
/// Meter response on invalid LUT file e.g. 0x8000FFFF
/// </summary>
public const String StrLutFileInvalidCrc = "0x8000";
/// <summary>
/// Disk number and name name of meter LUT file
/// </summary>

View File

@ -43,7 +43,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes
/// </summary>
public override String ToString()
{
return $@"{DateTimeUtc:yyyy-MM-dd HH:mm:ss}";
return $@"{DateTimeUtc:yyyy-MM-dd HH:mm:ss} UTC";
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,688 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="SensusLogoXylem" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\Ui\CommonResources\SensusLogoXylem.JPG;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="StrProcessStateIdle" xml:space="preserve">
<value>Process state idle</value>
</data>
<data name="StrProcessStateInit" xml:space="preserve">
<value>Process state initial init</value>
</data>
<data name="StrProcessStateReInit" xml:space="preserve">
<value>Process state re init</value>
</data>
<data name="StrProcessStateConnecting" xml:space="preserve">
<value>Process state connecting</value>
</data>
<data name="StrProcessStatePortSelection" xml:space="preserve">
<value>Process state port selection</value>
</data>
<data name="StrProcessStatePortScan" xml:space="preserve">
<value>Process state port scan</value>
</data>
<data name="StrProcessStateConnect" xml:space="preserve">
<value>Process state connect</value>
</data>
<data name="StrProcessStateLoadUpdateFiles" xml:space="preserve">
<value>Process load update files</value>
</data>
<data name="StrProcessStateFwUpdateExit" xml:space="preserve">
<value>Process firmware update execution</value>
</data>
<data name="StrProcessStateStop" xml:space="preserve">
<value>Process stop</value>
</data>
<data name="StrCoreRevision" xml:space="preserve">
<value>System core revision:</value>
</data>
<data name="StrFwPackageInfo" xml:space="preserve">
<value>FW-Package:</value>
</data>
<data name="StrNotConnected" xml:space="preserve">
<value>NOT CONNECTED</value>
</data>
<data name="StrWaitForMeterResponse" xml:space="preserve">
<value>WAITING FOR CORDONEL RESPONSE</value>
</data>
<data name="StrBurnUpgrade" xml:space="preserve">
<value>Waiting for meter response</value>
</data>
<data name="StrConnecting" xml:space="preserve">
<value>Connecting to Cordonel</value>
</data>
<data name="StrCordonelAuthenticationFailed" xml:space="preserve">
<value>ERROR: Cordonel authentication failed.</value>
</data>
<data name="StrCordonelNotInUpdateList" xml:space="preserve">
<value>ERROR: Cordonel not in update list.</value>
</data>
<data name="StrCordonelAuthenticationSucceeded" xml:space="preserve">
<value>Cordonel authentication succeeded.</value>
</data>
<data name="StrCordonelAuthenticationUnspecified" xml:space="preserve">
<value>Cordonel authentication.</value>
</data>
<data name="StrCordonelDetectFailed" xml:space="preserve">
<value>ERROR: Cordonel detection failed</value>
</data>
<data name="StrCordonelDetectSucceeded" xml:space="preserve">
<value>Cordonel detected</value>
</data>
<data name="StrCordonelDetectUnspecified" xml:space="preserve">
<value>Cordonel detection.</value>
</data>
<data name="StrCordonelUpdateCapabilityCoreFailed" xml:space="preserve">
<value>ERROR: Incompatible core revision!</value>
</data>
<data name="StrCordonelUpdateCapabilityCoreSucceeded" xml:space="preserve">
<value>Core version is compatible.</value>
</data>
<data name="StrCordonelUpdateCapabilityMetrologyFailed" xml:space="preserve">
<value>ERROR: Deviating metrology version!</value>
</data>
<data name="StrCordonelUpdateCapabilityMetrologySucceeded" xml:space="preserve">
<value>Metrology version is approved</value>
</data>
<data name="StrCordonelUpdateCapabilityRegionFailed" xml:space="preserve">
<value>ERROR: Deviating region!</value>
</data>
<data name="StrCordonelUpdateCapabilityRegionSucceeded" xml:space="preserve">
<value>Region is approved!</value>
</data>
<data name="StrCordonelUpdateCapabilityMeterSizeFailed" xml:space="preserve">
<value>ERROR: Deviating meter size!</value>
</data>
<data name="StrCordonelUpdateCapabilityMeterSizeSucceeded" xml:space="preserve">
<value>Meter size is approved!</value>
</data>
<data name="StrCordonelUpdateCapabilityRadioFailed" xml:space="preserve">
<value>ERROR: Deviating radio frequency!</value>
</data>
<data name="StrCordonelUpdateCapabilityRadioSucceeded" xml:space="preserve">
<value>Radio frequency is approved!</value>
</data>
<data name="StrCordonelUpdateCapabilitySucceeded" xml:space="preserve">
<value>Update capability validated.</value>
</data>
<data name="StrCordonelUpdateCapabilityUnspecified" xml:space="preserve">
<value>Update capability.</value>
</data>
<data name="StrDataContainerUnknown" xml:space="preserve">
<value>ERROR: Unknown data container received</value>
</data>
<data name="StrFailedToUpdateApp" xml:space="preserve">
<value>ERROR: Failed to update application:</value>
</data>
<data name="StrFirmwareUpdateFailed" xml:space="preserve">
<value>ERROR: Firmware update failed!</value>
</data>
<data name="StrFirmwareUpdateBreak" xml:space="preserve">
<value>Firmware update user break!</value>
</data>
<data name="StrFirmwareUpdateCheck" xml:space="preserve">
<value>Firmware update validating....</value>
</data>
<data name="StrFirmwareUpdateOngoing" xml:space="preserve">
<value>Firmware update in process....</value>
</data>
<data name="StrFirmwareUpdateSucceeded" xml:space="preserve">
<value>Firmware update succeeded.</value>
</data>
<data name="StrFirmwareUpdateUnspecified" xml:space="preserve">
<value>Firmware update.</value>
</data>
<data name="StrFwUpToDateMessage" xml:space="preserve">
<value>Firmware is up to date!</value>
</data>
<data name="StrHistoryWindowShow" xml:space="preserve">
<value>Show History</value>
</data>
<data name="StrHistoryWindowToggle" xml:space="preserve">
<value>Toggle History</value>
</data>
<data name="StrMessageAppNotInstalled" xml:space="preserve">
<value>Not installed</value>
</data>
<data name="StrMessageInstalledApp" xml:space="preserve">
<value>Installed applications:</value>
</data>
<data name="StrMessageSystemCoreRevision" xml:space="preserve">
<value>System Core Revision:</value>
</data>
<data name="StrMessageSystemRegion" xml:space="preserve">
<value>Region:</value>
</data>
<data name="StrMessageSystemRadio" xml:space="preserve">
<value>Radio frequency[MHz]:</value>
</data>
<data name="StrMessageWindowFailed" xml:space="preserve">
<value>FAILED</value>
</data>
<data name="StrMessageWindowSuccess" xml:space="preserve">
<value>SUCCESS</value>
</data>
<data name="StrOverallProcess" xml:space="preserve">
<value>Overall process</value>
</data>
<data name="StrPackageFileInvalid" xml:space="preserve">
<value>ERROR: ADF invalid</value>
</data>
<data name="StrPackageFileToFileAppsMismatch" xml:space="preserve">
<value>ERROR: ADF to ABC mismatch</value>
</data>
<data name="StrPartPcbConnected" xml:space="preserve">
<value>Connected to PCB ID:</value>
</data>
<data name="StrPasswordFileNotInstalled" xml:space="preserve">
<value>ERROR: Password file not installed!</value>
</data>
<data name="StrPasswordFileReadoutFailed" xml:space="preserve">
<value>ERROR: Password file readout failed!</value>
</data>
<data name="StrPasswordFileReadoutSucceeded" xml:space="preserve">
<value>Password file readout succeeded.</value>
</data>
<data name="StrPasswordFileReadoutUnspecified" xml:space="preserve">
<value>Password file readout.</value>
</data>
<data name="StrPasswordFileRestoreFailed" xml:space="preserve">
<value>ERROR: Password file restore failed!</value>
</data>
<data name="StrPasswordFileNotDelivered" xml:space="preserve">
<value>ERROR: Password file is not in password container!</value>
</data>
<data name="StrPasswordFileRestoreSucceeded" xml:space="preserve">
<value>Password file restore succeeded.</value>
</data>
<data name="StrPasswordFileRestoreActive" xml:space="preserve">
<value>Password file installation actice...</value>
</data>
<data name="StrPasswordFileValid" xml:space="preserve">
<value>Password file validated with level 8 login.</value>
</data>
<data name="StrPasswordFileRestoreUnspecified" xml:space="preserve">
<value>Password file restore.</value>
</data>
<data name="StrPortConfigurationFileLoaded" xml:space="preserve">
<value>Port Configuration File loaded.</value>
</data>
<data name="StrPortNoReadFromFile" xml:space="preserve">
<value>Read from file.</value>
</data>
<data name="StrProductToInstall" xml:space="preserve">
<value>FW Update:</value>
</data>
<data name="StrRegisterUserBreak" xml:space="preserve">
<value>Configuration readout user break!</value>
</data>
<data name="StrRegisterReadoutFailed" xml:space="preserve">
<value>ERROR: Configuration readout failed!</value>
</data>
<data name="StrRegisterAccessActive" xml:space="preserve">
<value>Configuration access active....</value>
</data>
<data name="StrRegisterReadoutSucceeded" xml:space="preserve">
<value>Configuration readout succeeded.</value>
</data>
<data name="StrRegisterReadoutUnspecified" xml:space="preserve">
<value>Configuration readout.</value>
</data>
<data name="StrRegisterRestoreFailed" xml:space="preserve">
<value>ERROR: Configuration restoring failed!</value>
</data>
<data name="StrRegisterRestoreSucceeded" xml:space="preserve">
<value>Configuration restoring succeeded.</value>
</data>
<data name="StrRegisterRestoreUnspecified" xml:space="preserve">
<value>Configuration backup.</value>
</data>
<data name="StrRequestPortFailed" xml:space="preserve">
<value>ERROR: Request port not detected!</value>
</data>
<data name="StrRequestPortSucceeded" xml:space="preserve">
<value>Request port found.</value>
</data>
<data name="StrRequestPortUnspecified" xml:space="preserve">
<value>Request port detection.</value>
</data>
<data name="StrTableAppId" xml:space="preserve">
<value>AppId</value>
</data>
<data name="StrTableAppName" xml:space="preserve">
<value>AppName</value>
</data>
<data name="StrTableErase" xml:space="preserve">
<value>Erase</value>
</data>
<data name="StrTableFileCrc" xml:space="preserve">
<value>FileCrc</value>
</data>
<data name="StrTableFileSize" xml:space="preserve">
<value>FileSize [kB]</value>
</data>
<data name="StrTableFileVersion" xml:space="preserve">
<value>FileVersion</value>
</data>
<data name="StrTableMeterCrc" xml:space="preserve">
<value>MeterCrc</value>
</data>
<data name="StrTableMeterVersion" xml:space="preserve">
<value>MeterVersion</value>
</data>
<data name="StrTableStatus" xml:space="preserve">
<value>Status</value>
</data>
<data name="StrTableUpdate" xml:space="preserve">
<value>Download</value>
</data>
<data name="StrTestLoginFailed" xml:space="preserve">
<value>ERROR: Test login failed!</value>
</data>
<data name="StrTestLoginSucceeded" xml:space="preserve">
<value>Test Login succeeded.</value>
</data>
<data name="StrTestLoginUnspecified" xml:space="preserve">
<value>Test login.</value>
</data>
<data name="StrTestReportFailed" xml:space="preserve">
<value>ERROR: Test report generation failed!</value>
</data>
<data name="StrTestReportSucceeded" xml:space="preserve">
<value>Test report created.</value>
</data>
<data name="StrTestReportDate" xml:space="preserve">
<value>FW-Update Date:</value>
</data>
<data name="StrTestReportOrderNumber" xml:space="preserve">
<value>Order Number:</value>
</data>
<data name="StrTestReportCustomerName" xml:space="preserve">
<value>Customer Name:</value>
</data>
<data name="StrTestReportSwNameVersion" xml:space="preserve">
<value>FW-Update Software Info: FwUpdateSw Version:</value>
</data>
<data name="StrTestReportUnspecified" xml:space="preserve">
<value>Test report.</value>
</data>
<data name="StrUpdateAppAndRestartMeter" xml:space="preserve">
<value>Update applications and restart meter</value>
</data>
<data name="StrUpdateInformationStatusFailed" xml:space="preserve">
<value>ERROR: Update information incomplete!</value>
</data>
<data name="StrUpdateInformationStatusSucceeded" xml:space="preserve">
<value>Update information complete.</value>
</data>
<data name="StrUpdateInformationStatusUnspecified" xml:space="preserve">
<value>Update information status.</value>
</data>
<data name="StrUpdatePackageInvalid" xml:space="preserve">
<value>ERROR: Update package invalid!</value>
</data>
<data name="StrUpdatePathEmpty" xml:space="preserve">
<value>ERROR: No update files in path!</value>
</data>
<data name="StrUpdatePathInvalid" xml:space="preserve">
<value>ERROR: Update path invalid!</value>
</data>
<data name="StrUserStop" xml:space="preserve">
<value>User stopped operation</value>
</data>
<data name="StrLanguageChangeItemRestorageFailed" xml:space="preserve">
<value>ERROR: Failed to restore items after change of language!</value>
</data>
<data name="StrRegisterCompareActive" xml:space="preserve">
<value>Comparing configuration.....</value>
</data>
<data name="StrRegisterReadoutActive" xml:space="preserve">
<value>Reading configuration......</value>
</data>
<data name="StrSoftwareVersionExpired" xml:space="preserve">
<value>ERROR: The software license is expired! Program will be exited!</value>
</data>
<data name="StrRebootFailed" xml:space="preserve">
<value>ERROR: Device reboot timeout! Press [Connect]!</value>
</data>
<data name="StrFileAccessUserBreak" xml:space="preserve">
<value>File access readout user break!</value>
</data>
<data name="StrFileRead" xml:space="preserve">
<value>Files read from meter:</value>
</data>
<data name="StrFileErased" xml:space="preserve">
<value>Files erased from meter:</value>
</data>
<data name="StrFileRestored" xml:space="preserve">
<value>Files restored to meter:</value>
</data>
<data name="StrFileReadoutFailed" xml:space="preserve">
<value>ERROR: File readout failed!</value>
</data>
<data name="StrFileEraseNotDefined" xml:space="preserve">
<value>No meter files defined to erase!</value>
</data>
<data name="StrFileRestoreNotDefined" xml:space="preserve">
<value>No meter files defined to restore!</value>
</data>
<data name="StrFileAccessActive" xml:space="preserve">
<value>File access active....</value>
</data>
<data name="StrFileErasing" xml:space="preserve">
<value>Erasing file </value>
</data>
<data name="StrFileRestoring" xml:space="preserve">
<value>Restoring file </value>
</data>
<data name="StrFileEraseSucceeded" xml:space="preserve">
<value>File erasure succeeded.</value>
</data>
<data name="StrFileReadoutUnspecified" xml:space="preserve">
<value>File readout and erase.</value>
</data>
<data name="StrFileRestoreFailed" xml:space="preserve">
<value>ERROR: File restore failed!</value>
</data>
<data name="StrFileRestoreSucceeded" xml:space="preserve">
<value>File restore succeeded.</value>
</data>
<data name="StrFileRestoreUnspecified" xml:space="preserve">
<value>File backup.</value>
</data>
<data name="StrFileReadoutSucceeded" xml:space="preserve">
<value>File readout succeeded.</value>
</data>
<data name="StrStoreConfigFailed" xml:space="preserve">
<value>ERROR: Failed to store configurations!</value>
</data>
<data name="StrStoreConfigSuccess" xml:space="preserve">
<value>Successfully stored configurations.</value>
</data>
<data name="StrRadioActivationFailed" xml:space="preserve">
<value>ERROR: Failed to activate the radio in customer mode!</value>
</data>
<data name="StrRadioAlreadyActive" xml:space="preserve">
<value>Radio is in customer mode.</value>
</data>
<data name="StrRadioActivationSuccess" xml:space="preserve">
<value>Successfully activated the radio in customer mode.</value>
</data>
<data name="StrReleaseDisplaySucceeded" xml:space="preserve">
<value>Display released to accumulator- and flow-display.</value>
</data>
<data name="StrPulseModeInactive" xml:space="preserve">
<value>Pulse mode is inactive.</value>
</data>
<data name="StrPulseModeRestored" xml:space="preserve">
<value>Original pulse mode restored.</value>
</data>
<data name="StrPulseModeTemporaryDeactivated" xml:space="preserve">
<value>Pulse mode temporary deactivated.</value>
</data>
<data name="StrMessageLutCrc" xml:space="preserve">
<value>LUT CRC:</value>
</data>
<data name="StrMessageMeterSize" xml:space="preserve">
<value>MeterSize:</value>
</data>
<data name="StrDateTimeSetupFailed" xml:space="preserve">
<value>ERROR: Failed to setup date time!</value>
</data>
<data name="StrDateTimeSetupSucceeded" xml:space="preserve">
<value>Date time successfully set</value>
</data>
<data name="StrLoginPwdLevel8" xml:space="preserve">
<value>Successfully logged in with password level 8.</value>
</data>
<data name="StrLoginSkeletonKey" xml:space="preserve">
<value>Successfully logged in with skeletonKey.</value>
</data>
<data name="StrMessageCustomerSerialNumber" xml:space="preserve">
<value>Customer serial number:</value>
</data>
<data name="StrMessageHashedPwdFile" xml:space="preserve">
<value>Hashed password file:</value>
</data>
<data name="StrLedOffFailed" xml:space="preserve">
<value>ERROR: Switching LED off failed!</value>
</data>
<data name="StrLedOffSucceeded" xml:space="preserve">
<value>LED switched off.</value>
</data>
<data name="StrReleaseDisplayFailed" xml:space="preserve">
<value>ERROR: Display release failed!</value>
</data>
<data name="StrRegisterRecoveryFailed" xml:space="preserve">
<value>ERROR: Configuration recovery failed!</value>
</data>
<data name="StrRegisterRecoverySucceeded" xml:space="preserve">
<value>Configuration recovery succeeded.</value>
</data>
<data name="StrPasswordFileCompareSucceeded" xml:space="preserve">
<value>Installed password file is equal to required password file.</value>
</data>
<data name="StrPasswordFileCompareFailed" xml:space="preserve">
<value>ERROR: Installed password file is unequal to required file!</value>
</data>
<data name="StrTestReporSafeName" xml:space="preserve">
<value>FW-Update Safe Name:</value>
</data>
<data name="StrTestReportCustomerNumber" xml:space="preserve">
<value>Customer Number:</value>
</data>
<data name="StrTestReportFwUpdateBuilderInfo" xml:space="preserve">
<value>FW-Update Builder Info:</value>
</data>
<data name="StrTestReportFwUpdateFieldOperator" xml:space="preserve">
<value>FW-Update Field Operator ID:</value>
</data>
<data name="StrTestReportFwUpdateValidDate" xml:space="preserve">
<value>FW-Update Safe Valid Date:</value>
</data>
<data name="StrTestReportSafeBuiltDate" xml:space="preserve">
<value>FW-UpdateSafe Built Date:</value>
</data>
<data name="StrTestReportSafeBuiltOperator" xml:space="preserve">
<value>FW-Update Builder Operator ID:</value>
</data>
<data name="StrPasswordFileFromSafeInvalid" xml:space="preserve">
<value>ERROR: Password file from FW update safe is invalid!</value>
</data>
<data name="StrLutFileNotInstalled" xml:space="preserve">
<value>ERROR: LUT is required but not installed!</value>
</data>
<data name="StrLutFileNotNeeded" xml:space="preserve">
<value>LUT not required for this FW.</value>
</data>
<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>
</data>
<data name="StrLutFileCompareSucceeded" xml:space="preserve">
<value>Installed LUT is equal to required LUT.</value>
</data>
<data name="StrLutFileFromSafeInvalid" xml:space="preserve">
<value>ERROR: LUT from FW update safe invalid!</value>
</data>
<data name="StrLutFileNotDelivered" xml:space="preserve">
<value>ERROR: LUT is not in FW updae safe!</value>
</data>
<data name="StrLutFileReadoutFailed" xml:space="preserve">
<value>ERROR: LUT readout failed!</value>
</data>
<data name="StrLutFileReadoutSucceeded" xml:space="preserve">
<value>LUT readout succeeded.</value>
</data>
<data name="StrLutFileReadoutUnspecified" xml:space="preserve">
<value>LUT readout.</value>
</data>
<data name="StrLutFileRestoreActive" xml:space="preserve">
<value>LUT validation active...</value>
</data>
<data name="StrLutFileRestoreFailed" xml:space="preserve">
<value>ERROR: LUT restoring failed!</value>
</data>
<data name="StrLutFileRestoreSucceeded" xml:space="preserve">
<value>LUT restoring succeeded.</value>
</data>
<data name="StrLutFileRestoreUnspecified" xml:space="preserve">
<value>LUT restoring.</value>
</data>
<data name="StrMessageLutFile" xml:space="preserve">
<value>LUT file installed in meter:</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>
<data name="StrEngineeringLogsReadFailed" xml:space="preserve">
<value>ERROR: Engineering logs processing failed!</value>
</data>
<data name="StrLifeTimeCalculationFailed" xml:space="preserve">
<value>ERROR: Life time calculation failed!</value>
</data>
<data name="StrLifeTimeCalculation" xml:space="preserve">
<value>Life time calculation:</value>
</data>
<data name="StrLifeTimeCalculationSucceeded" xml:space="preserve">
<value>Life time calculation succeeded.</value>
</data>
<data name="StrLifeTimeDrainedBattery" xml:space="preserve">
<value>Drained battery load: </value>
</data>
<data name="StrLifeTimeRemainingYears" xml:space="preserve">
<value>Remaining life time:</value>
</data>
<data name="StrLifeTimeYears" xml:space="preserve">
<value>years</value>
</data>
<data name="StrRegisterCompareFailed" xml:space="preserve">
<value>ERROR: Configuration comparison failed!</value>
</data>
<data name="StrRegisterCompareSucceeded" xml:space="preserve">
<value>Successfully compared configuration.</value>
</data>
</root>

View File

@ -40,6 +40,12 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw.Const
/// </summary>
InitialConnect,
/// <summary>
/// Connecting including dispose of Genesis to force entire new read out of
/// applications and restructure of registers as they may have changed after update.
/// </summary>
RebootConnect,
/// <summary>
/// Connecting including dispose of Genesis to force entire new read out of
/// applications and restructure of registers as they may have changed after update.

View File

@ -100,7 +100,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// initial connect to force a quick connect being able switch the pulse mode off
private Boolean _initialConnect;
// remind final login, as this allows EXPLICIT login with password level 8 to validate password file
private Boolean _finalLoginAfterUpdate;
private Boolean _afterUpdateConnect;
// remind recovery request to check finally all register settings
private Boolean _recoveryRegistersRequired;
// reminder for Genesis found in update list (_cordonelDeviceInfos)
@ -176,8 +176,8 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// Login retry parameters to delay recurrent login trial after unsuccessfully trial to avoid lock
// of authentication by the meter
private Int32 _loginDelay_ms;
private const Int32 DefaultLoginDelay_ms = 1000;
private Int32 _loginDelay_ms = DefaultLoginDelay_ms;
// directory information
private List<String> _readMeterFiles;
@ -193,9 +193,10 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
private List<ProcessState> _stateSequencePrepareMeterRelease = new List<ProcessState>
{
ProcessState.RestoreMeterFiles,
ProcessState.RestoreLutFile,
ProcessState.RecoverRegisters,
ProcessState.FinalReadRegisters,
ProcessState.CompareRegisters,
ProcessState.RestoreLutFile,
ProcessState.RestorePasswordFile,
ProcessState.FinalConnect,
ProcessState.VerifyMeterFiles,
@ -213,7 +214,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
ProcessState.InitialReadRegisters,
ProcessState.InitialReadMeterFiles,
ProcessState.ReadInfoEraseRestoreFiles,
ProcessState.RecoverRegisters,
ProcessState.LoadUpdateFiles,
ProcessState.CheckUpdateRequest
};
@ -226,7 +226,8 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
ProcessState.EraseMeterFiles,
ProcessState.FirmwareUpdate,
ProcessState.Reboot,
ProcessState.FinalConnect
ProcessState.RebootConnect,
ProcessState.RestoreMeterFiles
};
/// <summary>
@ -319,6 +320,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// <remarks date="2023-Nov-15..21" author="Thomas Wiedebusch">
/// - State machine sequences based on ProcessState tables forcing the sequencing.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - Restore meter files and compare registers removed for this release.
/// </remarks>
private void FwUpdateSwStateMachine()
{
while (!_processToken.IsCancellationRequested)
@ -372,7 +376,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
case ProcessState.InitialConnect:
DisposeGenesis();
_initialConnect = true;
_finalLoginAfterUpdate = false;
_afterUpdateConnect = false;
_recoveryRegistersRequired = false;
Connect(GetNextProcessState(_processState, _stateSequencePrepareAndCheckMeter));
break;
@ -390,10 +394,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
_stateSequencePrepareAndCheckMeter));
break;
case ProcessState.RecoverRegisters:
RegisterRecovery(GetNextProcessState(_processState, _stateSequencePrepareAndCheckMeter));
break;
case ProcessState.LoadUpdateFiles:
LoadUpdateFiles(GetNextProcessState(_processState, _stateSequencePrepareAndCheckMeter));
break;
@ -417,21 +417,20 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
break;
case ProcessState.Reboot:
_finalLoginAfterUpdate = true;
_afterUpdateConnect = true;
Reboot(GetNextProcessState(_processState, _stateSequenceFwUpdate));
break;
case ProcessState.FinalConnect:
case ProcessState.RebootConnect:
DisposeGenesis();
// Final connect will be used after update and after password file installation
Connect(_finalLoginAfterUpdate ? ProcessState.RestoreMeterFiles :
GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
Connect(GetNextProcessState(_processState, _stateSequenceFwUpdate));
break;
case ProcessState.RestoreMeterFiles:
// Restore meter files is necessary after FW-Update procedure as this has erased
// those files before the update.
MeterFilesRestore(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
//TODO THW MeterFilesRestore(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
_processState = GetNextProcessState(_processState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.PrepareMeterRelease:
@ -441,8 +440,16 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// ATTENTION: Needed to reassign to "ProcessState.RestoreLutFile" to set a valid state
// of the _stateSequencePrepareMeterRelease beyond the FW-Update entry. This is needed
// to start the sequence.
_processState = ProcessState.FinalReadRegisters;
_processState = ProcessState.RestoreLutFile;
break;
case ProcessState.RestoreLutFile:
RestoreLutFile(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
case ProcessState.RecoverRegisters:
RegisterRecovery(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
case ProcessState.FinalReadRegisters:
// Read the registers after update as the definitions may have changed or after recovery
// has been executed
@ -450,17 +457,19 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
break;
case ProcessState.CompareRegisters:
ReadRegisters(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
case ProcessState.RestoreLutFile:
RestoreLutFile(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
//TODO THW ReadRegisters(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
_processState = GetNextProcessState(_processState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.RestorePasswordFile:
RestorePasswordFile(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
case ProcessState.FinalConnect:
_afterUpdateConnect = false;
Connect(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
case ProcessState.VerifyMeterFiles:
ReadMeterFiles(GetNextProcessState(_processState, _stateSequencePrepareMeterRelease));
break;
@ -552,7 +561,10 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// - UiInvoker needed as timer now being called from separate thread.
/// </remarks>
/// <remarks date="2021-Nov-16" author="Thomas Wiedebusch">
/// - Added new states..
/// - Added new states.
/// </remarks>
/// <remarks date="2023-Nov-16..22" author="Thomas Wiedebusch">
/// - Added new states.
/// </remarks>
private void TmrProgressUpdate_Tick(Object state)
{
@ -572,9 +584,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
case ProcessState.PreUpdateReadMeterFiles:
case ProcessState.RestorePasswordFile:
case ProcessState.RestoreLutFile:
case ProcessState.RecoverRegisters:
case ProcessState.ReadEngineeringLogs:
case ProcessState.InitialConnect:
case ProcessState.RebootConnect:
case ProcessState.FinalConnect:
// These routines do not have an event callback handler
if (_progressBarValueCounter++ > 100)
@ -1395,7 +1407,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
};
LogStringList(Resources.StrCoreRevision, coreLineList,
Resources.StrCordonelUpdateCapabilityCoreFailed);
errorMessage: Resources.StrCordonelUpdateCapabilityCoreFailed);
InfoProcessFailed(lblCordonelUpdateCapability, Resources.StrCordonelUpdateCapabilityCoreFailed, false);
_processState = ProcessState.Error;
@ -1632,7 +1644,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
private void BtnConnect_Click(Object sender, EventArgs e)
{
// restart for new device
_finalLoginAfterUpdate = false;
_afterUpdateConnect = false;
if (_resetTimeMeasurement)
{
_startTime = DateTimeOffset.UtcNow;
@ -1835,6 +1847,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// <remarks date="2023-Nov-13" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - LUT file invalid as it cannot be read.
/// </remarks>
private Boolean ReadLogAndCompareMeterLutFile()
{
if (_currentGenesis == null)
@ -1897,6 +1912,12 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
retVal = false;
}
}
// Here the LUT file format is invalid
else
{
LogStringList(Resources.StrMessageLutFile, lutLineList,
errorMessage: Resources.StrLutFileFromMeterInvalid);
}
}
catch (Exception)
{
@ -2735,12 +2756,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// Even if this state failed try to maintain the next steps of the sequence
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareAndCheckMeter);
break;
case ProcessState.RecoverRegisters:
msg = Resources.StrRegisterRecoveryFailed;
ErrorProcessCommon(msg);
// Even if this state failed try to maintain the next steps of the sequence
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareAndCheckMeter);
break;
case ProcessState.LoadUpdateFiles:
msg = Resources.StrUpdateInformationStatusFailed;
ErrorProcessCommon(msg);
@ -2754,6 +2769,17 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
ErrorProcessCommon(msg);
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.RestoreLutFile:
msg = Resources.StrLutFileRestoreFailed;
ErrorProcessCommon(msg);
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.RecoverRegisters:
msg = Resources.StrRegisterRecoveryFailed;
ErrorProcessCommon(msg);
// Even if this state failed try to maintain the next steps of the sequence
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.FinalReadRegisters:
msg = Resources.StrRegisterReadoutFailed;
ErrorProcessCommon(msg);
@ -2764,11 +2790,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
ErrorProcessCommon(msg);
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.RestoreLutFile:
msg = Resources.StrLutFileRestoreFailed;
ErrorProcessCommon(msg);
_processState = GetNextProcessState(_invokerProcessState, _stateSequencePrepareMeterRelease);
break;
case ProcessState.RestorePasswordFile:
msg = Resources.StrPasswordFileRestoreFailed;
ErrorProcessCommon(msg);
@ -3439,6 +3460,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// <remarks date="2023-Nov-17" author="Thomas Wiedebusch">
/// - LoginDelay dynamically based on trials, reset after successfully login.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - Added password valid information main screen and log file.
/// </remarks>
private Boolean ExecConnect()
{
// If the PCB ID is not set (read from meter) this is the first initial login.
@ -3490,6 +3514,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// Reset login delay as on successfully login the meter resets the retry-lock-in-delay
_loginDelay_ms = DefaultLoginDelay_ms;
LogText(Resources.StrLoginPwdLevel8);
InfoProcessSuccess(lblPasswordFileCheck, Resources.StrPasswordFileValid);
_passwordFileIsCorrupted = false;
return true;
}
@ -3580,7 +3605,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// Second login if initial was executed including reading out all installed applications
retVal = _currentGenesis.Login(password);
// Set radio to customer mode (encryption active)
if (_initialConnect && _currentGenesis.RadioFrequencyMhz != null)
{
@ -3601,7 +3626,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// remind initial connect has been executed once
_initialConnect = false;
}
return retVal;
}
/// <summary>
@ -3661,6 +3685,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// <remarks date="2023-Oct-15" author="Thomas Wiedebusch">
/// - Log always installed meter FW.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - FInal login is not a garant for valid password file anymore.
/// </remarks>
private void FinalizeConnect(Boolean success, IReadOnlyList<Object> exitProcessStateObjects)
{
ObjectsToProcessStates(exitProcessStateObjects, out var successExitState, out var errorExitState,
@ -3691,9 +3718,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
// if authentication succeeded, the cordonel port detection must have succeeded in advance,
// this information might get lost on Connect() without previous port scan.
InfoProcessSuccess(lblCordonelDetection, Resources.StrCordonelDetectSucceeded);
InfoProcessSuccess(lblCordonelAuthentication, _finalLoginAfterUpdate
? Resources.StrPasswordFileValid
: Resources.StrCordonelAuthenticationSucceeded);
InfoProcessSuccess(lblCordonelAuthentication, Resources.StrCordonelAuthenticationSucceeded);
// use here direct text assignment to avoid x or v before label
UiInvoker.ControlInvoker(lblConnectPcb, ColorSuccess,
@ -3782,7 +3807,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
break;
case ProcessState.FinalReadRegisters:
if (_finalLoginAfterUpdate || _recoveryRegistersRequired)
if (_afterUpdateConnect || _recoveryRegistersRequired)
{
retVal = _registerRestorer.FinalReadRegisters();
}
@ -3793,7 +3818,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
break;
case ProcessState.CompareRegisters:
if (_finalLoginAfterUpdate || _recoveryRegistersRequired)
if (_afterUpdateConnect || _recoveryRegistersRequired)
{
retVal = _registerRestorer.CompareRegisters();
}
@ -4281,8 +4306,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
ReadLogAndCompareMeterPwdFile())
{
_passwordFileIsCorrupted = false;
_finalLoginAfterUpdate = false;
_afterUpdateConnect = false;
InfoProcessSuccess(lblPasswordFileCheck, Resources.StrPasswordFileRestoreSucceeded);
_processState = successExitState;
}
else
{
@ -4316,20 +4342,31 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
/// - For FW version without LUT file needed return with success state,
/// - Reading initially the header to get the length of the LUT.
/// </remarks>
/// <remarks date="2023-Nov-22" author="Thomas Wiedebusch">
/// - Taking meter response of invalid LUT file indicated by 0x8000xxxx.
/// </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, false);
// 1. LUT file NOT installed:
// 1. LUT file is invalid indicated by CRC
if (_currentGenesis.LutCrc.Contains(MeterLutFile.StrLutFileInvalidCrc))
{
InfoProcessFailed(lblLutFileCheck, Resources.StrLutFileNotInstalled);
_processState = errorExitState;
return;
}
// 2. 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)) &&
_readMeterFiles != null && !_readMeterFiles.Any(f => f.Contains(MeterLutFile.StrLutMeterFileName)))
{
// 1. a) LUT file not installed but required by the FW update safe:
// 2. 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)
@ -4339,7 +4376,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
return;
}
// 1. b) LUT file not installed and not delivered by the FW update safe
// 2. b) LUT file not installed and not delivered by the FW update safe
// This FW version does not require a LUT file
InfoProcessSuccess(lblLutFileCheck, Resources.StrLutFileNotNeeded);
_processState = successExitState;
@ -4347,11 +4384,11 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
return;
}
// 2. LUT file is installed:
// 2.a) Lut file is installed but NOT in the safe:
// 3. LUT file is installed:
// 3.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:
// 3.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())
{
@ -4686,7 +4723,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw
LogText($"{Resources.StrTestReportSafeBuiltDate} " +
$"{_fwUpdateSafeInfo.SafeBuiltDateTime:dddd, dd-MMM-yyyy HH:mm:ss} UTC");
LogText($"{Resources.StrTestReportSafeBuiltOperator} " + _fwUpdateSafeInfo.FwUpdateBuilderOperatorId);
LogText(StrSeparator);
LogText($"{Resources.StrTestReportCustomerName} " + _fwUpdateSafeInfo.CustomerName);
LogText($"{Resources.StrTestReportCustomerNumber} " + _fwUpdateSafeInfo.CustomerNumber);