diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index fb760125..cb363074 100644 --- a/.gitignore +++ b/.gitignore @@ -98,6 +98,7 @@ StyleCopReport.xml *.pidb *.svclog *.scc +*.cache # Chutzpah Test files _Chutzpah* diff --git a/Common/.shared/SharedAssemblyInfo.cs b/Common/.shared/SharedAssemblyInfo.cs index 27f21205..b35ecebf 100644 --- a/Common/.shared/SharedAssemblyInfo.cs +++ b/Common/.shared/SharedAssemblyInfo.cs @@ -14,5 +14,5 @@ using System.Reflection; //[assembly: AssemblyVersion("1.2.*.0")] -[assembly: AssemblyVersion("2.1.4.*")] -[assembly: AssemblyFileVersion("2.1.4.04")] \ No newline at end of file +[assembly: AssemblyVersion("2.2.0.*")] +[assembly: AssemblyFileVersion("1.3.0.10")] \ No newline at end of file diff --git a/Common/.vs/config/applicationhost.config b/Common/.vs/config/applicationhost.config index 40cde372..1b9332b4 100644 --- a/Common/.vs/config/applicationhost.config +++ b/Common/.vs/config/applicationhost.config @@ -155,7 +155,7 @@ - + diff --git a/Common/Common.sln.DotSettings b/Common/Common.sln.DotSettings index 24aa8d10..e2741c0c 100644 --- a/Common/Common.sln.DotSettings +++ b/Common/Common.sln.DotSettings @@ -4,6 +4,8 @@ True True True + True + True True True diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index 5b1490a2..eb584f9a 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -22,6 +22,9 @@ <Assembly Path="D:\Projekte\SENSUS_tfs_workspaces\WorkBenchV2\Main\Common\Ui\IrdaFunctionalTestApp\bin\Debug\Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.dll" /> </AssemblyExplorer> True + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Solution /> +</SessionState> <data><HostParameters type="LocalHostParameters" /><Argument type="StandaloneArgument"><Arguments IsNull="False"></Arguments><FileName>D:\Workspace\WorkBenchV2\Main\ZeroFlowTool\bin\Debug\GenesisDisplayTool.exe</FileName><WorkingDirectory>D:\Workspace\WorkBenchV2\Main\ZeroFlowTool\bin\Debug</WorkingDirectory><Scope><ProcessFilters /></Scope></Argument><Info type="PerformanceInfo"><MeasureType>Sampling</MeasureType><MeterKind>Rdtsc</MeterKind><InjectInfo><SymbolSearch><SearchPaths /></SymbolSearch><Scope><PatternFilters /><DenyAttributeFilters /></Scope></InjectInfo></Info><CoreOptions type="CoreOptions"><CoreTempPath IsNull="False"></CoreTempPath><RemoteEndPoint IsNull="False"></RemoteEndPoint><AdditionalEnvironmentVariables /></CoreOptions><HostOptions type="HostOptions"><HostTempPath IsNull="False"></HostTempPath></HostOptions></data> <data><HostParameters type="LocalHostParameters" /><Argument type="StandaloneArgument"><Arguments IsNull="False"></Arguments><FileName IsNull="False"></FileName><WorkingDirectory IsNull="False"></WorkingDirectory><Scope><ProcessFilters /></Scope></Argument><Info type="PerformanceInfo"><MeasureType>TracingInject</MeasureType><MeterKind>Rdtsc</MeterKind><InjectInfo><SymbolSearch><SearchPaths /></SymbolSearch><Scope><PatternFilters><Item /></PatternFilters><DenyAttributeFilters /></Scope></InjectInfo></Info><CoreOptions type="CoreOptions"><CoreTempPath IsNull="False"></CoreTempPath><RemoteEndPoint IsNull="False"></RemoteEndPoint><AdditionalEnvironmentVariables /></CoreOptions><HostOptions type="HostOptions"><HostTempPath IsNull="False"></HostTempPath></HostOptions></data> <data><HostParameters type="LocalHostParameters" /><Argument type="StandaloneArgument"><Arguments IsNull="False"></Arguments><FileName IsNull="False"></FileName><WorkingDirectory IsNull="False"></WorkingDirectory><Scope><ProcessFilters /></Scope></Argument><Info type="TimelineInfo" /><CoreOptions type="CoreOptions"><CoreTempPath IsNull="False"></CoreTempPath><RemoteEndPoint IsNull="False"></RemoteEndPoint><AdditionalEnvironmentVariables /></CoreOptions><HostOptions type="HostOptions"><HostTempPath IsNull="False"></HostTempPath><ReprofileDisableReason>LaunchedByReSharperUnitTestRunner</ReprofileDisableReason></HostOptions></data> diff --git a/Common/CommonCore.Configuration/ServiceUrls.cs b/Common/CommonCore.Configuration/ServiceUrls.cs index 2df71b90..82ec85ea 100644 --- a/Common/CommonCore.Configuration/ServiceUrls.cs +++ b/Common/CommonCore.Configuration/ServiceUrls.cs @@ -21,6 +21,12 @@ namespace Xylem.Common.CommonCore.Configuration private const String DefaultListAllFwPackagesServiceUrl = "http://10.49.40.25/MeterProcessState/api/FileUpToDate/GetFwFiles?FileIsForDeveloperOnly=false&FileCategoryID=1"; + private const String DefaultListAllSwPackagesServiceUrl = + "http://10.49.40.25/MeterProcessState/api/FileUpToDate/GetFwFiles?FileIsForDeveloperOnly=false&FileCategoryID=5"; + + private const String DefaultListAllConfigFilePackagesServiceUrl = + "http://10.49.40.25/MeterProcessState/api/FileUpToDate/GetFwFiles?FileIsForDeveloperOnly=false&FileCategoryID=6"; + private const String DefaultListAllFwUpdateSafesServiceUrl = "http://10.49.40.25/MeterProcessState/api/FileUpToDate/GetFwFiles?FileIsForDeveloperOnly=false&FileCategoryID=4"; @@ -259,6 +265,26 @@ namespace Xylem.Common.CommonCore.Configuration DefaultListAllFwPackagesServiceUrl; } + /// + /// Get all Cordonel FW update SW package description files. + /// + /// + public static String ListAllSwPackages() + { + return ConfigurationManager.AppSettings["ListAllSwPackagesServiceUrl"] ?? + DefaultListAllSwPackagesServiceUrl; + } + + /// + /// Get all Cordonel FW update SW package description files. + /// + /// + public static String ListAllConfigurationFilePackages() + { + return ConfigurationManager.AppSettings["ListAllConfigFilePackagesServiceUrl"] ?? + DefaultListAllConfigFilePackagesServiceUrl; + } + /// /// Set all applications versions installed to a specific Cordonel. /// diff --git a/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs b/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs index 79dba45f..747c402b 100644 --- a/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs +++ b/Common/Hardware/Interfaces/Ports/SerialPorts/BaseSerialPort.cs @@ -630,6 +630,11 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts /// /// - Doubling of sync byte in protocol behind sync byte itself implemented /// + /// + /// - Flush buffer as MOXA sometimes takes two messages and combines these two one! + /// As the Genesis needs a separated wake-up message with a following delay before the + /// real payload message, this causes a lot of trouble. + /// protected void PhysicalWrite(Byte[] txBuffer) { try @@ -649,18 +654,20 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts } } } + _serialPort.Write(txByteList.ToArray(), 0, txByteList.Count); + // flush the buffer for MOXA, to avoid two subsequent communications assembled to one communication! _serialPort.BaseStream.Flush(); OnRawRecordSendOut?.Invoke(this, new ListBytePortDataEventArgs(txByteList, DateTimeOffset.UtcNow)); - } catch (Exception ex) { _byteDataLogger.Error($"{Ident} {ex.Message}"); } } + #region Prop #endregion } diff --git a/Common/Hardware/Interfaces/Ports/SerialPorts/IrdaSerialPort.cs b/Common/Hardware/Interfaces/Ports/SerialPorts/IrdaSerialPort.cs index 5740349c..05ada442 100644 --- a/Common/Hardware/Interfaces/Ports/SerialPorts/IrdaSerialPort.cs +++ b/Common/Hardware/Interfaces/Ports/SerialPorts/IrdaSerialPort.cs @@ -24,17 +24,17 @@ namespace Xylem.Common.Hardware.Interfaces.Ports.SerialPorts /// protected override void SpecificPortWrite(Byte[] tx) { - //send wake up burst with two 0xF0 byte - //var wakeUpBurst = new Byte[] { 0xF0, 0xF0 }; - var wakeUpBurst = new Byte[] { 0x01, 0x01, 0x01, 0x01, }; - var delayPattern = new Byte[] { 0x0F, 0x0F, 0x0F, 0x0F , 0x0F, 0x0F, 0x0F, 0x0F }; + //send wake up burst + var wakeUpBurst = new Byte[] { 0x01, 0x01, 0x01, 0x01 }; PhysicalWrite(wakeUpBurst); Thread.Sleep(1); //delay at least 500 µs with 0f *8 //PhysicalWrite(delayPattern); //Thread.Sleep(1); - + //delay at least 500 µs + Thread.Sleep(1); + //send the IrDA record PhysicalWrite(tx); } diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index 9f1327f8..8f884836 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -1141,6 +1141,21 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// public String CoreRevision; + /// + /// This is the FLEXNET version which describes the entire packet. + /// + public String FwVersion; + + /// + /// This is the Metrology Lookup Table CRC. + /// + public String LutCrc; + + /// + /// This is the meter size. + /// + public String MeterSize; + /// /// Region (EMEA or NA) and Radio frequency (433 or 868 or null). /// @@ -1165,11 +1180,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// private void ReadMeterFirmwareAndAssignRegisters() { - //if (true) - //{ - - // return; - //} //avoid overwriting of list if this already exits if (MeterAppListVersion.Any()) { @@ -1196,16 +1206,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore //read version, skip retries on SYSTEM 0x04-> FW nor present is a valid feedback var readFwVersionBytes = ReadRegister(Register.System.CheckFwPresence, 4, 0x04); - //the FW version as Uint32 will be used for comparison with the configuration.json - if (readFwVersionBytes != null && readFwVersionBytes.Length > 0) - { - readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 + - (readFwVersionBytes[1] & 0x0F)) * 100; - readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 + - (readFwVersionBytes[0] & 0x0F)); - //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]); + //the FW version as Uint32 will be used for comparison with the configuration.json + if (readFwVersionBytes != null && readFwVersionBytes.Length > 0) + { + readFwVersion = (UInt32)(((readFwVersionBytes[1] & 0xF0) >> 4) * 10 + + (readFwVersionBytes[1] & 0x0F)) * 100; + readFwVersion += (UInt32)(((readFwVersionBytes[0] & 0xF0) >> 4) * 10 + + (readFwVersionBytes[0] & 0x0F)); + //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) { @@ -1220,7 +1231,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } } } - Thread.Sleep(250); } //add application always, even if this is not installed. This will be used for FW updates @@ -1240,6 +1250,15 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore MetrologyUpgradePermission = RegisterConverter.ConvertTo( ReadRegister(Register.System.MetrologyUpgradePermission)); + //read metrology lookup table CRC + var lutCrc = RegisterConverter.ConvertTo(ReadRegister(Register.Genesisflow.LookupFileCrc)); + LutCrc = $@"0x{lutCrc:X4}"; + + + //read meter size + MeterSize = MeterSizeConverter.ConvertMeterSizeEnumToSizeName((MeterSize)RegisterConverter.ConvertTo( + ReadRegister(Register.Genesisflow.MeterSize))); + //read core revision var coreRegisterRead = RegisterConverter.ConvertTo(ReadRegister(Register.System.CoreRevision, 16)); var coreRevision = coreRegisterRead?.Split('\0'); @@ -1288,10 +1307,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore } } - //read radio frequency - - _logger.Info("Region and radio frequency[Mhz]: " + RegionRadio); - //safe temporary registers from file to compare first and last version with application version read from meter and + _logger.Info($"Meter size: {MeterSize}"); //remove unused registers with invalid version var tempConfigRegisters = _configRegister.MeterRegisterDic.ToList(); //tempConfigRegisters.ToList() diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json index 9bc7b627..12d6566f 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json @@ -3,7 +3,7 @@ "id": 9, "version": { "first": 1, - "last": 153 + "last": 154 }, "registers": { "AlarmStatus0": { @@ -24,7 +24,7 @@ "description": "8 bit counts corresponding to alarms 0-3.", "version": { "first": 1, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -48,7 +48,7 @@ "description": "8 bit counts corresponding to alarms 4-7.", "version": { "first": 1, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -91,7 +91,7 @@ "description": "Any set bits manually clear the corresponding alarm.", "version": { "first": 111, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -115,7 +115,7 @@ "description": "8 bit counts corresponding to alarms 8-11.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -139,7 +139,7 @@ "description": "8 bit counts corresponding to alarms 12-15.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -163,7 +163,7 @@ "description": "8 bit counts corresponding to alarms 16-19.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -187,7 +187,7 @@ "description": "8 bit counts corresponding to alarms 20-23.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -211,7 +211,7 @@ "description": "8 bit counts corresponding to alarms 24-27.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -235,7 +235,7 @@ "description": "8 bit counts corresponding to alarms 28-31.", "version": { "first": 26, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -283,7 +283,7 @@ "description": "Bit set of those alarms which are being monitored.", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 4294967295, @@ -336,7 +336,7 @@ "description": "Bit set of those alarms which will generate events.", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 4294967295, @@ -389,7 +389,7 @@ "description": "Bit set of those alarms which are displayed with IDs and the alarm icon.", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 4294967295, @@ -437,7 +437,7 @@ "description": "Alarms that have their display automatically cleared", "version": { "first": 111, - "last": 153 + "last": 154 }, "statictype": "static" } @@ -533,7 +533,7 @@ "description": "Flow rate above which broken pipe alarm is set in 1/256 l/h", "version": { "first": 133, - "last": 153 + "last": 154 }, "values": { "default": 639999, @@ -610,7 +610,7 @@ "description": "Time threshold for leak alarm in minutes", "version": { "first": 119, - "last": 153 + "last": 154 }, "values": { "default": 360, @@ -687,7 +687,7 @@ "description": "Number of measurements in reverse flow required to set reverse flow alarm", "version": { "first": 143, - "last": 153 + "last": 154 }, "values": { "default": 15, @@ -716,7 +716,7 @@ "description": "Timezone in which this application is set to run.", "version": { "first": 24, - "last": 153 + "last": 154 }, "values": { "default": 0, @@ -745,7 +745,7 @@ "description": "A name for the arrangement of applications on the meter", "version": { "first": 130, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -792,7 +792,7 @@ "description": "The number of times the meter has rebooted", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "minimum": 0, @@ -868,7 +868,7 @@ "description": "Time threshold for broken pipe alarm in minutes", "version": { "first": 119, - "last": 153 + "last": 154 }, "values": { "default": 180, @@ -969,7 +969,7 @@ "description": "Flow rate above which leak alarm can be set in 1/256 l/h", "version": { "first": 133, - "last": 153 + "last": 154 }, "values": { "default": 6399, @@ -998,7 +998,7 @@ "description": "Charge in uAs available in manufacturing (read only)", "version": { "first": 84, - "last": 153 + "last": 154 }, "values": { "default": 181440000 @@ -1073,7 +1073,7 @@ "description": "High temperature alarm threshold in 0.1°C", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 500, @@ -1126,7 +1126,7 @@ "description": "Time threshold for high temperature alarm in seconds", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 600, @@ -1203,7 +1203,7 @@ "description": "Low temperature alarm threshold in 0.1°C", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 20, @@ -1256,7 +1256,7 @@ "description": "Time threshold for low temperature alarm in seconds", "version": { "first": 111, - "last": 153 + "last": 154 }, "values": { "default": 600, @@ -1333,7 +1333,7 @@ "description": "High pressure alarm threshold in Pa", "version": { "first": 122, - "last": 153 + "last": 154 }, "values": { "default": 1600000, @@ -1410,7 +1410,7 @@ "description": "Time threshold for high pressure alarm in seconds", "version": { "first": 119, - "last": 153 + "last": 154 }, "values": { "default": 600, @@ -1487,7 +1487,7 @@ "description": "Low pressure alarm threshold in Pa", "version": { "first": 122, - "last": 153 + "last": 154 }, "values": { "default": 30000, @@ -1564,7 +1564,7 @@ "description": "Time threshold for low pressure alarm in seconds", "version": { "first": 119, - "last": 153 + "last": 154 }, "values": { "default": 600, @@ -1612,7 +1612,7 @@ "description": "Store all configuration items in non-volatile memory.", "version": { "first": 131, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -1636,7 +1636,7 @@ "description": "Customer serial number string", "version": { "first": 139, - "last": 153 + "last": 154 }, "statictype": "static" } @@ -1660,7 +1660,7 @@ "description": "Internal backup of calendar seconds", "version": { "first": 145, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -1684,7 +1684,7 @@ "description": "Time meter was determined to have been installed. 0 means not installed", "version": { "first": 147, - "last": 153 + "last": 154 }, "statictype": "infrequentlyupdated" } @@ -1708,7 +1708,7 @@ "description": "Read to view the string used as a decimal point for this locale", "version": { "first": 151, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -1732,7 +1732,7 @@ "description": "Read to view the string used as a thousands separarator for this locale", "version": { "first": 151, - "last": 153 + "last": 154 }, "statictype": "dynamic" } @@ -2691,7 +2691,7 @@ "id": 16, "version": { "first": 100, - "last": 484 + "last": 485 }, "registers": { "TxInterval": { @@ -2712,7 +2712,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 15, @@ -2741,7 +2741,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 3600, @@ -2770,7 +2770,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 3, @@ -2799,7 +2799,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 3, @@ -2828,7 +2828,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 7, @@ -2857,7 +2857,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 433, @@ -2886,7 +2886,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -2915,7 +2915,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -2944,7 +2944,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -2973,7 +2973,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3002,7 +3002,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3031,7 +3031,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3060,7 +3060,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3089,7 +3089,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3118,7 +3118,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "static" } @@ -3142,7 +3142,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 25, @@ -3171,7 +3171,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 360, @@ -3200,7 +3200,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 2500, @@ -3229,7 +3229,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 180, @@ -3258,7 +3258,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 160, @@ -3287,7 +3287,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 3, @@ -3316,7 +3316,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 600, @@ -3345,7 +3345,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 600, @@ -3374,7 +3374,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 60, @@ -3403,7 +3403,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3432,7 +3432,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3461,7 +3461,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 50, @@ -3490,7 +3490,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 2, @@ -3519,7 +3519,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 600, @@ -3548,7 +3548,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 600, @@ -3577,7 +3577,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 60, @@ -3606,7 +3606,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -3635,7 +3635,7 @@ "description": "An enumerator defining the currently active PulseWidth (0 ... 8 for non testmode values and 9 ... 15 for testmode)", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 4, @@ -3664,7 +3664,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -3693,7 +3693,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -3722,7 +3722,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "infrequentlyupdated" } @@ -3746,7 +3746,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "infrequentlyupdated" } @@ -3770,7 +3770,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 207, @@ -3799,7 +3799,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 60, @@ -3828,7 +3828,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 29, @@ -3857,7 +3857,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3886,7 +3886,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "static" } @@ -3910,7 +3910,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "static" } @@ -3934,7 +3934,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3963,7 +3963,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -3992,7 +3992,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4021,7 +4021,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4050,7 +4050,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4079,7 +4079,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 19, @@ -4108,7 +4108,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4137,7 +4137,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -4166,7 +4166,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "statictype": "dynamic" } @@ -4190,7 +4190,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4219,7 +4219,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 201335811, @@ -4248,7 +4248,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 60, @@ -4277,7 +4277,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 5, @@ -4306,7 +4306,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 201335811, @@ -4335,7 +4335,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 1, @@ -4364,7 +4364,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4393,7 +4393,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4422,7 +4422,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 4, @@ -4451,7 +4451,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 4, @@ -4480,7 +4480,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4509,7 +4509,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4538,7 +4538,7 @@ "description": "Lorem ipsum", "version": { "first": 100, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4567,7 +4567,7 @@ "description": "Lorem ipsum", "version": { "first": 412, - "last": 484 + "last": 485 }, "values": { "default": 4320000, @@ -4596,7 +4596,7 @@ "description": "Lorem ipsum", "version": { "first": 412, - "last": 484 + "last": 485 }, "values": { "default": 1000, @@ -4625,7 +4625,7 @@ "description": "Storage item for HistoricalErrorLimitCounters Reverse(1, hi) and Leak(0, lo)", "version": { "first": 437, - "last": 484 + "last": 485 }, "values": { "default": 16711935, @@ -4654,7 +4654,7 @@ "description": "Storage item for HistoricalErrorLimitCounters Magnet(3, hi) and Air(2, lo)", "version": { "first": 437, - "last": 484 + "last": 485 }, "values": { "default": 16711935, @@ -4683,7 +4683,7 @@ "description": "Storage item for HistoricalErrorLimitCounters PressureMin(5, hi) and PressureMax(4, lo)", "version": { "first": 437, - "last": 484 + "last": 485 }, "values": { "default": 16711935, @@ -4712,7 +4712,7 @@ "description": "Storage item for HistoricalErrorLimitCounters TempMin(7, hi) and TempMax(6, lo)", "version": { "first": 437, - "last": 484 + "last": 485 }, "values": { "default": 16711935, @@ -4741,7 +4741,7 @@ "description": "Lorem ipsum", "version": { "first": 483, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4770,7 +4770,7 @@ "description": "Lorem ipsum", "version": { "first": 482, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4799,7 +4799,7 @@ "description": "Lorem ipsum", "version": { "first": 482, - "last": 484 + "last": 485 }, "values": { "default": 0, @@ -4833,7 +4833,7 @@ "id": 4, "version": { "first": 3, - "last": 223 + "last": 224 }, "registers": { "Privilege": { @@ -4854,7 +4854,7 @@ "description": "Written to set the login level, followed by the password. Note, this can be read at any login level including 0.", "version": { "first": 3, - "last": 223 + "last": 224 }, "values": { "default": 0, @@ -4883,7 +4883,7 @@ "description": "Password for logging in, requires 3 consecutive writes", "version": { "first": 3, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -4907,7 +4907,7 @@ "description": "Remote file operations, use this to open a file on the meter, handle returned", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -4931,7 +4931,7 @@ "description": "Remote file operations, use this to close a file on the meter", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -4955,7 +4955,7 @@ "description": "Remote file operations, use this to read bytes from an open file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -4979,7 +4979,7 @@ "description": "Remote file operations, use this to write bytes to an open file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5003,7 +5003,7 @@ "description": "Remote file operations, use this to seek within an open file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5027,7 +5027,7 @@ "description": "Remote file operations, use this to determine position within an open file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5051,7 +5051,7 @@ "description": "Remote file operations, use this to delete a file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5075,7 +5075,7 @@ "description": "Remote file operations, use this determine whether the current position in an open file is the end of the file", "version": { "first": 20, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5099,7 +5099,7 @@ "description": "Returns a list of files in the filesystem that matches a string containing wildcards passed in", "version": { "first": 49, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5123,7 +5123,7 @@ "description": "String containing the PCB serial number. Note, this can be read at any login level including 0", "version": { "first": 59, - "last": 223 + "last": 224 }, "statictype": "static" } @@ -5147,7 +5147,7 @@ "description": "Bitmask of login levels permitted to manipulate dangerous files", "version": { "first": 59, - "last": 223 + "last": 224 }, "statictype": "static" } @@ -5171,7 +5171,7 @@ "description": "Remote file operations, use this to flush write buffers to an open file", "version": { "first": 66, - "last": 223 + "last": 224 }, "statictype": "dynamic" } @@ -5280,7 +5280,7 @@ "id": 21, "version": { "first": 1, - "last": 55 + "last": 56 }, "registers": { "EraseRMA": { @@ -5301,7 +5301,7 @@ "description": "Writing TRUE to this register erases the RMA area", "version": { "first": 7, - "last": 55 + "last": 56 }, "statictype": "dynamic" } @@ -5325,7 +5325,7 @@ "description": "Write to this to force an update of some data. 0 - NDEF readings, 1 - NDEF details, 2 - RMA details", "version": { "first": 49, - "last": 55 + "last": 56 }, "statictype": "dynamic" } @@ -5399,7 +5399,7 @@ "id": 0, "version": { "first": 141, - "last": 510 + "last": 511 }, "registers": { "TriggerUpgrade": { @@ -5420,7 +5420,7 @@ "description": "Writing TRUE to this register internally calls SysTriggerUpgrade() then returns the result.", "version": { "first": 141, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5444,7 +5444,7 @@ "description": "Writing an application id number allows the version number of that application to be read back.", "version": { "first": 150, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5468,7 +5468,7 @@ "description": "A string reporting the PCB serial number, this string must be set using production equipment.", "version": { "first": 169, - "last": 510 + "last": 511 }, "values": { "default": "" @@ -5495,7 +5495,7 @@ "description": "A string reported relating to the customer, this string can be written only once after manufacture. If subsequent changes are needed CUSTOMERSERIALNUMBER1 must be used.", "version": { "first": 170, - "last": 510 + "last": 511 }, "values": { "default": "" @@ -5522,7 +5522,7 @@ "description": "A string reported relating to the customer, this string can be written only once after manufacture. If subsequent changes are needed CUSTOMERSERIALNUMBER2 must be used.", "version": { "first": 170, - "last": 510 + "last": 511 }, "values": { "default": "" @@ -5549,7 +5549,7 @@ "description": "A string reported relating to the customer, this string can be written only once after manufacture. If subsequent changes are needed CUSTOMERSERIALNUMBER3 must be used.", "version": { "first": 170, - "last": 510 + "last": 511 }, "values": { "default": "" @@ -5576,7 +5576,7 @@ "description": "A string reported relating to the customer, this string can be written only once after manufacture. This is the last customer serial number change slot.", "version": { "first": 170, - "last": 510 + "last": 511 }, "values": { "default": "" @@ -5603,7 +5603,7 @@ "description": "The number of seconds since reboot.", "version": { "first": 176, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5627,7 +5627,7 @@ "description": "The number of seconds since 01-Jan-2000.", "version": { "first": 176, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5651,7 +5651,7 @@ "description": "A string reporting the product version string held in the system core binary.", "version": { "first": 196, - "last": 510 + "last": 511 }, "statictype": "static" } @@ -5675,7 +5675,7 @@ "description": "Writing a drive number returns the drive capacity in bytes, or 0 if the drive is not ready, or an error if the driver is not configured to be present.", "version": { "first": 233, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5699,7 +5699,7 @@ "description": "Writing an application id number allows the exit error number of that application to be read back.", "version": { "first": 258, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5723,7 +5723,7 @@ "description": "Reports the instruction set of the hosting microprocessor in b8-15 and allocated platform number in b0-7.", "version": { "first": 265, - "last": 510 + "last": 511 }, "statictype": "static" } @@ -5747,7 +5747,7 @@ "description": "Writing an application id number allows the CRC of that application to be read back.", "version": { "first": 279, - "last": 510 + "last": 511 }, "statictype": "dynamic" } @@ -5771,7 +5771,7 @@ "description": "Bitfield of permissions releated to firmware upgrade", "version": { "first": 470, - "last": 510 + "last": 511 }, "statictype": "static" } @@ -6050,7 +6050,7 @@ "id": 18, "version": { "first": 4, - "last": 109 + "last": 110 }, "registers": { "ILoopMaxFlowRate": { @@ -6090,7 +6090,7 @@ "description": "The flow rate that gives max output on the current loop", "version": { "first": 82, - "last": 109 + "last": 110 }, "statictype": "static" } @@ -6133,7 +6133,7 @@ "description": "Writing TRUE to this register stores the values of the other registers to the non-volatile memory", "version": { "first": 82, - "last": 109 + "last": 110 }, "statictype": "dynamic" } @@ -6205,7 +6205,7 @@ "description": "Volume represented by one pulse. Units of (2^-5)ml. If this is zero pulse output will not be enabled", "version": { "first": 102, - "last": 109 + "last": 110 }, "values": { "default": 32000, @@ -6282,7 +6282,7 @@ "description": "The way pulses are output on the two available channels. This is an enum of type pulse_mode_t.", "version": { "first": 98, - "last": 109 + "last": 110 }, "values": { "default": 0, @@ -6359,7 +6359,7 @@ "description": "The length of a pulse. This is an enum of type pulse_length_t.", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 4, @@ -6412,7 +6412,7 @@ "description": "The units of flow rate to display on the LCD. An enum of type displayflowunits_t", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 4, @@ -6465,7 +6465,7 @@ "description": "Position of the decimal point on the LCD for flow rate. An enum of type displayflowpoint_t", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 2, @@ -6513,7 +6513,7 @@ "description": "The update rate for the current loop", "version": { "first": 82, - "last": 109 + "last": 110 }, "statictype": "static" } @@ -6561,7 +6561,7 @@ "description": "Units for displaying temperature on the LCD. 0 – Celcius, 1 – Fahrenheit.", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 0, @@ -6614,7 +6614,7 @@ "description": "Units for displaying pressure on the LCD. 0 – Mpa, 1 – PSI.", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 0, @@ -6691,7 +6691,7 @@ "description": "Time between pressure measurements in milliseconds", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 60000, @@ -6792,7 +6792,7 @@ "description": "Value in Pa to subtract from measured value to correct for atmospheric pressure", "version": { "first": 82, - "last": 109 + "last": 110 }, "values": { "default": 0, @@ -6845,7 +6845,7 @@ "description": "Whether there is a pressure sensor present", "version": { "first": 71, - "last": 109 + "last": 110 }, "values": { "default": 0, @@ -6874,7 +6874,7 @@ "description": "Write TRUE to trigger a pressure measurement, Read to get the latest measured value in Pa", "version": { "first": 65, - "last": 109 + "last": 110 }, "statictype": "dynamic" } @@ -6898,7 +6898,7 @@ "description": "Returns the latest flow rate. Write 0 to change scaling to internal scaling, 1 to change to display scaling", "version": { "first": 92, - "last": 109 + "last": 110 }, "statictype": "dynamic" } @@ -6922,7 +6922,7 @@ "description": "Generate some artificial pulses, used for testing", "version": { "first": 97, - "last": 109 + "last": 110 }, "values": { "minimum": 0, @@ -6950,7 +6950,7 @@ "description": "Generate some artificial pulses, used for testing", "version": { "first": 97, - "last": 109 + "last": 110 }, "values": { "minimum": 0, @@ -6978,7 +6978,7 @@ "description": "Boolean value for whether pulse output is to space the pulses evenly (TRUE) or grouped (FALSE)", "version": { "first": 98, - "last": 109 + "last": 110 }, "values": { "default": 1, @@ -7007,7 +7007,7 @@ "description": "The number of bits of fractional resolution in a pulse event", "version": { "first": 98, - "last": 109 + "last": 110 }, "values": { "minimum": 0, @@ -7035,7 +7035,7 @@ "description": "Value in Pa to add to measured value after recalibration to correct for sensor drift over time", "version": { "first": 108, - "last": 109 + "last": 110 }, "statictype": "static" } @@ -7064,7 +7064,7 @@ "id": 8, "version": { "first": 1, - "last": 17 + "last": 18 }, "registers": { "Quota": { @@ -7085,7 +7085,7 @@ "description": "A quota in bytes for the log. The Logger does not apply any policy to how the quota is allocated, this is left as a restriction to be applied on a product by product basis.", "version": { "first": 1, - "last": 17 + "last": 18 }, "values": { "default": 4096, @@ -7114,7 +7114,7 @@ "description": "The drive to write to.", "version": { "first": 1, - "last": 17 + "last": 18 }, "values": { "default": 1, @@ -7143,7 +7143,7 @@ "description": "Writing TRUE will force a log flush", "version": { "first": 7, - "last": 17 + "last": 18 }, "statictype": "dynamic" } @@ -7167,7 +7167,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 16, - "last": 17 + "last": 18 }, "statictype": "dynamic" } @@ -7402,7 +7402,7 @@ "id": 17, "version": { "first": 1, - "last": 71 + "last": 72 }, "registers": { "DataLogContents": { @@ -7423,7 +7423,7 @@ "description": "Bit Mask of the items to store in LOG memory", "version": { "first": 10, - "last": 71 + "last": 72 }, "values": { "default": 201335811, @@ -7452,7 +7452,7 @@ "description": "Storage Period of the LOG memory in minutes", "version": { "first": 10, - "last": 71 + "last": 72 }, "values": { "default": 60, @@ -7481,7 +7481,7 @@ "description": "Averiging period for the Min/Max calculation of LOG&FDR memory", "version": { "first": 10, - "last": 71 + "last": 72 }, "values": { "default": 5, @@ -7510,7 +7510,7 @@ "description": "Bit Mask of the items to store in FDR memory", "version": { "first": 10, - "last": 71 + "last": 72 }, "values": { "default": 201335811, @@ -7539,7 +7539,7 @@ "description": "The day of month the FDR storage will take place at 00:00", "version": { "first": 10, - "last": 71 + "last": 72 }, "values": { "default": 1, @@ -7568,7 +7568,7 @@ "description": "A counter used for internal purposes", "version": { "first": 15, - "last": 71 + "last": 72 }, "values": { "default": 0, @@ -7597,7 +7597,7 @@ "description": "A counter to monitor the application resets", "version": { "first": 20, - "last": 71 + "last": 72 }, "values": { "default": 0, @@ -7636,7 +7636,7 @@ "id": 1, "version": { "first": 17, - "last": 67 + "last": 68 }, "registers": { "BatteryVoltage": { @@ -7657,7 +7657,7 @@ "description": "Measured battery terminal voltage in 1mV units.", "version": { "first": 17, - "last": 67 + "last": 68 }, "statictype": "dynamic" } @@ -7681,7 +7681,7 @@ "description": "String describing the battery brand.", "version": { "first": 17, - "last": 67 + "last": 68 }, "values": { "default": "Tadiran" @@ -7708,7 +7708,7 @@ "description": "One of: 0 = battery absent; 1 = built in; 2 = other; 3 = AA; 4 = AAA; 5 = C; 6 = D; 255 = unknown", "version": { "first": 17, - "last": 67 + "last": 68 }, "values": { "default": 6, @@ -7759,7 +7759,7 @@ "description": "The number of installed batteries.", "version": { "first": 60, - "last": 67 + "last": 68 }, "values": { "default": 1, @@ -7788,7 +7788,7 @@ "description": "Datasheet terminal voltage in 100mV units as manufactured.", "version": { "first": 17, - "last": 67 + "last": 68 }, "values": { "default": 36, @@ -7817,7 +7817,7 @@ "description": "Datasheet terminal voltage in 100mV units below which the cell is considered empty.", "version": { "first": 17, - "last": 67 + "last": 68 }, "values": { "default": 28, @@ -7846,7 +7846,7 @@ "description": "Chosen manufacturer from the internal lookup table of known batteries.", "version": { "first": 20, - "last": 67 + "last": 68 }, "values": { "default": 0, @@ -7875,7 +7875,7 @@ "description": "Accumulated charge used in uAs.", "version": { "first": 24, - "last": 67 + "last": 68 }, "statictype": "dynamic" } @@ -7899,7 +7899,7 @@ "description": "Elapsed time since manufacture in seconds.", "version": { "first": 39, - "last": 67 + "last": 68 }, "statictype": "dynamic" } @@ -7923,7 +7923,7 @@ "description": "Time in seconds for which the projected end time cannot exceed.", "version": { "first": 39, - "last": 67 + "last": 68 }, "values": { "default": 473040000, @@ -7952,7 +7952,7 @@ "description": "Datasheet capacity in mAh units as manufactured.", "version": { "first": 45, - "last": 67 + "last": 68 }, "values": { "default": 19000, @@ -7981,7 +7981,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 61, - "last": 67 + "last": 68 }, "statictype": "dynamic" } @@ -8005,7 +8005,7 @@ "description": "The number of 15 minute periods of consecutive low battery voltage required for the battery to be deemed critically low", "version": { "first": 66, - "last": 67 + "last": 68 }, "values": { "default": 96, @@ -8069,7 +8069,7 @@ "id": 15, "version": { "first": 7, - "last": 302 + "last": 303 }, "registers": { "SampleRate": { @@ -8138,7 +8138,7 @@ "description": "The rate in Hz that each GP30 takes measurements", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 2, @@ -8210,7 +8210,7 @@ "description": "The rate in Hz that each GP30 takes measurements", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 2, @@ -8263,7 +8263,7 @@ "description": "The first hit level in the upstream direction for channel 1, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8335,7 +8335,7 @@ "description": "The first hit level in the upstream direction for channel 1, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8388,7 +8388,7 @@ "description": "The first hit level in the upstream direction for channel 2, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8460,7 +8460,7 @@ "description": "The first hit level in the upstream direction for channel 2, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8513,7 +8513,7 @@ "description": "The first hit level in the upstream direction for channel 3, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8585,7 +8585,7 @@ "description": "The first hit level in the upstream direction for channel 3, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8638,7 +8638,7 @@ "description": "The first hit level in the downstream direction for channel 1, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8710,7 +8710,7 @@ "description": "The first hit level in the downstream direction for channel 1, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8763,7 +8763,7 @@ "description": "The first hit level in the downstream direction for channel 2, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8835,7 +8835,7 @@ "description": "The first hit level in the downstream direction for channel 2, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8888,7 +8888,7 @@ "description": "The first hit level in the downstream direction for channel 3, units of 0.88mV", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -8960,7 +8960,7 @@ "description": "The first hit level in the downstream direction for channel 3, units of 0.88mV", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -9013,7 +9013,7 @@ "description": "The hit number to consider as the first hit", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 6, @@ -9085,7 +9085,7 @@ "description": "The hit number to consider as the first hit", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 6, @@ -9138,7 +9138,7 @@ "description": "Where to stop running the amplitude peak detection", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 19, @@ -9210,7 +9210,7 @@ "description": "Where to stop running the amplitude peak detection", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 19, @@ -9263,7 +9263,7 @@ "description": "The number of pulses to fire for a measurement", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 17, @@ -9335,7 +9335,7 @@ "description": "The number of pulses to fire for a measurement", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 17, @@ -9388,7 +9388,7 @@ "description": "The weight of the lowest display digit as a power of 10. The accepted range of values depends on the LCD present and the DisplayUnits chosen", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": -6, @@ -9460,7 +9460,7 @@ "description": "The weight of the lowest display digit as a power of 10. The accepted range of values depends on the LCD present and the DisplayUnits chosen", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": -6, @@ -9513,7 +9513,7 @@ "description": "The units of volume to display. The accepted range of values depends on the LCD present and the DisplayPow10 chosen", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -9585,7 +9585,7 @@ "description": "The units of volume to display. The accepted range of values depends on the LCD present and the DisplayPow10 chosen", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -9662,7 +9662,7 @@ "description": "The meter pipe size", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -9718,30 +9718,6 @@ "maximum": 17 }, "statictype": "static" - }, - { - "type": "enum8", - "privilege": { - "lvl1": "RO", - "lvl2": "RO", - "lvl3": "RO", - "lvl4": "RO", - "lvl5": "RO", - "lvl6": "RO", - "lvl7": "RW", - "lvl8": "RW" - }, - "description": "The meter pipe size", - "version": { - "first": 601, - "last": 302 - }, - "values": { - "default": 1, - "minimum": 0, - "maximum": 17 - }, - "statictype": "static" } ] }, @@ -9811,7 +9787,7 @@ "description": "The calibration factor for ultrasonic channel 1", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -9883,7 +9859,7 @@ "description": "The calibration factor for ultrasonic channel 1", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -9960,7 +9936,7 @@ "description": "The calibration factor for ultrasonic channel 2", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -10032,7 +10008,7 @@ "description": "The calibration factor for ultrasonic channel 2", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -10109,7 +10085,7 @@ "description": "The calibration factor for ultrasonic channel 3", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -10181,7 +10157,7 @@ "description": "The calibration factor for ultrasonic channel 3", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 15625, @@ -10258,7 +10234,7 @@ "description": "The delta time of flight expected on ultrasound channel 1 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10330,7 +10306,7 @@ "description": "The delta time of flight expected on ultrasound channel 1 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10407,7 +10383,7 @@ "description": "The delta time of flight expected on ultrasound channel 2 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10479,7 +10455,7 @@ "description": "The delta time of flight expected on ultrasound channel 2 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10556,7 +10532,7 @@ "description": "The delta time of flight expected on ultrasound channel 3 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10628,7 +10604,7 @@ "description": "The delta time of flight expected on ultrasound channel 3 at zero flow. Value is in units 4 times smaller than usual time of flight scaling (ie LS bit is 2^-40 seconds)", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10657,7 +10633,7 @@ "description": "The scaled volume value shown on the display. In the units and precision set by DisplayUnits and DisplayPow10 respectively. Decimal point is not represented in this value", "version": { "first": 47, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -10714,7 +10690,7 @@ "description": "The scaled volume value shown on the display. In the units and precision set by DisplayUnits and DisplayPow10 respectively. Decimal point is not represented in this value", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -10757,7 +10733,7 @@ "description": "Write 1 to reset all accumulated volume to zero", "version": { "first": 268, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -10814,7 +10790,7 @@ "description": "Write 1 to reset all accumulated volume to zero", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -10862,7 +10838,7 @@ "description": "The forward flow direction. 0 - undecided, 1 - right, 2 - left", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -10934,7 +10910,7 @@ "description": "The forward flow direction. 0 - undecided, 1 - right, 2 - left", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -11011,7 +10987,7 @@ "description": "The type of data output by the green LED", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -11083,7 +11059,7 @@ "description": "The type of data output by the green LED", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -11112,7 +11088,7 @@ "description": "Write 1 to store calibration values to non-volatile storage. Read back for status", "version": { "first": 54, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -11169,7 +11145,7 @@ "description": "Write 1 to store calibration values to non-volatile storage. Read back for status", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -11193,7 +11169,7 @@ "description": "The forward flow accumulator volume. The scale depends on the meter size", "version": { "first": 54, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -11250,7 +11226,7 @@ "description": "The forward flow accumulator volume. The scale depends on the meter size", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -11274,7 +11250,7 @@ "description": "The reverse flow accumulator volume. The scale depends on the meter size", "version": { "first": 54, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -11331,7 +11307,7 @@ "description": "The reverse flow accumulator volume. The scale depends on the meter size", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -11379,7 +11355,7 @@ "description": "The volume that must pass in LowFlowMaxPeriod for it to be registered as real flow. Units of ml", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 200, @@ -11451,7 +11427,7 @@ "description": "The volume that must pass in LowFlowMaxPeriod for it to be registered as real flow. Units of ml", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 200, @@ -11504,7 +11480,7 @@ "description": "The time during which LowFlowThreshold volume must pass for it to be registered as real flow. Units of seconds << 16", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 3932160, @@ -11576,7 +11552,7 @@ "description": "The time during which LowFlowThreshold volume must pass for it to be registered as real flow. Units of seconds << 16", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 3932160, @@ -11629,7 +11605,7 @@ "description": "The amount of flow in ml to accumulate before updating the main scaled accumulators.", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -11701,7 +11677,7 @@ "description": "The amount of flow in ml to accumulate before updating the main scaled accumulators.", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -11754,7 +11730,7 @@ "description": "The net volume in ml that must flow in one direction for the forward arrow to be set", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 5000000, @@ -11826,7 +11802,7 @@ "description": "The net volume in ml that must flow in one direction for the forward arrow to be set", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 5000000, @@ -11879,7 +11855,7 @@ "description": "The fire buffer within the GP30 on channel 1 to be used", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -11914,16 +11890,16 @@ }, { "type": "uint8_t", - "privilege": { - "lvl1": "RO", - "lvl2": "RO", - "lvl3": "RO", - "lvl4": "RO", - "lvl5": "RO", - "lvl6": "RO", - "lvl7": "RW", - "lvl8": "RW" - }, + "privilege": { + "lvl1": "RO", + "lvl2": "RO", + "lvl3": "RO", + "lvl4": "RO", + "lvl5": "RO", + "lvl6": "RO", + "lvl7": "RW", + "lvl8": "RW" + }, "description": "The fire buffer within the GP30 on channel 1 to be used", "version": { "first": 500, @@ -11951,7 +11927,7 @@ "description": "The fire buffer within the GP30 on channel 1 to be used", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -12004,7 +11980,7 @@ "description": "The fire buffer within the GP30 on channel 2 to be used", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -12076,7 +12052,7 @@ "description": "The fire buffer within the GP30 on channel 2 to be used", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -12129,7 +12105,7 @@ "description": "The fire buffer within the GP30 on channel 3 to be used", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -12201,7 +12177,7 @@ "description": "The fire buffer within the GP30 on channel 3 to be used", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -12249,7 +12225,7 @@ "description": "Write 1 to put GenesisFlow in Active mode. This is the normal measurement mode", "version": { "first": 268, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -12306,7 +12282,7 @@ "description": "Write 1 to put GenesisFlow in Active mode. This is the normal measurement mode", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -12330,7 +12306,7 @@ "description": "Write 0 to put GenesisFlow in Active mode, otherwise put GenesisFlow in Idle mode. Idle mode displays just the number written to TriggerIdle. No measurements are performed. Read returns the number written", "version": { "first": 75, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -12402,7 +12378,7 @@ "description": "Write 0 to put GenesisFlow in Active mode, otherwise put GenesisFlow in Idle mode. Idle mode displays just the number written to TriggerIdle. No measurements are performed. Read returns the number written", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -12455,7 +12431,7 @@ "description": "The maximum delta time of flight, above this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 309237, @@ -12527,7 +12503,7 @@ "description": "The maximum delta time of flight, above this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 309237, @@ -12580,7 +12556,7 @@ "description": "The maximum absolute time of flight, above this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 24739011, @@ -12652,7 +12628,7 @@ "description": "The maximum absolute time of flight, above this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 24739011, @@ -12705,7 +12681,7 @@ "description": "The minimum absolute time of flight, below this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 13743895, @@ -12777,7 +12753,7 @@ "description": "The minimum absolute time of flight, below this the measurement is deemed bad. In 2^-38 seconds units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 13743895, @@ -12830,7 +12806,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 1", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -12902,7 +12878,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 1", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -12955,7 +12931,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 2", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13027,7 +13003,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 2", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13080,7 +13056,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 3", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13152,7 +13128,7 @@ "description": "The percentage of the measured amplitude to use for the first hit level for channel 3", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13205,7 +13181,7 @@ "description": "A value describing how long the amplitude is averaged over for calculating the first hit level. This is the amount each amplitude value is shifted down before being added to the moving average", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 4, @@ -13277,7 +13253,7 @@ "description": "A value describing how long the amplitude is averaged over for calculating the first hit level. This is the amount each amplitude value is shifted down before being added to the moving average", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 4, @@ -13330,7 +13306,7 @@ "description": "Minimum absolute first hit level value", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13402,7 +13378,7 @@ "description": "Minimum absolute first hit level value", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 20, @@ -13455,7 +13431,7 @@ "description": "The number of ToF errors to allow before resetting the first hit levels to FirstHitMinimum", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 16, @@ -13527,7 +13503,7 @@ "description": "The number of ToF errors to allow before resetting the first hit levels to FirstHitMinimum", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 16, @@ -13580,7 +13556,7 @@ "description": "The period (in seconds) between first hit level updates", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 10, @@ -13652,7 +13628,7 @@ "description": "The period (in seconds) between first hit level updates", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 10, @@ -13705,7 +13681,7 @@ "description": "The time (in seconds) to maintain zero flow after leaving empty pipe", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 30, @@ -13777,7 +13753,7 @@ "description": "The time (in seconds) to maintain zero flow after leaving empty pipe", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 30, @@ -13830,7 +13806,7 @@ "description": "The calibration offset for the temperature measurement on channel 1. In units of 2^-38 seconds", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -13902,7 +13878,7 @@ "description": "The calibration offset for the temperature measurement on channel 1. In units of 2^-38 seconds", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -13955,7 +13931,7 @@ "description": "The calibration offset for the temperature measurement on channel 2. In units of 2^-38 seconds", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14027,7 +14003,7 @@ "description": "The calibration offset for the temperature measurement on channel 2. In units of 2^-38 seconds", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14080,7 +14056,7 @@ "description": "The calibration offset for the temperature measurement on channel 3. In units of 2^-38 seconds", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14152,7 +14128,7 @@ "description": "The calibration offset for the temperature measurement on channel 3. In units of 2^-38 seconds", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14204,7 +14180,7 @@ "description": "Write the current temperature to this register to trigger a calibration step. In units of 2^-12 degrees celcius", "version": { "first": 205, - "last": 302 + "last": 303 }, "values": { "minimum": 0, @@ -14273,7 +14249,7 @@ "description": "Write the current temperature to this register to trigger a calibration step. In units of 2^-12 degrees celcius", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "minimum": 0, @@ -14320,7 +14296,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 268, - "last": 302 + "last": 303 }, "statictype": "dynamic" }, @@ -14377,7 +14353,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 601, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -14425,7 +14401,7 @@ "description": "Write 1 to stop various display related registers being changed. Read back 1 for 'sealed' 0 for 'unsealed'", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14497,7 +14473,7 @@ "description": "Write 1 to stop various display related registers being changed. Read back 1 for 'sealed' 0 for 'unsealed'", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14550,7 +14526,7 @@ "description": "Write 1 to put GenesisFlow in Test mode. This differs from normal measurement mode in that the volume is presented to 3 extra decimal places if possible. Read back 1 for Test mode, 0 otherwise", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14622,7 +14598,7 @@ "description": "Write 1 to put GenesisFlow in Test mode. This differs from normal measurement mode in that the volume is presented to 3 extra decimal places if possible. Read back 1 for Test mode, 0 otherwise", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -14675,7 +14651,7 @@ "description": "Maximum amplitude for a valid signal in 2^-22mV units", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 2936012800, @@ -14747,7 +14723,7 @@ "description": "Maximum amplitude for a valid signal in 2^-22mV units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 2936012800, @@ -14800,7 +14776,7 @@ "description": "Minimum amplitude for a valid signal in 2^-22mV units", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 209715200, @@ -14872,7 +14848,7 @@ "description": "Minimum amplitude for a valid signal in 2^-22mV units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 209715200, @@ -14925,7 +14901,7 @@ "description": "Number of hard errors to allow before declaring a fatal error", "version": { "first": 268, - "last": 302 + "last": 303 }, "values": { "default": 4, @@ -14997,7 +14973,7 @@ "description": "Number of hard errors to allow before declaring a fatal error", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 4, @@ -15026,7 +15002,7 @@ "description": "The timeout for an ultrasonic measurement (0 - 128us, 1 - 256us, 2 - 1024us, 3 - 4096us)", "version": { "first": 273, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -15098,7 +15074,7 @@ "description": "The timeout for an ultrasonic measurement (0 - 128us, 1 - 256us, 2 - 1024us, 3 - 4096us)", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 1, @@ -15127,7 +15103,7 @@ "description": "The maximum deviation of a valid delta tof from the recent mean. In 2^-38 seconds units", "version": { "first": 280, - "last": 302 + "last": 303 }, "values": { "default": 109951, @@ -15199,7 +15175,7 @@ "description": "The maximum deviation of a valid delta tof from the recent mean. In 2^-38 seconds units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 109951, @@ -15228,7 +15204,7 @@ "description": "The maximum range of temperatures between channels before one is rejected. In units of 2^-12 degrees celcius", "version": { "first": 289, - "last": 302 + "last": 303 }, "values": { "default": 8192, @@ -15300,7 +15276,7 @@ "description": "The maximum range of temperatures between channels before one is rejected. In units of 2^-12 degrees celcius", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 8192, @@ -15329,7 +15305,7 @@ "description": "The maximum range of delta time of flight between channels before one is rejected. In 2^-38 seconds units", "version": { "first": 289, - "last": 302 + "last": 303 }, "values": { "default": 137438, @@ -15401,7 +15377,7 @@ "description": "The maximum range of delta time of flight between channels before one is rejected. In 2^-38 seconds units", "version": { "first": 601, - "last": 302 + "last": 303 }, "values": { "default": 137438, @@ -15430,7 +15406,7 @@ "description": "Read for the current loaded lookup table CRC, write to set the expected CRC.", "version": { "first": 295, - "last": 302 + "last": 303 }, "statictype": "dynamic" } @@ -15454,7 +15430,7 @@ "description": "Whether to display leading zeros on row 2. If false leading zeros will be replaced with a space", "version": { "first": 302, - "last": 302 + "last": 303 }, "values": { "default": 0, @@ -15798,7 +15774,7 @@ "id": 20, "version": { "first": 10, - "last": 202 + "last": 203 }, "registers": { "PulseReportRate": { @@ -15867,7 +15843,7 @@ "description": "The rate at which pulse reports are sent to the IrDA pulse adapter", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 0, @@ -15968,7 +15944,7 @@ "description": "The number of 15 minute periods we have to have received no valid IrDA messages to assume there is no adapter present", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 3, @@ -16066,7 +16042,7 @@ "description": "The present sequence number used in pulse reports", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "minimum": 0, @@ -16132,7 +16108,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 161, - "last": 202 + "last": 203 }, "statictype": "dynamic" } @@ -16228,7 +16204,7 @@ "description": "The number of digits to use for AMR", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 8, @@ -16305,7 +16281,7 @@ "description": "The offset of the AMR smallest digit from the right (always negative)", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 0, @@ -16382,7 +16358,7 @@ "description": "A bitfield of the optional fields being used for UI-1203", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 268, @@ -16435,7 +16411,7 @@ "description": "A timestamp of meter manufacture in seconds since 1/1/2000 00:00:00 UTC", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 0, @@ -16512,7 +16488,7 @@ "description": "Whether or not to display AMR digits on the screen", "version": { "first": 161, - "last": 202 + "last": 203 }, "values": { "default": 0, @@ -16541,7 +16517,7 @@ "description": "The serial number of the current pulse adapter", "version": { "first": 193, - "last": 202 + "last": 203 }, "statictype": "infrequentlyupdated" } @@ -16565,7 +16541,7 @@ "description": "The firmware version of the current pulse adapter", "version": { "first": 193, - "last": 202 + "last": 203 }, "statictype": "infrequentlyupdated" } @@ -16609,7 +16585,7 @@ "id": 23, "version": { "first": 41, - "last": 99 + "last": 100 }, "registers": { "StoreConfiguration": { @@ -16630,7 +16606,7 @@ "description": "Write 1 to store configuration values to non-volatile storage. Read back for status", "version": { "first": 41, - "last": 99 + "last": 100 }, "statictype": "dynamic" } @@ -16654,7 +16630,7 @@ "description": "Bitmask of enabled predefined alarms", "version": { "first": 41, - "last": 99 + "last": 100 }, "values": { "default": 561047, @@ -16788,7 +16764,7 @@ "id": 22, "version": { "first": 1, - "last": 196 + "last": 197 }, "registers": { "StoreConfiguration": { @@ -16809,7 +16785,7 @@ "description": "Store all configuration items in non-volatile memory.", "version": { "first": 147, - "last": 196 + "last": 197 }, "statictype": "dynamic" } @@ -16833,7 +16809,7 @@ "description": "Override the maximum number of entries per log (0 keeps default)", "version": { "first": 147, - "last": 196 + "last": 197 }, "statictype": "static" } @@ -16852,7 +16828,7 @@ "id": 26, "version": { "first": 1, - "last": 17 + "last": 18 }, "registers": { "UpgState": { @@ -16873,7 +16849,7 @@ "description": "Lorem Ipsum", "version": { "first": 2, - "last": 17 + "last": 18 }, "statictype": "dynamic" } @@ -16897,7 +16873,7 @@ "description": "Lorem Ipsum", "version": { "first": 2, - "last": 17 + "last": 18 }, "statictype": "dynamic" } @@ -16917,4 +16893,4 @@ } } } -} +} \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateState.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateState.cs new file mode 100644 index 00000000..7b000d42 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateState.cs @@ -0,0 +1,53 @@ +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts +{ + /// + /// Genesis meter lookup table update states + /// + public enum LutUpdateState + { + /// + /// Metrology lookup table update state Idle + /// + Idle, + /// + /// Single step failed + /// + StepFailed, + /// + /// Entire process failed + /// + UpdateFailed, + /// + /// Start initial FW update + /// + StartInitial, + /// + /// Repeat update + /// + RepeatLutUpdate, + /// + /// Upload lookup table file + /// + UploadLutFile, + /// + /// Download lookup table file + /// + DownloadLutFile, + /// + /// Compare lookup table file + /// + CompareLutFile, + /// + /// Download the CRC, the meter size and store calibration as preparation for the lookup table + /// + FinalizeLutDownload, + /// + /// Erase lookup table file + /// + EraseLutFile, + /// + /// Delimiter for list + /// + LutUpdateStateListDelimiter + } +} \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateInfo.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateInfo.cs new file mode 100644 index 00000000..c2e7fe52 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateInfo.cs @@ -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 +{ + /// + /// Concatenation of state and string + /// + public static class LutUpdateStateInfo + { + /// + /// Build state information + /// + private static readonly LutUpdateStateText[] StateInfos; + + /// + /// Ctor + /// + 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.FinalizeLutDownload; + StateInfos[8].Message = "Finalize LUT file installation"; + + StateInfos[9].State = LutUpdateState.EraseLutFile; + StateInfos[9].Message = "Erase LUT file in meter"; + } + + /// + /// Get the current information + /// + /// state to search for information text + public static String GetTextFromState(LutUpdateState state) + { + return (from stateInfo in StateInfos + where stateInfo.State == state select stateInfo.Message).FirstOrDefault(); + } + /// + /// Get the state of the text + /// + /// information text to search if state is assigned + public static LutUpdateState GetStateFromText(String text) + { + return (from stateInfo in StateInfos + where stateInfo.Message == text select stateInfo.State).FirstOrDefault(); + } + } +} diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateText.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateText.cs new file mode 100644 index 00000000..88947bf6 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/Consts/LutUpdateStateText.cs @@ -0,0 +1,19 @@ +using System; + +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile.Consts +{ + /// + /// Concatenation between lokup table update state and text + /// + public struct LutUpdateStateText + { + /// + /// The state of the firmware update + /// + public LutUpdateState State; + /// + /// The message text of the lookup table update state + /// + public String Message; + } +} diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj b/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj index 9bc084fb..4c821315 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/GenesisFile.csproj @@ -96,11 +96,16 @@ Properties\SharedAssemblyInfo.cs + + + + + @@ -119,6 +124,14 @@ + + {D0C859D9-D55E-4E85-AC50-0FF31B1CE50D} + Logic.ProductionToProductMapper + + + {91DEF0C0-AA4F-40AE-8F18-CB717FDE7E7F} + Crc16Ccitt + {4B88B0D3-E791-4774-9521-EABEACDC420E} Logging diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFile.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFile.cs index 73a14419..94802c08 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFile.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFile.cs @@ -29,9 +29,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile private Int32 _fileWriteTimeOutMs = ExtendedFileIoTimeoutMs; private readonly GenesisMeter _currentGenesis; + private Int32 _filePointer; + //TODO THW test only private const String StrNewFileReadWriteMode = "wb+"; + //wb open file for writing in binary mode, if file exists its contents will be overwritten, + //if file does not exist it will be created + private const String StrNewFileReadWriteMode = "wb"; + //Open for reading in binary mode. If the file does not exist, fopen( ) returns NULL public Int32 _filePointer; private const String StrNewFileReadWriteMode = "wb+"; private const String StrOpenFileReadOnlyMode = "rb"; + //Open for both reading and writing in binary mode. If the file does not exist, fopen( ) returns NULL private const String StrOpenFileReadWriteMode = "rb+"; private String _fileName; private Int32 _overallBytesCtr; @@ -55,7 +62,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// Wildcard for search all. /// public const Char WildcardAll = '*'; -// public const String StrWildcardAll = "*"; + // public const String StrWildcardAll = "*"; /// /// Processed bytes counter @@ -171,6 +178,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Dynamic timeout load from extended to extreme timeout on retries. /// + /// + /// - Add a NULL at the end of the file name. + /// public Boolean WriteMeterFile(String fileName, Byte[] dataBytes, Int32 fileOffset = 0) { var returnValue = false; @@ -181,8 +191,11 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs("", 0)); _overallBytesCtr = dataBytes.Length; + //add file name delimiter + fileName += StringDelimiter; //check if file is unlocked for write - if (_fileName != fileName) return false; + if (_fileName != fileName) + return false; if (fileOffset == 0 && OpenMeterFile(fileName, StrNewFileReadWriteMode) || fileOffset > 0 && OpenMeterFile(fileName, StrOpenFileReadWriteMode)) @@ -319,18 +332,20 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Event on changed process counter. /// - public Boolean ReadMeterFile(String fileName, out List readBackData, Int32? readBackCount = null, string OpenFileReadOnlyModeOver = null) + /// + /// - Add a NULL at the end of the file name. + /// + public Boolean ReadMeterFile(String fileName, out List readBackData, Int32 readBackCount) { - if (String.IsNullOrEmpty(OpenFileReadOnlyModeOver)) - { - OpenFileReadOnlyModeOver = StrOpenFileReadOnlyMode; - } //set processing counter ProcessedBytesCtr = 0; OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs("", 0)); + //add file name delimiter + fileName += StringDelimiter; + readBackData = new List(); - var returnValue = OpenMeterFile(fileName, OpenFileReadOnlyModeOver); + var returnValue = OpenMeterFile(fileName, StrOpenFileReadOnlyMode); if (returnValue) { @@ -343,29 +358,29 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile CommunicationConfig.RequestRetries = 0; _currentGenesis.TransmitProtocol.SetResponseTimeout(ExtendedFileIoTimeoutMs); - int fixedReadBackCount; + //int fixedReadBackCount; - if (readBackCount.HasValue) - { - fixedReadBackCount = readBackCount.Value; - } - else - { - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false); - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 2, false); + //if (readBackCount.HasValue) + //{ + // fixedReadBackCount = readBackCount.Value; + //} + //else + //{ + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false); + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 2, false); - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FTell", _filePointer, false); - fixedReadBackCount = RegisterConverter.ConvertTo(_currentGenesis.ReadRegister("CONFIGEXCHANGE_FTell")) + 1; + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FTell", _filePointer, false); + // fixedReadBackCount = RegisterConverter.ConvertTo(_currentGenesis.ReadRegister("CONFIGEXCHANGE_FTell")) + 1; - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false); - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); - _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", _filePointer, false); + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); + // _currentGenesis.WriteRegister("CONFIGEXCHANGE_FSeek", 0, false); - } + //} //write size to 1 _currentGenesis.WriteRegister(Register.Configexchange.FileRead, 1, false); //write counts to expected length @@ -374,10 +389,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile _currentGenesis.WriteRegister(Register.Configexchange.FileRead, _filePointer); //the preceding routine needs to wait for response, else this is always true! - while (fixedReadBackCount > 0 && returnValue) + while (readBackCount > 0 && !_stopProcess) // while (fixedReadBackCount > 0 && returnValue) { - returnValue = _stopProcess; - var remainingData = RegisterConverter.ConvertTo( _currentGenesis.ReadRegister(Register.Configexchange.FileRead)); @@ -465,7 +478,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile _currentGenesis.ReadRegister(Register.Configexchange.Catalogue)); } - if (key == lastKey) break; + if (key == lastKey) + break; // remove the "\0" var strMeterFile = readData.Split(StringDelimiter); // avoid identical files repetition @@ -485,12 +499,19 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Initial /// + /// + /// - Add a NULL at the end of the file name. + /// public Boolean CreateEmptyMeterFile(String fileName, Int32 fileSize = 0) { var returnValue = false; + //add file name delimiter + fileName += StringDelimiter; + //check if file is unlocked for write - if (_fileName != fileName) return false; + if (_fileName != fileName) + return false; if (OpenMeterFile(fileName, StrNewFileReadWriteMode)) { @@ -543,7 +564,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile _currentGenesis.TransmitProtocol.SetDefaultResponseTimeout(); CommunicationConfig.RequestRetries = CommunicationConfig.DefaultRequestRetries; - if (returnedFileOffset != fileSize) returnValue = false; + if (returnedFileOffset != fileSize) + returnValue = false; } }//file open @@ -560,9 +582,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Initial /// + /// + /// - Add a NULL at the end of the file name. + /// public Boolean VerifyMeterFile(String fileName, Byte[] dataBytes) { - if (!OpenMeterFile(fileName, StrOpenFileReadOnlyMode)) return false; + //add file name delimiter + fileName += StringDelimiter; + + if (!OpenMeterFile(fileName, StrOpenFileReadOnlyMode)) + return false; //TODO THW implement //read raw data from meter return true; @@ -582,17 +611,25 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Removed retries to speed up erasure as it returns error code 0x040B. /// + /// + /// - Add a NULL at the end of the file name. + /// public Boolean EraseMeterFile(String fileName) { + //add file name delimiter + fileName += StringDelimiter; //check if file is unlocked for erase - if (_fileName != fileName) return false; + if (_fileName != fileName) + return false; //check if logged on to meter and access level is as expected - if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) return false; + if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) + return false; //set extended timeout for file operations _currentGenesis.TransmitProtocol.SetResponseTimeout(ExtendedFileIoTimeoutMs); CommunicationConfig.RequestRetries = 0; - //write "remove-command" to meter, wait for result and read back (read back returns false because of unreadable content) + //write "remove-command" to meter, wait for result and read back + //ATTENTION: read back returns FALSE because of unreadable content _currentGenesis.WriteRegister(Register.Configexchange.FileRemove, fileName, true, true); //set timeout back to default value _currentGenesis.TransmitProtocol.SetDefaultResponseTimeout(); @@ -609,10 +646,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Initial /// + /// + /// - Add a NULL at the end of the file name. + /// public Boolean UnlockEraseWriteMeterFile(String fileName) { + //add file name delimiter + fileName += StringDelimiter; //check if logged on to meter and access level is as expected - if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) return false; + if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) + return false; //remind file name being unlocked _fileName = fileName; return true; @@ -746,7 +789,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile public Boolean OpenMeterFile(String fileName, String accessMode) { //check if logged on to meter and access level is as expected - if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) return false; + if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) + return false; Boolean returnValue; var retryCtr = 0; @@ -806,25 +850,23 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Wait after writing for response before reading! /// + /// + /// - Ignore file close write return! + /// private Boolean CloseMeterFile() { //avoid file close if file pointer assignment failed - if (_filePointer <= 0) return false; + if (_filePointer <= 0) + return false; //set extended timeout for file operations _currentGenesis.TransmitProtocol.SetResponseTimeout(ExtendedFileIoTimeoutMs); CommunicationConfig.RequestRetries = 0; + _currentGenesis.WriteRegister(Register.Configexchange.FileClose, _filePointer); - var returnValue = _currentGenesis.WriteRegister(Register.Configexchange.FileClose, - _filePointer); - - //the preceding routine needs to wait for response, else this is always true! - if (returnValue) - { - //function call returns 0 if FClose successfully executed - returnValue &= 0 == RegisterConverter.ConvertTo( - _currentGenesis.ReadRegister(Register.Configexchange.FileClose)); - } + //function call returns 0 if FClose successfully executed + var returnValue = 0 == RegisterConverter.ConvertTo( + _currentGenesis.ReadRegister(Register.Configexchange.FileClose)); //set timeout back to default value _currentGenesis.TransmitProtocol.SetDefaultResponseTimeout(); CommunicationConfig.RequestRetries = CommunicationConfig.DefaultRequestRetries; diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs index 8c6d3a09..e336bb41 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterFwUpdate.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; +using System.Threading; using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; @@ -139,6 +140,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile // Text for caller to inform about actual process being carried out private String _actualOperation; private FwUpdateState _fwUpdateState; + private FwUpdateState _fwBackupUpdateState; // Process counter for caller to monitor actual progress private Int32 _processedBytesCtr; @@ -150,6 +152,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile //the package file describes all files needed for a specific release private String _packageDescriptionFile; + // manual stop of update process + private Boolean _stopUpdateProcess; + private Int32 _actualUpdateFileCtr; + /// /// Enable partial file writes of single parts with gaps in between /// @@ -624,7 +630,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile return _actualOperation; } - private Int32 _actualUpdateFileCtr; /// /// Returns the FW Update state @@ -677,8 +682,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile _genesisMeter?.ReLogin(); } - private Boolean _stopUpdateProcess; - /// /// Stop the update process /// @@ -724,6 +727,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// /// - Exit preparation added /// + /// + /// - Introduced lock for repeated execution of state machine + /// public Boolean UpdateMeterFw() { if (!UpdatePreparation()) @@ -732,6 +738,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile } _fwUpdateState = FwUpdateState.StartInitial; + _fwBackupUpdateState = FwUpdateState.Idle; while (_fwUpdateState != FwUpdateState.Idle && !StopUpdateProcess) { FwUpdateStateMachine(); @@ -897,6 +904,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile //set state machine for automatic FW update _fwUpdateState = FwUpdateState.Idle; + _fwBackupUpdateState = FwUpdateState.Idle; _actualOperation = ""; //update file information @@ -979,7 +987,6 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile var writeBackValue = _genesisMeter.ReadRegister(item.Key); _registersAfterUpdate.Add(item.Key, writeBackValue); _genesisMeter.WriteRegister(item.Key, item.Value); - } //remove the update stop action @@ -1059,97 +1066,110 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile /// useful as on increased size and number of applications needed to install in one run, the /// file system is slowing down for write accesses. /// + /// + /// - Introduced lock for repeated execution of state machine + /// private void FwUpdateStateMachine() { - switch (_fwUpdateState) + if (_fwBackupUpdateState == _fwUpdateState) { - case FwUpdateState.Idle: - break; - - case FwUpdateState.StartInitial: - _updateProcedureRetryCtr = 0; - _fwUpdateState = FwUpdateState.BuildFileApps; - break; - - case FwUpdateState.BuildFileApps: - if (!SingleFilePartsRetryEnable && !ConsecutiveFilePartsRetryEnable) - { - _remainingFileAppsParts.Clear(); - } - - BuildFileApps(); - _fwUpdateState = FwUpdateState.DownloadFileApps; - break; - - case FwUpdateState.DownloadFileApps: - _fwUpdateState = DownloadFileApps() - ? FwUpdateState.BuildUpgradeControlFile - : FwUpdateState.StepFailed; - break; - - case FwUpdateState.BuildUpgradeControlFile: - //prepare the trigger to select all successfully downloaded applications - PrepareTrigger(); - _fwUpdateState = BuildUpgradeCtrlFile() - ? FwUpdateState.DownloadUpgradeControlFile - : FwUpdateState.StepFailed; - break; - - case FwUpdateState.DownloadUpgradeControlFile: - _fwUpdateState = DownloadUpgradeCtrlFile() - ? FwUpdateState.TriggerUpgrade - : FwUpdateState.StepFailed; - break; - - case FwUpdateState.TriggerUpgrade: - _fwUpdateState = TriggerUpgrade() ? FwUpdateState.Idle : FwUpdateState.StepFailed; - break; - - case FwUpdateState.StepFailed: - _processedBytesCtr = 0; - _overallBytesCtr = 0; - //retry entire file if some partial file writes failed - if (RetryEntireFileAfterFailedPartialRetries == _updateProcedureRetryCtr) - { - _remainingFileAppsParts.Clear(); - } - - _fwUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries - ? FwUpdateState.RepeatFwUpdate - : FwUpdateState.UpdateFailed; - break; - - case FwUpdateState.RepeatFwUpdate: - _processedBytesCtr = 0; - _overallBytesCtr = 0; - _fwUpdateState = FwUpdateState.BuildFileApps; - if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries) - { - _meterFile?.SetExtremeFileWriteTimeout(); - } - break; - - case FwUpdateState.UpdateFailed: - _processedBytesCtr = 0; - _overallBytesCtr = 0; - StopUpdateProcess = true; - _fwUpdateState = FwUpdateState.Idle; - break; - - case FwUpdateState.UploadFileApps: - break; - - case FwUpdateState.CompareFileApps: - break; - - case FwUpdateState.EraseUpdateFile: - break; - - default: - _fwUpdateState = FwUpdateState.Idle; - break; - + Thread.Sleep(1); } + else + { + // remind backup state to avoid repeated execution and side effects + _fwBackupUpdateState = _fwUpdateState; + switch (_fwUpdateState) + { + case FwUpdateState.Idle: + break; + + case FwUpdateState.StartInitial: + _updateProcedureRetryCtr = 0; + _fwUpdateState = FwUpdateState.BuildFileApps; + break; + + case FwUpdateState.BuildFileApps: + if (!SingleFilePartsRetryEnable && !ConsecutiveFilePartsRetryEnable) + { + _remainingFileAppsParts.Clear(); + } + + BuildFileApps(); + _fwUpdateState = FwUpdateState.DownloadFileApps; + break; + + case FwUpdateState.DownloadFileApps: + _fwUpdateState = DownloadFileApps() + ? FwUpdateState.BuildUpgradeControlFile + : FwUpdateState.StepFailed; + break; + + case FwUpdateState.BuildUpgradeControlFile: + //prepare the trigger to select all successfully downloaded applications + PrepareTrigger(); + _fwUpdateState = BuildUpgradeCtrlFile() + ? FwUpdateState.DownloadUpgradeControlFile + : FwUpdateState.StepFailed; + break; + + case FwUpdateState.DownloadUpgradeControlFile: + _fwUpdateState = DownloadUpgradeCtrlFile() + ? FwUpdateState.TriggerUpgrade + : FwUpdateState.StepFailed; + break; + + case FwUpdateState.TriggerUpgrade: + _fwUpdateState = TriggerUpgrade() ? FwUpdateState.Idle : FwUpdateState.StepFailed; + break; + + case FwUpdateState.StepFailed: + _processedBytesCtr = 0; + _overallBytesCtr = 0; + //retry entire file if some partial file writes failed + if (RetryEntireFileAfterFailedPartialRetries == _updateProcedureRetryCtr) + { + _remainingFileAppsParts.Clear(); + } + + _fwUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries + ? FwUpdateState.RepeatFwUpdate + : FwUpdateState.UpdateFailed; + break; + + case FwUpdateState.RepeatFwUpdate: + _processedBytesCtr = 0; + _overallBytesCtr = 0; + _fwUpdateState = FwUpdateState.BuildFileApps; + if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries) + { + _meterFile?.SetExtremeFileWriteTimeout(); + } + + break; + + case FwUpdateState.UpdateFailed: + _processedBytesCtr = 0; + _overallBytesCtr = 0; + StopUpdateProcess = true; + _fwUpdateState = FwUpdateState.Idle; + break; + + case FwUpdateState.UploadFileApps: + break; + + case FwUpdateState.CompareFileApps: + break; + + case FwUpdateState.EraseUpdateFile: + break; + + default: + _fwUpdateState = FwUpdateState.Idle; + break; + + } + }// lock repeated execution of identical state } #endregion diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutFile.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutFile.cs new file mode 100644 index 00000000..ffd74f26 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutFile.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using Logic.ProductionToProductMapper.Cordonel; + +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile +{ + /// + /// File for metrology look up table + /// + public class MeterLutFile + { + /// + /// File name of the file on PC + /// + public String LutPcFileName; + + /// + /// Ctor file applications + /// + /// + public MeterLutFile(String lutPcFileName) + { + LutPcFileName = lutPcFileName; + } + + /// + /// File ID for LUT file + /// + public String StrLutFileId; + + /// + /// Data length + /// + public UInt32 DataLength; + + /// + /// Version of LUT file + /// + public UInt16 Version; + + /// + /// Check of LUT file for verification and register write, read from file + /// + public UInt16 FileCrc; + + /// + /// Calculated during file processing for verification + /// + public UInt16 CalculatedCrc; + + /// + /// Validation of LUT file + /// + public Boolean IsValid; + + /// + /// Binary file content + /// + public List BinData = new List(); + + /// + /// Meter size + /// + public MeterSize MeterSize; + } +} diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs new file mode 100644 index 00000000..29d4496c --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterLutUpdate.cs @@ -0,0 +1,980 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using Logic.ProductionToProductMapper.Cordonel; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts; +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.Utils.Crc16Ccitt; +using Xylem.Common.Utils.ProcessExec; +using Xylem.Common.Utils.ProcessExec.EventArguments; + +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile +{ + /// + /// Meter lookup table for metrology update procedure + /// + public class MeterLutUpdate : IProcessState + { + #region Variables + + /// + /// Port scan result event for message dispatcher to caller + /// + public event EventHandler OnProcessUpdate; + + //error mask for unsuccessfully written LUT CRC + private const UInt32 LutCrcErrorMask = 0x8000000; + + //disk and name of lookup file + private const String StrLutMeterFileName = "1\\mettbl"; + + //disk and name of lookup file + private const String StrLutBackupMeterFileName = "1\\mettbl_b"; + + // identifier for Genesis lookup table + private const String StrLutFileId = "GEN_LUT\0"; + private const Int32 IndexLutFileId = 0; + private const Int32 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 Int32 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 Int32 LutFileHeaderLength = LengthLutFileId + LengthDataLength + LengthCrc + LengthVersion; + + // data size of file + private const Int32 LutFileDataLength = 730; + + // LUT file entire file size + private const Int32 SizeLutFile = LutFileHeaderLength + LutFileDataLength; + + //trigger update retries + private const Int32 RegisterWriteRetries = 0; + + //update reties for files + private const Int32 FileWriteRetries = 1; + + //retry of entire update procedure + private const Int32 UpdateProcedureRetries = 1; + + //threshold to increase the file write timing + private const Int32 IncreaseTimeoutUpdateProcedureRetries = 4; + + private Int32 _updateProcedureRetryCtr; + + private GenesisMeter _genesisMeter; + private MeterFile _meterFile; + + // Text for caller to inform about actual process being carried out + private String _actualOperation; + private LutUpdateState _lutUpdateState; + private LutUpdateState _lutBackupUpdateState; + + // Look up table file + public MeterLutFile LutFile; + + // list of names of installed meter files on drive 1 + private List _meterFilesDrive1; + + // number of operations for over all access + private const Int32 NumberOfOperations = 11; + private Int32 _operationCtr; + + + // error message for display of error reason + public String ErrorMessage; + + // manual stop of update process + private Boolean _stopUpdateProcess; + + + /// + /// Register subset needed to adjust for update performance content before update + /// + private readonly Dictionary _registersBeforeUpdate = new Dictionary(); + + /// + /// Register to restore after update + /// + private Dictionary _registersAfterUpdate = new Dictionary(); + + #endregion + + #region Events + + /// + /// Process update event + /// + /// + /// + /// + /// - Initial + /// + public virtual void ProcessUpdate_Event(Object sender, ProcessExecEventArgs e) + { + //// copy text from overall messages to actual, because this is from sub-routine + //OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(_overallOperation, + // OverallProcessCtrPercent, _actualOperation, e.OverallProcessPercent)); + } + + #endregion + + #region Information + + /// + /// Process counter in percent + /// + /// + /// - Initial + /// + public Double OverallProcessCtrPercent => 100.0 * _operationCtr / NumberOfOperations; + + /// + /// Single file process counter in percent + /// + /// + /// - Initial + /// + public Double SingleFileProcessCtrPercent => _meterFile?.ProcessCtrPercent ?? 0; + + #endregion + + #region CtorAssignment + + /// + /// Ctor + /// + /// + /// + /// - Initial + /// + public MeterLutUpdate(GenesisMeter genesisMeter) + { + if (genesisMeter == null) + return; + AssignGenesis(genesisMeter); + + if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "GENESISFLOW" && f.IsInstalled)) + { + _registersBeforeUpdate.Add(Register.Genesisflow.LedMode, new[] { (Byte)LedMode.Off }); + _registersBeforeUpdate.Add(Register.Genesisflow.SampleRate, new Byte[] { 1 }); + } + if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "METROLOGYASST" && f.IsInstalled)) + _registersBeforeUpdate.Add(Register.Mertrologyasst.PulseMode, new Byte[] { 0 }); + //deny access if NA product, because this does not have the radio app installed + if (genesisMeter.MeterAppListVersion.Any(f => f.AppName == "SENSUSRADIO" && f.IsInstalled)) + _registersBeforeUpdate.Add(Register.Sensusradio.WakeupInterval, new Byte[] { 6 }); + } + + /// + /// Assign new genesis + /// + /// + /// + /// - Initial + /// + public void AssignGenesis(GenesisMeter genesisMeter) + { + _genesisMeter = genesisMeter; + _actualOperation = ""; + _lutUpdateState = LutUpdateState.Idle; + } + + /// + /// Dispose + /// + public void Dispose() + { + if (_meterFile == null) + return; + _meterFile.OnProcessUpdate -= ProcessUpdate_Event; + _meterFile = null; + } + + #endregion + + #region ProcessInformation + + /// + /// Returns the actual file in process for update + /// + /// + /// + /// - Initial + /// + public String GetActualOperation() + { + return _actualOperation; + } + + /// + /// Returns the LUT Update state + /// + /// + /// + /// - Initial + /// + public String GetLutUpdateStateOperation() + { + // 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 + + #region Actions + + /// + /// Try to re-establish the file system, therefor logout to close all open files + /// and login again. + /// + /// + /// - Initial + /// + /// + /// - Enable auto-logon added + /// + /// + /// - Removed auto-logon + /// + public void ReestablishMeterFileSystem() + { + _genesisMeter?.Logout(); + _genesisMeter?.ReLogin(); + } + + /// + /// Stop the update process + /// + public Boolean StopUpdateProcess + { + get => _stopUpdateProcess; + set + { + _stopUpdateProcess = value; + if (_meterFile != null) + { + _meterFile.StopProcess = value; + } + + _lutUpdateState = LutUpdateState.UpdateFailed; + } + } + + /// + /// Update meter lookup table + /// + /// + /// + /// - Initial + /// + public Boolean UpdateMeterLut() + { + if (!UpdatePreparation()) + { + return false; + } + + _operationCtr = 0; + _actualOperation = ""; + ErrorMessage = ""; + _lutUpdateState = LutUpdateState.StartInitial; + _lutBackupUpdateState = LutUpdateState.Idle; + while (_lutUpdateState != LutUpdateState.Idle && !StopUpdateProcess) + { + LutUpdateStateMachine(); + } + + return ExitPreparation(true); + } + + /// + /// Upload lookup table file and compare with the loaded from file system + /// + /// + /// - Initial + /// + public Boolean VerifyLutFile() + { + if (!UpdatePreparation()) + { + return false; + } + + return ExitPreparation(true); + } + + /// + /// Reset lookup table update process and all lists and counters + /// + /// + /// - Initial + /// + public void ResetAll() + { + LutFile = null; + //remove the update stop action + StopUpdateProcess = false; + + //reset all counters + _updateProcedureRetryCtr = 0; + + //set state machine for automatic FW update + _lutUpdateState = LutUpdateState.Idle; + _lutBackupUpdateState = LutUpdateState.Idle; + _actualOperation = ""; + _operationCtr = 0; + + //logout/login/auto-login + ReestablishMeterFileSystem(); + _genesisMeter?.Logout(); + } + + /// + /// Common update preparation and check + /// + /// + /// - Initial + /// + public Boolean UpdatePreparation() + { + _actualOperation = "Update preparation"; + _lutUpdateState = LutUpdateState.Idle; + + _meterFile = new MeterFile(_genesisMeter); + if (_meterFile != null) + _meterFile.OnProcessUpdate += ProcessUpdate_Event; + _genesisMeter?.ReLogin(); + _genesisMeter?.SetProcessState(DisplayCodes.FwUpdateActive, false); + + if (_genesisMeter == null || !_genesisMeter.IsLoggedOn) + { + return false; + } + + //set default timeout for file write operation + _meterFile.SetDefaultFileWriteTimeout(); + + //switch LED off set sample rate to 1 -> 1Hz to slow down CPU load + _registersAfterUpdate = new Dictionary(); + foreach (var item in _registersBeforeUpdate) + { + var writeBackValue = _genesisMeter.ReadRegister(item.Key); + _registersAfterUpdate.Add(item.Key, writeBackValue); + _genesisMeter.WriteRegister(item.Key, item.Value); + + } + //remove the update stop action + StopUpdateProcess = false; + return true; + } + + /// + /// Common exit routine + /// + /// + /// - Initial + /// + public Boolean ExitPreparation(Boolean returnValue) + { + if (_meterFile != null) + _meterFile.OnProcessUpdate -= ProcessUpdate_Event; + _meterFile = null; + ReestablishMeterFileSystem(); + + foreach (var item in _registersAfterUpdate) + { + _genesisMeter.WriteRegister(item.Key, item.Value); + } + + _genesisMeter?.Logout(); + if (!StopUpdateProcess) + { + return returnValue; + } + + _actualOperation = ""; + return false; + } + + #endregion + + #region StateMachine + + /// + /// State machine for metrology lookup table update process + /// + /// + /// - Initial + /// + /// + /// - Introduced lock for repeated execution of state machine + /// + private void LutUpdateStateMachine() + { + if (_lutBackupUpdateState == _lutUpdateState) + { + Thread.Sleep(1); + } + else + { + // remind backup state to avoid repeated execution and side effects + _lutBackupUpdateState = _lutUpdateState; + switch (_lutUpdateState) + { + case LutUpdateState.Idle: + break; + + case LutUpdateState.StartInitial: + _updateProcedureRetryCtr = 0; + _lutUpdateState = LutUpdateState.EraseLutFile; + break; + + case LutUpdateState.EraseLutFile: + _lutUpdateState = EraseLutFiles() ? LutUpdateState.DownloadLutFile : LutUpdateState.StepFailed; + break; + + case LutUpdateState.DownloadLutFile: + _lutUpdateState = DownloadLutFiles() ? LutUpdateState.UploadLutFile : LutUpdateState.StepFailed; + break; + + case LutUpdateState.UploadLutFile: + _lutUpdateState = UploadAndCompareLutFiles() ? LutUpdateState.FinalizeLutDownload : LutUpdateState.StepFailed; + break; + + case LutUpdateState.FinalizeLutDownload: + _lutUpdateState = + FinalizeLutDownload() ? LutUpdateState.Idle : LutUpdateState.StepFailed; + break; + + case LutUpdateState.CompareLutFile: + break; + + case LutUpdateState.StepFailed: + _lutUpdateState = _updateProcedureRetryCtr++ < UpdateProcedureRetries + ? LutUpdateState.RepeatLutUpdate + : LutUpdateState.UpdateFailed; + break; + + case LutUpdateState.RepeatLutUpdate: + _lutUpdateState = LutUpdateState.DownloadLutFile; + if (_updateProcedureRetryCtr >= IncreaseTimeoutUpdateProcedureRetries) + { + _meterFile?.SetExtremeFileWriteTimeout(); + } + + break; + + case LutUpdateState.UpdateFailed: + StopUpdateProcess = true; + _lutUpdateState = LutUpdateState.Idle; + break; + + case LutUpdateState.LutUpdateStateListDelimiter: + _lutUpdateState = LutUpdateState.Idle; + break; + + default: + _lutUpdateState = LutUpdateState.Idle; + break; + } + }// lock for identical state + } + + #endregion + + #region LutFile + /// + /// Check the content of the metrology lookup table file + /// + /// + /// + /// - Initial + /// + private Boolean ValidateLutFile() + { + // check if LUT file contains data + if (LutFile?.BinData == null || LutFile.BinData.Count < SizeLutFile) + { + ErrorMessage = "File size mismatch!"; + return false; + } + + LutFile.IsValid = false; + // extract the identifier and check, if this is a LUT file + LutFile.StrLutFileId = + Encoding.UTF8.GetString(LutFile.BinData.ToArray(), IndexLutFileId, IndexDataLength); + if (LutFile.StrLutFileId != StrLutFileId) + return false; + + 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(); + entireFile.AddRange(LutFile.BinData); + var payload = new List(); + payload.AddRange(entireFile.GetRange(IndexVersion, LutFileDataLength + LengthVersion)); + var calculatedCrc = Crc16Ccitt.CalculateMsb1021(payload.ToArray()); + if (calculatedCrc != LutFile.FileCrc) + { + ErrorMessage = "CRC mismatch!"; + return false; + } + + LutFile.CalculatedCrc = calculatedCrc; + LutFile.IsValid = true; + return true; + } + + /// + /// Download the CRC, the meter size and store calibration as preparation for the lookup table + /// + /// + /// + /// - Initial + /// + private Boolean FinalizeLutDownload() + { + var returnValue = true; + + var retryCtr = 0; + if (LutFile == null || _genesisMeter == null || _meterFile == null) + return false; + // set extended timeout for trigger upgrade response delay + _genesisMeter.TransmitProtocol.SetResponseTimeout(5000); + do + { + // for repeated entry + if (!returnValue) + { + ReestablishMeterFileSystem(); + } + + _actualOperation = "Write Lut CRC to meter"; + _operationCtr++; + returnValue = _genesisMeter.WriteRegister(Register.Genesisflow.LookupFileCrc, LutFile.FileCrc); + if (!returnValue) + { + const String txt = "Meter LUT CRC could not be set!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + _operationCtr--; + continue; + } + + _operationCtr++; + _actualOperation = "Write meter size"; + returnValue = + _genesisMeter.WriteRegister(Register.Genesisflow.MeterSize, new[] { (Byte)LutFile.MeterSize }); + if (!returnValue) + { + const String txt = "Meter size could not be set!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + _operationCtr--; + continue; + } + + _operationCtr++; + _actualOperation = "Store calibration to meter"; + returnValue = _genesisMeter.WriteRegister(Register.Genesisflow.StoreCalibration, 1); + if (!returnValue) + { + const String txt = "Meter store calibration failed!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + _operationCtr--; + continue; + } + + _operationCtr++; + _actualOperation = "Read back LUT CRC from meter"; + var lutCrc = RegisterConverter.ConvertTo( + _genesisMeter.ReadRegister(Register.Genesisflow.LookupFileCrc)); + + if ((lutCrc & LutCrcErrorMask) != 0) + { + const String txt = "Meter LUT CRC could not be set!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + _operationCtr--; + returnValue = false; + continue; + } + + OnProcessUpdate?.Invoke(this, + new ProcessExecEventArgs($"Read back and validated LUT CRC 0x{lutCrc:X4}")); + + _operationCtr++; + _actualOperation = "Read back meter size from meter"; + var meterSize = (MeterSize)RegisterConverter.ConvertTo( + _genesisMeter.ReadRegister(Register.Genesisflow.MeterSize)); + + if (meterSize != LutFile.MeterSize) + { + const String txt = "Meter size could not be set!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + _operationCtr--; + returnValue = false; + continue; + } + + ErrorMessage = ""; + OnProcessUpdate?.Invoke(this, + new ProcessExecEventArgs("Read back and validated meter size " + + $"{MeterSizeConverter.ConvertMeterSizeEnumToSizeName(meterSize)}")); + + } while (!returnValue && retryCtr++ < RegisterWriteRetries && !StopUpdateProcess); + + // set timeout back to default value + _genesisMeter.TransmitProtocol.SetDefaultResponseTimeout(); + + return returnValue && !StopUpdateProcess; + } + + /// + /// Read meter files of drive 1 + /// + /// + /// + /// - Initial + /// + private Boolean ListMeterFilesDrive1() + { + // logout and re-login to clear all ongoing processes and clear the Genesis buffers + ReestablishMeterFileSystem(); + + if (_meterFilesDrive1 == null) + { + _meterFilesDrive1 = new List(); + } + _meterFilesDrive1.Clear(); + + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs("List meter files drive 1")); + if (!_meterFile.ReadMeterFileCatalog(out var meterFilesDrive1, MeterFile.StrMeterDrive1, + MeterFile.WildcardAll.ToString())) + return false; + + _meterFilesDrive1.AddRange(meterFilesDrive1); + + // inform overlay system of found files + foreach (var meterFile in _meterFilesDrive1) + { + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(meterFile)); + } + return true; + } + + /// + /// Erase file and check if done! + /// + /// + /// + /// - Initial + /// + private Boolean EraseFile(String fileDriveName) + { + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($"Erasing {fileDriveName}")); + var returnValue = _meterFile.UnlockEraseWriteMeterFile(fileDriveName); + // erase returns always TRUE, even if the erasure failed! Check with catalogue + _meterFile.EraseMeterFile(fileDriveName); + + //if (ListMeterFilesDrive1()) + //{ + // if (_meterFilesDrive1.Contains(fileDriveName)) + // { + // returnValue = false; + // var txt = $"Failed to erase {fileDriveName}!"; + // ErrorMessage = txt; + // OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + // } + // else + // { + // ErrorMessage = ""; + // OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs($"Successfully erased {fileDriveName}")); + // } + //} + //else + //{ + // returnValue = false; + // const String txt = "Meter files read error!"; + // ErrorMessage = txt; + // OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + //} + return returnValue; + } + + /// + /// Erase old LUT files from meter + /// + /// + /// - Initial + /// + public Boolean EraseLutFiles() + { + //counters for actual process information + var retryCtr = 0; + if (LutFile == null) + return false; + + //set extended timeout for trigger upgrade response delay + _genesisMeter.TransmitProtocol.SetResponseTimeout(10000); + var returnValue = true; + + //erase loop and retry if not successful + do + { + var filesToErase = new[] { StrLutMeterFileName, StrLutBackupMeterFileName }; + + // read all files which are already installed + _actualOperation = "Catalogue installed meter files drive 1"; + _operationCtr++; + + // read files on drive 1 to verify the LUT installation + if (ListMeterFilesDrive1()) + { + foreach (var fileToErase in filesToErase) + { + if (!_meterFilesDrive1.Contains(fileToErase)) + continue; + + _operationCtr++; + _actualOperation = $"Erase {fileToErase}"; + if (EraseFile(fileToErase)) + { + ErrorMessage = ""; + continue; + } + + ErrorMessage = $"LUT file {fileToErase} not erased!"; + returnValue = false; + _operationCtr--; + } + } + + if (!returnValue) + { + ReestablishMeterFileSystem(); + } + } while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess); + + //set timeout back to default value + _genesisMeter.TransmitProtocol.SetDefaultResponseTimeout(); + + return !StopUpdateProcess && returnValue; + } + + /// + /// Download the metrology lookup table files and read the catalog of drive 1 + /// + /// + /// + /// - Initial + /// + 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(1000); + var returnValue = true; + + //write LUT files and retry if not successful + do + { + var filesToDownload = new[] { StrLutMeterFileName, StrLutBackupMeterFileName }; + + foreach (var fileToDownload in filesToDownload) + { + _operationCtr++; + _actualOperation = $"Write {fileToDownload}"; + + // logout and re-login to clear all ongoing processes and clear the Genesis buffers + ReestablishMeterFileSystem(); + + _meterFile.UnlockEraseWriteMeterFile(fileToDownload); + var txt = $"{fileToDownload} successfully written"; + if (_meterFile.WriteMeterFile(fileToDownload, LutFile.BinData.ToArray())) + { + ErrorMessage = ""; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + continue; + } + + txt = $"Writing of {fileToDownload} failed!"; + ErrorMessage = txt; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + returnValue = false; + _operationCtr--; + } + + // read all files on drive 1 + _operationCtr++; + + if (ListMeterFilesDrive1()) + { + foreach (var checkInstalledFile in filesToDownload) + { + if (_meterFilesDrive1.Contains(checkInstalledFile)) + { + ErrorMessage = ""; + var txt = $"{checkInstalledFile} found in meter"; + OnProcessUpdate?.Invoke(this, new ProcessExecEventArgs(txt)); + continue; + } + + ErrorMessage = $"LUT file {StrLutMeterFileName} not installed!\n"; + returnValue = false; + } + } + else + { + returnValue = false; + } + + if (!returnValue) + { + ReestablishMeterFileSystem(); + } + } while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess); + + //set timeout back to default value + _genesisMeter.TransmitProtocol.SetDefaultResponseTimeout(); + + return !StopUpdateProcess && returnValue; + } + + /// + /// Upload the metrology lookup table files and read the catalog of drive 1 + /// + /// + /// + /// - Initial + /// + /// + /// - Take the different size of original and receive buffer, which is an integer division by 4, into account. + /// + 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(1000); + var returnValue = true; + + //write LUT files and retry if not successful + do + { + var filesToUpload = new[] { StrLutMeterFileName, StrLutBackupMeterFileName }; + + foreach (var fileToUpload in filesToUpload) + { + _operationCtr++; + _actualOperation = $"Read {fileToUpload}"; + + // logout and re-login to clear all ongoing processes and clear the Genesis buffers + ReestablishMeterFileSystem(); + + if (_meterFile.ReadMeterFile(fileToUpload, out var binData, SizeLutFile)) + { + // compare the entire buffer which also includes the header of the file, remind the original + // buffer may be smaller due to the chunk size of the communication (always dividable by 4), + // meaning the receive buffer is always and integer of this chunk size! + if (LutFile.BinData.Where((t, ctr) => t != binData[ctr]).Any()) + { + ErrorMessage = $"Meter LUT file is unequal to downloaded {fileToUpload}!"; + returnValue = false; + _operationCtr--; + } + + if (returnValue) + { + OnProcessUpdate?.Invoke(this, + new ProcessExecEventArgs($"LUT file {fileToUpload} of meter successfully compared!")); + + } + } + else + { + + ErrorMessage += $"Reading of {fileToUpload} failed!"; + returnValue = false; + _operationCtr--; + } + } + + if (!returnValue) + { + ReestablishMeterFileSystem(); + } + } while (!returnValue && retryCtr++ < FileWriteRetries && !StopUpdateProcess); + + //set timeout back to default value + _genesisMeter.TransmitProtocol.SetDefaultResponseTimeout(); + + return !StopUpdateProcess && returnValue; + } + + /// + /// Load file from memory + /// + /// to binary files + /// + /// + /// - Initial + /// + public Boolean LoadLutFile(String filePathName) + { + if (!File.Exists(filePathName)) + { + return false; + } + + LutFile = null; + LutFile = new MeterLutFile(filePathName) + { + BinData = new List(File.ReadAllBytes(filePathName)) + }; + + // validate the file + return ValidateLutFile(); + } + #endregion + } +} \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs index 85ac4fa1..2ab9cf09 100644 --- a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs +++ b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs @@ -81,7 +81,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers public static readonly String StartHit = "GENESISFLOW_StartHit"; public static readonly String NumFirePulses = "GENESISFLOW_NumFirePulses"; - + public static readonly String LookupFileCrc = "GENESISFLOW_LookupFileCrc"; }; @@ -121,6 +121,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers Configexchange.FileClose, Configexchange.FileWrite, Configexchange.FileRead, + Configexchange.Catalogue, Configexchange.GetFilePointerOffset, Configexchange.SetFilePointerOffset, Configexchange.FileRemove, @@ -135,6 +136,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers Genesisflow.TriggerIdle, Genesisflow.LedMode, Genesisflow.SampleRate, + Genesisflow.MeterSize, + Genesisflow.LookupFileCrc, + Genesisflow.StoreCalibration, Sensusradio.WakeupInterval, Sensusradio.FrequencyIndicator diff --git a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache index b81d5f66..2d9cbed7 100644 --- a/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache +++ b/Common/Hardware/WaterMeter/WaterMeterCore/WaterMeterRegisters/obj/Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -46bd00889699f5a20a4981a22f62b66368323855 +7ac73abb7afd9e6ddc0520a1568581c7ed0afd36 diff --git a/Common/Logic.PrdoctionToProductMapper/Cordonel/MeterSizeConverter.cs b/Common/Logic.PrdoctionToProductMapper/Cordonel/MeterSizeConverter.cs index 34d5d307..9c4c60e8 100644 --- a/Common/Logic.PrdoctionToProductMapper/Cordonel/MeterSizeConverter.cs +++ b/Common/Logic.PrdoctionToProductMapper/Cordonel/MeterSizeConverter.cs @@ -7,6 +7,59 @@ namespace Logic.ProductionToProductMapper.Cordonel /// public static class MeterSizeConverter { + /// + /// Convert Meter size enumeration to name . + /// + public static String ConvertMeterSizeEnumToSizeName(MeterSize meterSizeId) + { + switch (meterSizeId) + { + case MeterSize.DN40: + return "DN40"; + case MeterSize.DN50 : + return "DN50"; + case MeterSize.DN65: + return "DN65"; + case MeterSize.DN80: + return "DN80"; + case MeterSize.DN100: + return "DN100"; + case MeterSize.DN125: + return "DN125"; + case MeterSize.DN150: + return "DN150"; + case MeterSize.DN200: + return "DN200"; + case MeterSize.DN250: + return "DN250"; + case MeterSize.DN300: + return "DN300"; + + case MeterSize.US1_5: + return "US1_5"; + case MeterSize.US2: + return "US2"; + case MeterSize.US3: + return "US3"; + case MeterSize.US4: + return "US4"; + case MeterSize.US6: + return "US6"; + case MeterSize.US8: + return "US8"; + case MeterSize.US10: + return "US10"; + case MeterSize.US12: + return "US12"; + + case MeterSize.DNMAX: + return "*"; + default: + return "*"; + } + } + + /// /// Convert from order meter size of production order to name . /// diff --git a/Common/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/ProductionUiCordonel/ProductionUiCordonel.csproj index ed83e999..9e61e165 100644 --- a/Common/ProductionUiCordonel/ProductionUiCordonel.csproj +++ b/Common/ProductionUiCordonel/ProductionUiCordonel.csproj @@ -99,7 +99,7 @@ ..\Hardware\WaterMeter\Genesis\GenesisConfig\bin\Debug\NLog.dll - ..\..\packages\Sirt\SIRTCOM.dll + .\SIRTCOM.dll diff --git a/Common/ProductionUiCordonel/SIRTCOM.dll b/Common/ProductionUiCordonel/SIRTCOM.dll new file mode 100644 index 00000000..9ef0cf07 Binary files /dev/null and b/Common/ProductionUiCordonel/SIRTCOM.dll differ diff --git a/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache b/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache index 133b97f0..0028f628 100644 --- a/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache +++ b/Common/Tools/Tools.JsonToXlsHelper/obj/Debug/Tools.JsonToXlsHelper.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -0d85a5b3a7561b41163c20e5dc7713bcd0d65555 +f64d563def603c89cafafa61a3219ba97e1e344c diff --git a/Common/Ui/GenesisToolBox/FrmFwUpdate.Designer.cs b/Common/Ui/GenesisToolBox/FrmFwUpdate.Designer.cs index d2b310f7..07efe0f6 100644 --- a/Common/Ui/GenesisToolBox/FrmFwUpdate.Designer.cs +++ b/Common/Ui/GenesisToolBox/FrmFwUpdate.Designer.cs @@ -259,7 +259,7 @@ this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(116, 25); this.button1.TabIndex = 0; - this.button1.Text = "Set Trigger Active"; + this.button1.Text = "Clear Display"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // diff --git a/Common/Ui/GenesisToolBox/FrmFwUpdate.cs b/Common/Ui/GenesisToolBox/FrmFwUpdate.cs index 4b144eaa..55bc8e52 100644 --- a/Common/Ui/GenesisToolBox/FrmFwUpdate.cs +++ b/Common/Ui/GenesisToolBox/FrmFwUpdate.cs @@ -18,7 +18,6 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; -using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; using Xylem.Common.Logic.ProductionOrderCore.FW; using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Ui.GenesisToolBox.Properties; @@ -120,13 +119,12 @@ namespace Xylem.Common.Ui.GenesisToolBox "This is a stepwise update, proceed until update is completed!\n"; private const String StrUpdateErrorMessage = "FW UPDATE FAILED!\n\n"; - private FwSource fwSource = FwSource.File; + private FwSource _fwSource = FwSource.File; private enum FwSource { File, - Production, - Db, - +// Production, + Db } #endregion #region FormControls @@ -670,6 +668,9 @@ namespace Xylem.Common.Ui.GenesisToolBox return; } + lblOverall.Text = @"Establish data base connection.."; + lblOverall.Visible = true; + Update(); _currentGenesis?.DisposeMeter(); //dispose old meter _meterBatch.RemoveAllMeters(); @@ -1030,7 +1031,7 @@ namespace Xylem.Common.Ui.GenesisToolBox { _packageFileToFileAppsValidated = _meterFwUpdate.ValidateFileAppsWithPackageFile(); } - catch (Exception e) + catch (Exception) { if (_meterFwUpdate.CoreRevisionMaximum == null) MessageBoxShow(@"Core Revision missing in ADF!", @"FAILED", @@ -1174,9 +1175,10 @@ namespace Xylem.Common.Ui.GenesisToolBox private void btnOpenPackageControlFile_Click(Object sender, EventArgs e) { - ////reload last path + //reload last path dlgOpenPackageFile.InitialDirectory = DefaultPackageFile; + dlgOpenPackageFile.DefaultExt = ".txt"; if (dlgOpenPackageFile.ShowDialog() != DialogResult.OK) { return; @@ -1657,11 +1659,11 @@ namespace Xylem.Common.Ui.GenesisToolBox private void checkSelectionChanged(FwSource newMode) { - if (newMode == fwSource) + if (newMode == _fwSource) { return; } - fwSource = newMode; + _fwSource = newMode; } private void PushFwFile(MeterFwUpdate meterFwUpdate) @@ -1778,14 +1780,14 @@ namespace Xylem.Common.Ui.GenesisToolBox private void button1_Click(Object sender, EventArgs e) { - if (_currentGenesis == null || !_currentGenesis.IsLoggedOn) + if (_currentGenesis == null ) return; + if (!_currentGenesis.IsLoggedOn) { - return; - } - else - { - _currentGenesis.SetLcdText(true, new Byte[] { 0x00, 0x00, 0x00, 0x00 }); + _currentGenesis.Login(); } + + _currentGenesis.SetLcdText(true, new Byte[] { 0x00, 0x00, 0x00, 0x00 }); + _currentGenesis.Logout(); } private void btnFixBat_Click(Object sender, EventArgs e) diff --git a/Common/Ui/GenesisToolBox/FrmHistory.Designer.cs b/Common/Ui/GenesisToolBox/FrmHistory.Designer.cs new file mode 100644 index 00000000..d3cbae97 --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmHistory.Designer.cs @@ -0,0 +1,105 @@ +namespace Xylem.Common.Ui.GenesisToolBox +{ + partial class FrmHistory + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.rtbHistory = new System.Windows.Forms.RichTextBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // rtbHistory + // + this.rtbHistory.Dock = System.Windows.Forms.DockStyle.Fill; + this.rtbHistory.Location = new System.Drawing.Point(3, 53); + this.rtbHistory.Name = "rtbHistory"; + this.rtbHistory.Size = new System.Drawing.Size(378, 673); + this.rtbHistory.TabIndex = 31; + this.rtbHistory.Text = ""; + this.rtbHistory.TextChanged += new System.EventHandler(this.rtbHistory_TextChanged); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Controls.Add(this.rtbHistory, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 111F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(384, 729); + this.tableLayoutPanel1.TabIndex = 38; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 1; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 44F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(378, 44); + this.tableLayoutPanel2.TabIndex = 36; + // + // FrmHistory + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.ClientSize = new System.Drawing.Size(384, 729); + this.ControlBox = false; + this.Controls.Add(this.tableLayoutPanel1); + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(400, 768); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(400, 768); + this.Name = "FrmHistory"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; + this.Text = "FW-Update Process History"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmHistory_FormClosing); + this.tableLayoutPanel1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + public System.Windows.Forms.RichTextBox rtbHistory; + } +} \ No newline at end of file diff --git a/Common/Ui/GenesisToolBox/FrmHistory.cs b/Common/Ui/GenesisToolBox/FrmHistory.cs new file mode 100644 index 00000000..f4b16c22 --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmHistory.cs @@ -0,0 +1,37 @@ +using System; +using System.Windows.Forms; + +namespace Xylem.Common.Ui.GenesisToolBox +{ + /// + /// History display of update process + /// + [Serializable] + public partial class FrmHistory : Form + { + /// + /// Ctor + /// + public FrmHistory() + { + InitializeComponent(); + } + + private void FrmHistory_FormClosing(Object sender, FormClosingEventArgs e) + { + //avoid destroying of object + e.Cancel = true; + //instead just hide it + Hide(); + } + + /// + /// Select always the last line for the display. + /// + private void rtbHistory_TextChanged(Object sender, EventArgs e) + { + //rtbHistory.SelectionStart = rtbHistory.Text.Length; + //rtbHistory.ScrollToCaret(); + } + } +} diff --git a/Common/Ui/GenesisToolBox/FrmHistory.resx b/Common/Ui/GenesisToolBox/FrmHistory.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmHistory.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Common/Ui/GenesisToolBox/FrmLutUpdate.Designer.cs b/Common/Ui/GenesisToolBox/FrmLutUpdate.Designer.cs new file mode 100644 index 00000000..2b3172c8 --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmLutUpdate.Designer.cs @@ -0,0 +1,522 @@ +namespace Xylem.Common.Ui.GenesisToolBox +{ + partial class FrmLutUpdate + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.grpSetup = new System.Windows.Forms.GroupBox(); + this.tbxRegionRadio = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.tbxPcbId = new System.Windows.Forms.TextBox(); + this.tbxMeterFw = new System.Windows.Forms.TextBox(); + this.tbxMeterMeterSize = new System.Windows.Forms.TextBox(); + this.tbxMeterLutCrc = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.lblFwVersion = new System.Windows.Forms.Label(); + this.btnConnect = new System.Windows.Forms.Button(); + this.lblConnectPcb = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.cbComSlot = new System.Windows.Forms.ComboBox(); + this.lblWaitingForMeterResponse = new System.Windows.Forms.Label(); + this.btnStopFwUpdate = new System.Windows.Forms.Button(); + this.btnDownloadLutFile = new System.Windows.Forms.Button(); + this.lblOverall = new System.Windows.Forms.Label(); + this.barSingleProgressUpdate = new System.Windows.Forms.ProgressBar(); + this.lblActualProcess = new System.Windows.Forms.Label(); + this.barOverallProgressUpdate = new System.Windows.Forms.ProgressBar(); + this.tmrProgressUpdate = new System.Windows.Forms.Timer(this.components); + this.dlgOpenLuFile = new System.Windows.Forms.OpenFileDialog(); + this.lblFwUpdateInfo = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.tbxFileMeterSize = new System.Windows.Forms.TextBox(); + this.tbxFileCrc = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.lblLutFileLoadedInfo = new System.Windows.Forms.Label(); + this.tbxLutFilePathName = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.btnOpenLutFile = new System.Windows.Forms.Button(); + this.label9 = new System.Windows.Forms.Label(); + this.lblUpdateTime = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.grpSetup.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // grpSetup + // + this.grpSetup.Controls.Add(this.tbxRegionRadio); + this.grpSetup.Controls.Add(this.label8); + this.grpSetup.Controls.Add(this.tbxPcbId); + this.grpSetup.Controls.Add(this.tbxMeterFw); + this.grpSetup.Controls.Add(this.tbxMeterMeterSize); + this.grpSetup.Controls.Add(this.tbxMeterLutCrc); + this.grpSetup.Controls.Add(this.label5); + this.grpSetup.Controls.Add(this.label6); + this.grpSetup.Controls.Add(this.lblFwVersion); + this.grpSetup.Controls.Add(this.btnConnect); + this.grpSetup.Controls.Add(this.lblConnectPcb); + this.grpSetup.Controls.Add(this.label2); + this.grpSetup.Controls.Add(this.cbComSlot); + this.grpSetup.Location = new System.Drawing.Point(12, 56); + this.grpSetup.Name = "grpSetup"; + this.grpSetup.Size = new System.Drawing.Size(248, 212); + this.grpSetup.TabIndex = 24; + this.grpSetup.TabStop = false; + this.grpSetup.Text = "Cordonel"; + // + // tbxRegionRadio + // + this.tbxRegionRadio.Location = new System.Drawing.Point(124, 178); + this.tbxRegionRadio.Name = "tbxRegionRadio"; + this.tbxRegionRadio.ReadOnly = true; + this.tbxRegionRadio.Size = new System.Drawing.Size(68, 20); + this.tbxRegionRadio.TabIndex = 34; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(10, 182); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(105, 13); + this.label8.TabIndex = 33; + this.label8.Text = "Region/Radio[MHz]:"; + // + // tbxPcbId + // + this.tbxPcbId.Location = new System.Drawing.Point(124, 59); + this.tbxPcbId.Name = "tbxPcbId"; + this.tbxPcbId.ReadOnly = true; + this.tbxPcbId.Size = new System.Drawing.Size(68, 20); + this.tbxPcbId.TabIndex = 32; + // + // tbxMeterFw + // + this.tbxMeterFw.Location = new System.Drawing.Point(124, 88); + this.tbxMeterFw.Name = "tbxMeterFw"; + this.tbxMeterFw.ReadOnly = true; + this.tbxMeterFw.Size = new System.Drawing.Size(68, 20); + this.tbxMeterFw.TabIndex = 31; + // + // tbxMeterMeterSize + // + this.tbxMeterMeterSize.Location = new System.Drawing.Point(124, 148); + this.tbxMeterMeterSize.Name = "tbxMeterMeterSize"; + this.tbxMeterMeterSize.ReadOnly = true; + this.tbxMeterMeterSize.Size = new System.Drawing.Size(68, 20); + this.tbxMeterMeterSize.TabIndex = 30; + // + // tbxMeterLutCrc + // + this.tbxMeterLutCrc.Location = new System.Drawing.Point(124, 118); + this.tbxMeterLutCrc.Name = "tbxMeterLutCrc"; + this.tbxMeterLutCrc.ReadOnly = true; + this.tbxMeterLutCrc.Size = new System.Drawing.Size(68, 20); + this.tbxMeterLutCrc.TabIndex = 29; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(10, 152); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(60, 13); + this.label5.TabIndex = 28; + this.label5.Text = "Meter Size:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(10, 122); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(86, 13); + this.label6.TabIndex = 27; + this.label6.Text = "Meter LUT CRC:"; + // + // lblFwVersion + // + this.lblFwVersion.AutoSize = true; + this.lblFwVersion.Location = new System.Drawing.Point(10, 92); + this.lblFwVersion.Name = "lblFwVersion"; + this.lblFwVersion.Size = new System.Drawing.Size(57, 13); + this.lblFwVersion.TabIndex = 25; + this.lblFwVersion.Text = "Meter FW:"; + // + // btnConnect + // + this.btnConnect.Location = new System.Drawing.Point(123, 24); + this.btnConnect.Name = "btnConnect"; + this.btnConnect.Size = new System.Drawing.Size(116, 25); + this.btnConnect.TabIndex = 24; + this.btnConnect.Text = "Connect"; + this.btnConnect.UseVisualStyleBackColor = true; + this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click); + // + // lblConnectPcb + // + this.lblConnectPcb.AutoSize = true; + this.lblConnectPcb.Location = new System.Drawing.Point(10, 62); + this.lblConnectPcb.Name = "lblConnectPcb"; + this.lblConnectPcb.Size = new System.Drawing.Size(33, 13); + this.lblConnectPcb.TabIndex = 23; + this.lblConnectPcb.Text = "NOT "; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(10, 30); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(28, 13); + this.label2.TabIndex = 20; + this.label2.Text = "Slot:"; + // + // cbComSlot + // + this.cbComSlot.FormattingEnabled = true; + this.cbComSlot.Items.AddRange(new object[] { + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20"}); + this.cbComSlot.Location = new System.Drawing.Point(44, 27); + this.cbComSlot.Name = "cbComSlot"; + this.cbComSlot.Size = new System.Drawing.Size(37, 21); + this.cbComSlot.TabIndex = 5; + this.cbComSlot.Text = "1"; + this.cbComSlot.SelectedIndexChanged += new System.EventHandler(this.cbComSlot_SelectedIndexChanged); + // + // lblWaitingForMeterResponse + // + this.lblWaitingForMeterResponse.AutoSize = true; + this.lblWaitingForMeterResponse.ForeColor = System.Drawing.Color.Red; + this.lblWaitingForMeterResponse.Location = new System.Drawing.Point(532, 280); + this.lblWaitingForMeterResponse.Name = "lblWaitingForMeterResponse"; + this.lblWaitingForMeterResponse.Size = new System.Drawing.Size(182, 13); + this.lblWaitingForMeterResponse.TabIndex = 18; + this.lblWaitingForMeterResponse.Text = "WAITING FOR METER RESPONSE"; + // + // btnStopFwUpdate + // + this.btnStopFwUpdate.Location = new System.Drawing.Point(310, 181); + this.btnStopFwUpdate.Name = "btnStopFwUpdate"; + this.btnStopFwUpdate.Size = new System.Drawing.Size(116, 25); + this.btnStopFwUpdate.TabIndex = 8; + this.btnStopFwUpdate.Text = "STOP"; + this.btnStopFwUpdate.UseVisualStyleBackColor = true; + this.btnStopFwUpdate.Click += new System.EventHandler(this.btnStopFwUpdate_Click); + // + // btnDownloadLutFile + // + this.btnDownloadLutFile.Location = new System.Drawing.Point(310, 147); + this.btnDownloadLutFile.Name = "btnDownloadLutFile"; + this.btnDownloadLutFile.Size = new System.Drawing.Size(116, 25); + this.btnDownloadLutFile.TabIndex = 0; + this.btnDownloadLutFile.Text = "Download"; + this.btnDownloadLutFile.UseVisualStyleBackColor = true; + this.btnDownloadLutFile.Click += new System.EventHandler(this.btnDownloadLutFile_Click); + // + // lblOverall + // + this.lblOverall.AutoSize = true; + this.lblOverall.Location = new System.Drawing.Point(21, 317); + this.lblOverall.Name = "lblOverall"; + this.lblOverall.Size = new System.Drawing.Size(80, 13); + this.lblOverall.TabIndex = 7; + this.lblOverall.Text = "Overall process"; + // + // barSingleProgressUpdate + // + this.barSingleProgressUpdate.Location = new System.Drawing.Point(12, 296); + this.barSingleProgressUpdate.Name = "barSingleProgressUpdate"; + this.barSingleProgressUpdate.Size = new System.Drawing.Size(702, 18); + this.barSingleProgressUpdate.TabIndex = 6; + this.barSingleProgressUpdate.Visible = false; + // + // lblActualProcess + // + this.lblActualProcess.AutoSize = true; + this.lblActualProcess.Location = new System.Drawing.Point(21, 280); + this.lblActualProcess.Name = "lblActualProcess"; + this.lblActualProcess.Size = new System.Drawing.Size(76, 13); + this.lblActualProcess.TabIndex = 4; + this.lblActualProcess.Text = "Process status"; + // + // barOverallProgressUpdate + // + this.barOverallProgressUpdate.Location = new System.Drawing.Point(12, 333); + this.barOverallProgressUpdate.Name = "barOverallProgressUpdate"; + this.barOverallProgressUpdate.Size = new System.Drawing.Size(702, 18); + this.barOverallProgressUpdate.TabIndex = 3; + this.barOverallProgressUpdate.Visible = false; + // + // tmrProgressUpdate + // + this.tmrProgressUpdate.Interval = 200; + this.tmrProgressUpdate.Tick += new System.EventHandler(this.tmrProgressUpdate_Tick); + // + // dlgOpenLuFile + // + this.dlgOpenLuFile.Filter = "metrology lookup tables (*.lut)|*.lut"; + // + // lblFwUpdateInfo + // + this.lblFwUpdateInfo.AutoSize = true; + this.lblFwUpdateInfo.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lblFwUpdateInfo.Location = new System.Drawing.Point(18, 32); + this.lblFwUpdateInfo.Name = "lblFwUpdateInfo"; + this.lblFwUpdateInfo.Size = new System.Drawing.Size(72, 13); + this.lblFwUpdateInfo.TabIndex = 27; + this.lblFwUpdateInfo.Text = "Version: 0.0.0"; + // + // pictureBox1 + // + this.pictureBox1.Image = global::Xylem.Common.Ui.GenesisToolBox.Properties.Resources.SensusLogoXylem; + this.pictureBox1.Location = new System.Drawing.Point(611, 3); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(102, 54); + this.pictureBox1.TabIndex = 29; + this.pictureBox1.TabStop = false; + // + // openFileDialog1 + // + this.openFileDialog1.FileName = "openFileDialog1"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.tbxFileMeterSize); + this.groupBox1.Controls.Add(this.tbxFileCrc); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.lblLutFileLoadedInfo); + this.groupBox1.Controls.Add(this.btnDownloadLutFile); + this.groupBox1.Controls.Add(this.tbxLutFilePathName); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.btnStopFwUpdate); + this.groupBox1.Controls.Add(this.btnOpenLutFile); + this.groupBox1.Location = new System.Drawing.Point(278, 56); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(436, 212); + this.groupBox1.TabIndex = 28; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Lookup Table File"; + // + // tbxFileMeterSize + // + this.tbxFileMeterSize.Location = new System.Drawing.Point(104, 148); + this.tbxFileMeterSize.Name = "tbxFileMeterSize"; + this.tbxFileMeterSize.ReadOnly = true; + this.tbxFileMeterSize.Size = new System.Drawing.Size(68, 20); + this.tbxFileMeterSize.TabIndex = 13; + // + // tbxFileCrc + // + this.tbxFileCrc.Location = new System.Drawing.Point(104, 118); + this.tbxFileCrc.Name = "tbxFileCrc"; + this.tbxFileCrc.ReadOnly = true; + this.tbxFileCrc.Size = new System.Drawing.Size(68, 20); + this.tbxFileCrc.TabIndex = 12; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(10, 152); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(79, 13); + this.label3.TabIndex = 11; + this.label3.Text = "File Meter Size:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(10, 122); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(75, 13); + this.label1.TabIndex = 10; + this.label1.Text = "File LUT CRC:"; + // + // lblLutFileLoadedInfo + // + this.lblLutFileLoadedInfo.AutoSize = true; + this.lblLutFileLoadedInfo.Location = new System.Drawing.Point(10, 60); + this.lblLutFileLoadedInfo.Name = "lblLutFileLoadedInfo"; + this.lblLutFileLoadedInfo.Size = new System.Drawing.Size(97, 13); + this.lblLutFileLoadedInfo.TabIndex = 9; + this.lblLutFileLoadedInfo.Text = "LUT file not loaded"; + // + // tbxLutFilePathName + // + this.tbxLutFilePathName.Location = new System.Drawing.Point(104, 27); + this.tbxLutFilePathName.Name = "tbxLutFilePathName"; + this.tbxLutFilePathName.ReadOnly = true; + this.tbxLutFilePathName.Size = new System.Drawing.Size(322, 20); + this.tbxLutFilePathName.TabIndex = 2; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(10, 30); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(63, 13); + this.label4.TabIndex = 1; + this.label4.Text = "Path Name:"; + // + // btnOpenLutFile + // + this.btnOpenLutFile.Location = new System.Drawing.Point(310, 112); + this.btnOpenLutFile.Name = "btnOpenLutFile"; + this.btnOpenLutFile.Size = new System.Drawing.Size(116, 26); + this.btnOpenLutFile.TabIndex = 0; + this.btnOpenLutFile.Text = "Open"; + this.btnOpenLutFile.UseVisualStyleBackColor = true; + this.btnOpenLutFile.Click += new System.EventHandler(this.btnOpenLutFile_Click); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(250, 280); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(101, 13); + this.label9.TabIndex = 30; + this.label9.Text = "UpdateTime [min:s]:"; + // + // lblUpdateTime + // + this.lblUpdateTime.AutoSize = true; + this.lblUpdateTime.Location = new System.Drawing.Point(357, 280); + this.lblUpdateTime.Name = "lblUpdateTime"; + this.lblUpdateTime.Size = new System.Drawing.Size(28, 13); + this.lblUpdateTime.TabIndex = 31; + this.lblUpdateTime.Text = "0:00"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label7.Location = new System.Drawing.Point(16, 9); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(159, 16); + this.label7.TabIndex = 32; + this.label7.Text = "Cordonel LUT Update"; + // + // FrmLutUpdate + // + this.AccessibleRole = System.Windows.Forms.AccessibleRole.Sound; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(723, 366); + this.Controls.Add(this.label7); + this.Controls.Add(this.lblUpdateTime); + this.Controls.Add(this.label9); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.lblWaitingForMeterResponse); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.lblOverall); + this.Controls.Add(this.lblFwUpdateInfo); + this.Controls.Add(this.barSingleProgressUpdate); + this.Controls.Add(this.lblActualProcess); + this.Controls.Add(this.grpSetup); + this.Controls.Add(this.barOverallProgressUpdate); + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(739, 405); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(739, 405); + this.Name = "FrmLutUpdate"; + this.Text = "Metrology Lookup Table Update"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmLutUpdate_FormClosing); + this.Load += new System.EventHandler(this.FrmLutUpdate_Load); + this.grpSetup.ResumeLayout(false); + this.grpSetup.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.GroupBox grpSetup; + private System.Windows.Forms.Button btnConnect; + private System.Windows.Forms.Label lblConnectPcb; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox cbComSlot; + private System.Windows.Forms.Button btnDownloadLutFile; + private System.Windows.Forms.ProgressBar barOverallProgressUpdate; + private System.Windows.Forms.Timer tmrProgressUpdate; + private System.Windows.Forms.Label lblActualProcess; + private System.Windows.Forms.Label lblOverall; + private System.Windows.Forms.ProgressBar barSingleProgressUpdate; + private System.Windows.Forms.OpenFileDialog dlgOpenLuFile; + private System.Windows.Forms.Label lblFwUpdateInfo; + private System.Windows.Forms.Button btnStopFwUpdate; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private System.Windows.Forms.Label lblWaitingForMeterResponse; + private System.Windows.Forms.Label lblFwVersion; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox tbxLutFilePathName; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button btnOpenLutFile; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label lblUpdateTime; + private System.Windows.Forms.Label lblLutFileLoadedInfo; + private System.Windows.Forms.TextBox tbxFileMeterSize; + private System.Windows.Forms.TextBox tbxFileCrc; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox tbxMeterMeterSize; + private System.Windows.Forms.TextBox tbxMeterLutCrc; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox tbxMeterFw; + private System.Windows.Forms.TextBox tbxPcbId; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox tbxRegionRadio; + private System.Windows.Forms.Label label8; + } +} \ No newline at end of file diff --git a/Common/Ui/GenesisToolBox/FrmLutUpdate.cs b/Common/Ui/GenesisToolBox/FrmLutUpdate.cs new file mode 100644 index 00000000..221779e2 --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmLutUpdate.cs @@ -0,0 +1,687 @@ +using System; +using System.Drawing; +using System.Globalization; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Logic.ProductionToProductMapper.Cordonel; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; +using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; +using Xylem.Common.Utils.ProcessExec.EventArguments; + + +namespace Xylem.Common.Ui.GenesisToolBox +{ + /// + /// FW update form + /// + public partial class FrmLutUpdate : Form + { + #region Variables + private readonly MeterBatch _meterBatch = new MeterBatch(); + private GenesisMeter _currentGenesis; + private const String StrConnecting = "Connecting to PCB"; + private const String StrNotConnected = "NOT CONNECTED"; + private const String StrPartPcbConnected = "PCB ID: "; + private const String StrOverallProcess = "Overall Process"; + + private MeterLutUpdate _meterLutUpdate; + + private String _lastFwUpdateState; + private Int32 _lastSingleProgress; + private DateTimeOffset _startTime; + private Boolean _resetTimeMeasurement; + private readonly Boolean _updateGui = true; + private Boolean _lutFileValid; + + private Boolean _tryConnectPcb; + private Boolean _lutFileSuccessfulWritten; + private const String StrUpdateErrorMessage = "METROLOGY LOOKUP TABLE UPDATE FAILED!"; + private const String StrUpdateSuccessMessage = "Metrology lookup table successfulley written!"; + private const String StrLutFileInvalid = "LUT FILE INVALID"; + private const String StrLutFileValid = "LUT file loaded"; + + // external update remarks form + private readonly FrmHistory _frmHistory = new FrmHistory(); + + private readonly Version _version; + + // status information + private static readonly Color ColorDefault = Color.Black; + private static readonly Color ColorSuccess = Color.Green; + private static readonly Color ColorProcessFailed = Color.Red; + //private static readonly Color ColorOngoingProcess = Color.Blue; + //private static readonly Color ColorUnknownStatus = Color.Gray; + //private const String SuccessSign = @"✔"; + //private const String FailedSign = @"✘"; + + private const String StrSeparator = "-----------------------------------------------------" + + "-----------------------------------------------------"; + #endregion + + #region FormControls + /// + /// Ctor FW update + /// + public FrmLutUpdate() + { + InitializeComponent(); + var cultureInfo = new CultureInfo("en-GB"); + Thread.CurrentThread.CurrentUICulture = cultureInfo; + Thread.CurrentThread.CurrentCulture = cultureInfo; + _version = Assembly.GetExecutingAssembly().GetName().Version; + } + + /// + /// Clear data table and set genesis to not connected + /// + private void Init() + { + ProcessViewControl(false); + lblConnectPcb.Text = StrNotConnected; + lblConnectPcb.ForeColor = Color.Red; + lblWaitingForMeterResponse.Visible = false; + btnConnect.Enabled = true; + btnDownloadLutFile.ForeColor = Color.DarkGreen; + btnStopFwUpdate.ForeColor = Color.Red; + SetControlDownloadsLocked(); + btnStopFwUpdate.Enabled = false; + btnOpenLutFile.Enabled = true; + tbxPcbId.Visible = false; + } + + private void FrmLutUpdate_Load(Object sender, EventArgs e) + { + var version = Assembly.GetExecutingAssembly().GetName().Version; + lblFwUpdateInfo.Text = $@"Version: {version.Major}.{version.Minor}.{version.Build}"; + _resetTimeMeasurement = true; + Init(); + } + + private void FrmLutUpdate_FormClosing(Object sender, FormClosingEventArgs e) + { + _frmHistory?.Close(); + _currentGenesis?.Logout(); + _meterBatch?.RemoveAllMeters(); + _meterBatch?.Dispose(); + if (_meterLutUpdate != null) + { + _meterLutUpdate.OnProcessUpdate -= ProcessUpdate_Event; + _meterLutUpdate.Dispose(); + _meterLutUpdate = null; + } + + Dispose(); + } + + private void cbComSlot_SelectedIndexChanged(Object sender, EventArgs e) + { + _resetTimeMeasurement = true; + Init(); + } + #endregion + #region ActivationControls + + private void SetControlDownloadsLocked() + { + btnDownloadLutFile.Enabled = false; + btnStopFwUpdate.Enabled = false; + btnConnect.Enabled = true; + } + + private void SetControlsDownloadIsOngoing() + { + btnConnect.Enabled = false; + btnOpenLutFile.Enabled = false; + + btnDownloadLutFile.Enabled = false; + btnStopFwUpdate.Enabled = true; + } + + private void SetControlsDownloadIsFinished() + { + _currentGenesis.RequestProtocol.AdditionalRetryTimeoutMs = 0; + btnConnect.Enabled = true; + btnOpenLutFile.Enabled = true; + + btnDownloadLutFile.Enabled = true; + btnStopFwUpdate.Enabled = false; + } + private void SetControlsDownloadEnabled() + { + btnConnect.Enabled = true; + btnOpenLutFile.Enabled = true; + + btnDownloadLutFile.Enabled = true; + btnStopFwUpdate.Enabled = false; + } + #endregion + + #region BoardControls + private void Connect() + { + try + { + Init(); + Int32 slotNr; + + if (string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) || + !int.TryParse(cbComSlot.SelectedItem.ToString(), out slotNr)) + { + return; + } + + lblOverall.Text = @"Establish data base connection.."; + lblOverall.Visible = true; + Update(); + _currentGenesis?.DisposeMeter(); + //dispose old meter + _meterBatch.RemoveAllMeters(); + _currentGenesis = null; + Thread.Sleep(200); + + //assign new meter and assign meter to FW update file if this exists + _currentGenesis = new GenesisMeter(); + + _currentGenesis.SetupFromConfigFile(slotNr); + _meterBatch.AddMeter(_currentGenesis); + + _currentGenesis._configuration.UseRegisterWatchService = false; + _currentGenesis._configuration.UseMinMaxCheck = false; + + var xPosition = Location.X + Size.Width; + var yPosition = Location.Y; + if (_frmHistory != null) + { + _frmHistory.SetDesktopLocation(xPosition, yPosition); + _frmHistory.Show(); + } + + ClearHistoryWindow(); + LogText(StrSeparator); + LogText($"GenesisToolBox: {_version.Major}.{_version.Minor}.{_version.Build}"); + LogText($"Date: {DateTime.Now.ToShortDateString()}"); + LogText(StrSeparator); + Task.Factory.StartNew(() => + { + ViewProgressPcb(true); + + _meterBatch.MetersLogin(); + + if (!_currentGenesis.IsLoggedOn) + { + Thread.Sleep(2000); + _meterBatch.MetersLogin(); + } + + if (!_currentGenesis.IsLoggedOn) + { + return; + } + + _meterLutUpdate?.AssignGenesis(_currentGenesis); + + Invoke(new Action(() => + { + lblConnectPcb.Text = StrPartPcbConnected; + tbxPcbId.Text = _currentGenesis.PcbId; + tbxPcbId.Visible = true; + tbxMeterFw.Text = _currentGenesis.FwVersion; + tbxMeterMeterSize.Text = _currentGenesis.MeterSize; + tbxMeterLutCrc.Text = _currentGenesis.LutCrc; + tbxRegionRadio.Text = _currentGenesis.RegionRadio; + LogText("Meter FW Version: " + _currentGenesis.FwVersion); + LogText("Meter LUT CRC: " + _currentGenesis.LutCrc); + LogText("Meter Size: " + _currentGenesis.MeterSize); + LogText("Meter Region/Radio[MHz]: " + _currentGenesis.RegionRadio); + lblConnectPcb.ForeColor = Color.Green; + CheckUpdateEnabled(); + _currentGenesis.Logout(); + LogInstalledMeterFw(); + })); + }).ContinueWith(delegate + { + ViewProgressPcb(false); + }); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + LogErrorText(ex.Message); + } + } + #endregion + + #region ProcessControls + private void ViewProgressPcb(Boolean isActive) + { + if (_updateGui) + { + if (isActive) + { + Invoke(new Action(() => + { + _tryConnectPcb = true; + ProcessViewControl(true); + lblActualProcess.Text = StrConnecting; + lblOverall.Text = StrOverallProcess; + })); + } + else + { + Invoke(new Action(() => + { + _tryConnectPcb = false; + ProcessViewControl(false); + })); + } + } + } + + /// + /// View all process bars and labels + /// + private void ProcessViewControl(Boolean view) + { + if (view) + { + lblActualProcess.Visible = true; + lblOverall.Visible = true; + barOverallProgressUpdate.Visible = true; + barSingleProgressUpdate.Visible = true; + _lastFwUpdateState = ""; + tmrProgressUpdate.Enabled = true; + } + else + { + lblActualProcess.Visible = false; + lblOverall.Visible = false; + barOverallProgressUpdate.Visible = false; + barSingleProgressUpdate.Visible = false; + tmrProgressUpdate.Enabled = false; + _lastFwUpdateState = ""; + lblWaitingForMeterResponse.Visible = false; + lblActualProcess.Text = ""; + lblOverall.Text = ""; + } + + //common actions and settings + lblActualProcess.Update(); + lblOverall.Update(); + barOverallProgressUpdate.Value = 0; + barOverallProgressUpdate.Update(); + barSingleProgressUpdate.Value = 0; + barSingleProgressUpdate.Update(); + Update(); + } + + private void StartStopDownload(Boolean isActive) + { + if (isActive) + { + Invoke(new Action(() => + { + _lastFwUpdateState = ""; + ProcessViewControl(true); + tmrProgressUpdate.Enabled = true; + })); + } + else + { + Invoke(new Action(() => + { + ProcessViewControl(false); + SetControlsDownloadIsFinished(); + + if (!_lutFileSuccessfulWritten) + { + lblLutFileLoadedInfo.ForeColor = Color.Red; + lblLutFileLoadedInfo.Text = StrUpdateErrorMessage; + var txt = StrUpdateErrorMessage; + if (!string.IsNullOrEmpty(_meterLutUpdate?.ErrorMessage)) + { + txt += "\n"; + txt += _meterLutUpdate?.ErrorMessage; + } + + LogErrorText(txt); + MessageBoxShow(txt, @"FAILED", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else + { + // on successfully execution the meter size and LUT CRC is identical to file content + tbxMeterMeterSize.Text = tbxFileMeterSize.Text; + tbxMeterLutCrc.Text = tbxFileCrc.Text; + LogSuccessText(StrUpdateSuccessMessage); + MessageBoxShow(StrUpdateSuccessMessage, @"SUCCESS", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + })); + } + } + + /// + /// Display installed meter FW. + /// + /// + /// - Init. + /// + private void LogInstalledMeterFw() + { + if (_currentGenesis == null) + return; + LogText(StrSeparator); + LogText($"PCB ID: {_currentGenesis.PcbId}"); + LogText($"Core Version: {_currentGenesis.CoreRevision}"); + LogText(""); + LogText("Installed Applications:"); + + foreach (var app in _currentGenesis.MeterAppListVersion) + { + var versionString = app.IsInstalled ? $"V: {app.StrVersion} - CRC: 0x{app.Crc:X4}" : + "App NOT Installed"; + LogText($"AppId: 0x{app.AppId:X2} - {versionString} - " + $"AppName: {app.AppName}"); + + if (app.IsInstalled) + { + var appVersion = new CordonelAppVersion(app.AppId, app.StrVersion); + + // Copy metrology update permission + if (app.AppName == MeterFwUpdateCapability.MetrologyName && + _currentGenesis.MetrologyUpgradePermission != MeterFwUpdateCapability.MetrologyUpgradePermitted) + { + appVersion.IsUpdateable = false; + } + } + } + LogText(StrSeparator); + } + + /// + /// Clear history window. + /// + /// + /// - Initial + /// + private void ClearHistoryWindow() + { + if (_frmHistory != null && _frmHistory.rtbHistory.InvokeRequired) + { + _frmHistory.rtbHistory.Invoke(new Action(() => { _frmHistory.rtbHistory.Clear(); })); + } + else + _frmHistory?.rtbHistory.Clear(); + + } + + /// + /// Output exclusively to user update remarks text window. + /// + /// + /// - Color added. + /// + private void LogText(String txtHistory) + { + InfoWindowColoredText(txtHistory, ColorDefault); + } + + /// + /// Output exclusively to user update remarks text window. + /// + private void LogErrorText(String txtHistory) + { + InfoWindowColoredText(txtHistory, ColorProcessFailed); + } + + /// + /// Output exclusively to user update remarks text window. + /// + private void LogSuccessText(String txtHistory) + { + InfoWindowColoredText(txtHistory, ColorSuccess); + } + + /// + /// Output exclusively to user update remarks text window. + /// + private void InfoWindowColoredText(String txtHistory, Color color) + { + if (_frmHistory?.rtbHistory == null) + return; + Invoke(new Action(() => + { + _frmHistory.rtbHistory.SuspendLayout(); + _frmHistory.rtbHistory.SelectionStart = _frmHistory.rtbHistory.Text.Length; + _frmHistory.rtbHistory.SelectionLength = 0; + _frmHistory.rtbHistory.SelectionColor = color; + _frmHistory.rtbHistory.AppendText($"{txtHistory}{Environment.NewLine}"); + _frmHistory.rtbHistory.SelectionColor = _frmHistory.rtbHistory.ForeColor; + _frmHistory.rtbHistory.ScrollToCaret(); + _frmHistory.rtbHistory.ResumeLayout(); + })); + } + #endregion + + #region Checks + private void CheckUpdateEnabled() + { + //this check has been placed here to force display update + if (_meterLutUpdate != null && _currentGenesis != null && _lutFileValid) + { + SetControlsDownloadEnabled(); + return; + } + SetControlDownloadsLocked(); + } + #endregion + + #region Events + + /// + /// Process update event for displaying messages in historxy window + /// + /// + /// + /// + /// - Initial + /// + public virtual void ProcessUpdate_Event(Object sender, ProcessExecEventArgs e) + { + LogText(e.OverallProcessMessage); + } + + #endregion + + #region TimerControls + private void tmrProgressUpdate_Tick(Object sender, EventArgs e) + { + //cbxManualControl.Visible = true; + if (_tryConnectPcb) + { + barOverallProgressUpdate.Value = barOverallProgressUpdate.Value + 1 > 100 ? 0 : + barOverallProgressUpdate.Value + 1; + barSingleProgressUpdate.Value = barSingleProgressUpdate.Value + 4 > 100 ? 0 : + barSingleProgressUpdate.Value + 4; + lblOverall.Text = StrOverallProcess; + } + else + { + lblOverall.Text = _meterLutUpdate?.GetLutUpdateStateOperation(); + lblActualProcess.Text = _meterLutUpdate?.GetActualOperation(); + + var overallProgress = (Int32)(_meterLutUpdate?.OverallProcessCtrPercent ?? 0); + if (overallProgress < 0) + overallProgress = 0; + barOverallProgressUpdate.Value = overallProgress > 100 ? 100 : overallProgress; + barOverallProgressUpdate.Update(); + + var singleProgress = (Int32)(_meterLutUpdate?.SingleFileProcessCtrPercent ?? 0); + if (_meterLutUpdate?.GetActualOperation() != _lastFwUpdateState) + { + _lastFwUpdateState = _meterLutUpdate?.GetActualOperation(); + lblWaitingForMeterResponse.Visible = false; + } + else + { + //if the communication gets frozen + lblWaitingForMeterResponse.Visible = _lastSingleProgress == singleProgress; + } + + barSingleProgressUpdate.Value = singleProgress > 100 ? 100 : singleProgress; + _lastSingleProgress = singleProgress; + barSingleProgressUpdate.Update(); + } + SetTimeDisplay(); + Update(); + } + + private void SetTimeDisplay() + { + var time = DateTimeOffset.UtcNow; + var timeSpan = time - _startTime; + lblUpdateTime.Text = $@"{(UInt32)timeSpan.TotalMinutes}:{timeSpan.Seconds:00}"; + } + #endregion + #region Buttons + private void btnConnect_Click(Object sender, EventArgs e) + { + if (_resetTimeMeasurement) + { + _startTime = DateTimeOffset.UtcNow; + _resetTimeMeasurement = false; + } + Connect(); + + } + + private void btnOpenLutFile_Click(Object sender, EventArgs e) + { + if (dlgOpenLuFile.ShowDialog() != DialogResult.OK) + { + return; + } + + var lutFilePathName = dlgOpenLuFile.FileName; + + lblLutFileLoadedInfo.Text = ""; + tbxLutFilePathName.Text = lutFilePathName; + if (_meterLutUpdate == null) + { + _meterLutUpdate = new MeterLutUpdate(_currentGenesis); + _meterLutUpdate.OnProcessUpdate += ProcessUpdate_Event; + } + + if (_meterLutUpdate == null) + { + return; + } + + if (_meterLutUpdate.LoadLutFile(lutFilePathName)) + { + lblLutFileLoadedInfo.ForeColor = Color.Green; + lblLutFileLoadedInfo.Text = StrLutFileValid; + tbxFileCrc.Text = $@"0x{_meterLutUpdate.LutFile.FileCrc:X4}"; + tbxFileMeterSize.Text = MeterSizeConverter.ConvertMeterSizeEnumToSizeName(_meterLutUpdate.LutFile.MeterSize); + _lutFileValid = true; + + LogText("File Meter Size: " + tbxFileMeterSize.Text); + LogText("File LUT CRC: " + tbxFileCrc.Text); + LogText(StrSeparator); + + } + else + { + var txt = ""; + if (!string.IsNullOrEmpty(_meterLutUpdate?.ErrorMessage)) + { + txt += _meterLutUpdate?.ErrorMessage; + } + else + { + txt = StrLutFileInvalid; + } + + LogErrorText(txt); + lblLutFileLoadedInfo.ForeColor = Color.Red; + lblLutFileLoadedInfo.Text = txt; + tbxFileCrc.Text = @" --- "; + tbxFileMeterSize.Text = @" --- "; + _lutFileValid = false; + } + + CheckUpdateEnabled(); + _resetTimeMeasurement = true; + } + + + /// + /// Download LUT file + /// + /// + /// + private void btnDownloadLutFile_Click(Object sender, EventArgs e) + { + if (_currentGenesis == null || _meterLutUpdate?.LutFile == null) + { + return; + } + + lblLutFileLoadedInfo.Text = ""; + SetControlsDownloadIsOngoing(); + StartStopDownload(true); + + _startTime = DateTimeOffset.UtcNow; + _resetTimeMeasurement = false; + + + Task.Factory.StartNew(() => + { + _lutFileSuccessfulWritten = _meterLutUpdate.UpdateMeterLut(); + Thread.Sleep(1000); + }).ContinueWith(delegate + { + StartStopDownload(false); + }); + } + + private void btnStopFwUpdate_Click(Object sender, EventArgs e) + { + if (_meterLutUpdate != null) + { + _meterLutUpdate.StopUpdateProcess = true; + } + } + + #endregion + #region ExternalCalls + + public MsgEventArgs LastMsgEvent; + public class MsgEventArgs : EventArgs + { + public String Text; + public String Caption; + public MessageBoxButtons Buttons; + public MessageBoxIcon Icon; + } + public event EventHandler OnMsgPopUp; + private void MessageBoxShow(String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon) + { + if (_updateGui) + { + MessageBox.Show(text, caption, buttons, icon); + } + else + { + LastMsgEvent = new MsgEventArgs() { Text = text, Caption = caption, Buttons = buttons, Icon = icon }; + OnMsgPopUp?.Invoke(this, LastMsgEvent); + } + + } + + #endregion + } +} + diff --git a/Common/Ui/GenesisToolBox/FrmLutUpdate.resx b/Common/Ui/GenesisToolBox/FrmLutUpdate.resx new file mode 100644 index 00000000..9543967f --- /dev/null +++ b/Common/Ui/GenesisToolBox/FrmLutUpdate.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 274, 17 + + + 144, 17 + + + 432, 17 + + \ No newline at end of file diff --git a/Common/Ui/GenesisToolBox/GenesisToolBox.csproj b/Common/Ui/GenesisToolBox/GenesisToolBox.csproj index 6615757a..28ec922e 100644 --- a/Common/Ui/GenesisToolBox/GenesisToolBox.csproj +++ b/Common/Ui/GenesisToolBox/GenesisToolBox.csproj @@ -238,6 +238,18 @@ FrmFrozenMeter.cs + + Form + + + FrmHistory.cs + + + Form + + + FrmLutUpdate.cs + Form @@ -401,6 +413,13 @@ FrmFrozenMeter.cs + + FrmHistory.cs + + + FrmLutUpdate.cs + Designer + FrmFwUpdate.cs Designer @@ -488,7 +507,7 @@ - Always + PreserveNewest @@ -616,6 +635,10 @@ {4b88b0d3-e791-4774-9521-eabeacdc420e} Logging + + {2FD60CF1-45CD-4060-B8E5-4F39FBA7F1CB} + ProcessExec + {60765bf4-6165-4f2f-8756-1c699826265d} LegacyGenCtl diff --git a/Common/Ui/GenesisToolBox/frmMainForm.Designer.cs b/Common/Ui/GenesisToolBox/frmMainForm.Designer.cs index 79e7d84d..b6196a50 100644 --- a/Common/Ui/GenesisToolBox/frmMainForm.Designer.cs +++ b/Common/Ui/GenesisToolBox/frmMainForm.Designer.cs @@ -29,6 +29,7 @@ private void InitializeComponent() { this.gpGerneral = new System.Windows.Forms.GroupBox(); + this.btnLutUpdate = new System.Windows.Forms.Button(); this.button1 = new System.Windows.Forms.Button(); this.btnPressure = new System.Windows.Forms.Button(); this.btnConfiguration = new System.Windows.Forms.Button(); @@ -58,6 +59,7 @@ // // gpGerneral // + this.gpGerneral.Controls.Add(this.btnLutUpdate); this.gpGerneral.Controls.Add(this.button1); this.gpGerneral.Controls.Add(this.btnPressure); this.gpGerneral.Controls.Add(this.btnConfiguration); @@ -71,14 +73,24 @@ this.gpGerneral.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.gpGerneral.Location = new System.Drawing.Point(13, 12); this.gpGerneral.Name = "gpGerneral"; - this.gpGerneral.Size = new System.Drawing.Size(181, 449); + this.gpGerneral.Size = new System.Drawing.Size(181, 503); this.gpGerneral.TabIndex = 19; this.gpGerneral.TabStop = false; this.gpGerneral.Text = "General"; // + // btnLutUpdate + // + this.btnLutUpdate.Location = new System.Drawing.Point(7, 279); + this.btnLutUpdate.Name = "btnLutUpdate"; + this.btnLutUpdate.Size = new System.Drawing.Size(151, 39); + this.btnLutUpdate.TabIndex = 17; + this.btnLutUpdate.Text = "Metrology LUT"; + this.btnLutUpdate.UseVisualStyleBackColor = true; + this.btnLutUpdate.Click += new System.EventHandler(this.btnLutUpdate_Click); + // // button1 // - this.button1.Location = new System.Drawing.Point(5, 411); + this.button1.Location = new System.Drawing.Point(4, 455); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(152, 40); this.button1.TabIndex = 16; @@ -98,7 +110,7 @@ // // btnConfiguration // - this.btnConfiguration.Location = new System.Drawing.Point(6, 321); + this.btnConfiguration.Location = new System.Drawing.Point(5, 365); this.btnConfiguration.Name = "btnConfiguration"; this.btnConfiguration.Size = new System.Drawing.Size(152, 40); this.btnConfiguration.TabIndex = 14; @@ -109,7 +121,7 @@ // btnCalender // this.btnCalender.Enabled = false; - this.btnCalender.Location = new System.Drawing.Point(6, 278); + this.btnCalender.Location = new System.Drawing.Point(5, 322); this.btnCalender.Name = "btnCalender"; this.btnCalender.Size = new System.Drawing.Size(151, 39); this.btnCalender.TabIndex = 13; @@ -169,7 +181,7 @@ // // btnSetup // - this.btnSetup.Location = new System.Drawing.Point(5, 15); + this.btnSetup.Location = new System.Drawing.Point(6, 15); this.btnSetup.Name = "btnSetup"; this.btnSetup.Size = new System.Drawing.Size(152, 40); this.btnSetup.TabIndex = 1; @@ -316,14 +328,14 @@ // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(390, 457); + this.ClientSize = new System.Drawing.Size(390, 517); this.Controls.Add(this.gbDeveloper); this.Controls.Add(this.gpLAA); this.Controls.Add(this.gpGerneral); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; this.MaximizeBox = false; - this.MaximumSize = new System.Drawing.Size(410, 500); - this.MinimumSize = new System.Drawing.Size(410, 500); + this.MaximumSize = new System.Drawing.Size(410, 560); + this.MinimumSize = new System.Drawing.Size(410, 560); this.Name = "FrmMainForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Genesis ToolBox"; @@ -358,6 +370,7 @@ private System.Windows.Forms.Button btnLegacyTestApp; private System.Windows.Forms.Button btnPressure; private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button btnLutUpdate; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button3; } diff --git a/Common/Ui/GenesisToolBox/frmMainForm.cs b/Common/Ui/GenesisToolBox/frmMainForm.cs index 2238317b..83b3880a 100644 --- a/Common/Ui/GenesisToolBox/frmMainForm.cs +++ b/Common/Ui/GenesisToolBox/frmMainForm.cs @@ -362,55 +362,12 @@ namespace Xylem.Common.Ui.GenesisToolBox Hide(); } - private void button3_Click(object sender, EventArgs e) + private void btnLutUpdate_Click(object sender, EventArgs e) { - var mb = new MeterBatch(); - for (int i = 1; i <= 10; i++) - { - try - { - var a = new GenesisMeter(); - mb.AddMeter(a); - a.SetupFromConfigFile(i); - a.Login(); - } - catch (Exception) - { - } - - } - - var taskList = new List(); - foreach (var item in mb.ListOfMeters) - { - - if (item is GenesisMeter gm) - { - var completTasks = new Task(() => - { - for (int i = 0; i < 50; i++) - { - gm.WriteRegister(Register.Genesisflow.LedMode, 0, false); - gm.WriteRegister(Register.Genesisflow.LedMode, 6, false); - gm.ReadRegister(Register.Genesisflow.LedMode); - gm.WriteRegister(Register.Genesisflow.LedMode, 0, false); - gm.WriteRegister(Register.Genesisflow.LedMode, 6, true, true); - gm.ReadRegister(Register.Genesisflow.LedMode); - gm.ReadRegister(Register.Genesisflow.CalFactor1); - gm.ReadRegister(Register.Genesisflow.CalFactor2); - gm.ReadRegister(Register.Genesisflow.AmplitudePeakDetectEnd); - } - - }); - - completTasks.Start(); - - } - } - - + var form = new FrmLutUpdate(); + form.Show(); + form.Closed += Form_Closed; + Hide(); } - - } } diff --git a/Common/Utils/DateTimeServerShared/DateTimeServer.cs b/Common/Utils/DateTimeServerShared/DateTimeServer.cs index e485ef3b..c7d9d888 100644 --- a/Common/Utils/DateTimeServerShared/DateTimeServer.cs +++ b/Common/Utils/DateTimeServerShared/DateTimeServer.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Threading; namespace Xylem.Common.Utils.DateTimeServer { diff --git a/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioning-250222-1232.pdf b/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioning-250222-1232.pdf new file mode 100644 index 00000000..5f4ecc0d Binary files /dev/null and b/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioning-250222-1232.pdf differ diff --git a/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioninginManufacturing-250222-1228.pdf b/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioninginManufacturing-250222-1228.pdf new file mode 100644 index 00000000..ca1b1f15 Binary files /dev/null and b/Docu/Hardware/Genesis/CORDFW-MetrologyTableProvisioninginManufacturing-250222-1228.pdf differ diff --git a/Docu/Hardware/Genesis/Metrology+Table+Provisioning.docm b/Docu/Hardware/Genesis/Metrology+Table+Provisioning.docm new file mode 100644 index 00000000..3d77f898 Binary files /dev/null and b/Docu/Hardware/Genesis/Metrology+Table+Provisioning.docm differ diff --git a/ServiceFwUpdate/Common/FwUpdateConfig/Consts/FwUpdateConfig.cs b/ServiceFwUpdate/Common/FwUpdateConfig/Consts/FwUpdateConfig.cs index d5f2e79d..bf071da6 100644 --- a/ServiceFwUpdate/Common/FwUpdateConfig/Consts/FwUpdateConfig.cs +++ b/ServiceFwUpdate/Common/FwUpdateConfig/Consts/FwUpdateConfig.cs @@ -14,6 +14,16 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateConfig.Consts /// public const UInt32 ValidDays = 21; + /// + /// Search strings for "Firmware up to date!" messages in report file, copied from Resources.resx of all + /// language packages from "ServiceFwUpdateSw" + /// + public static readonly String[] FirmwareUpToDateSearchStrings = new String[] + { + "Firmware is up to date!", + "Firmware ist aktuell!" + }; + /// /// Name of the file which contains the meter file names that can be erased before the FW-Update /// to free disk space and have to be restored after the FW-Update @@ -80,11 +90,27 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateConfig.Consts /// public const String FwUpdateFileExtension = ".safe"; + /// + /// Library-subfolder: For releases the files are sorted to subfolders to avoid confusion of the user. + /// + public const String LibrarySubFolderName = "Library"; + + /// + /// Library-subfolder: For releases the files are sorted to subfolders to avoid confusion of the user. + /// + public const String ConfigSubFolderName = "Config"; + /// /// Separator in file name between PcbId CustomerName and OrderNumber for the FW-Update Safe and all report /// files. /// public const Char FwUpdateFileFieldSeparator = '_'; + /// + /// Separator in file name between OrderNumber and position for the FW-Update Safe and all report + /// files. + /// + public const Char FwUpdateFileOrderPosSeparator = '-'; + } } diff --git a/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateDb.cs b/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateDb.cs index a588176b..85915707 100644 --- a/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateDb.cs +++ b/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateDb.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; using System.Text; @@ -37,6 +36,16 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// public List DbAllUpdateOperators { get; private set; } + /// + /// Cordonel SW package. + /// + public List DbFwUpdateSwPackage { get; private set; } + + /// + /// Cordonel configuration files. + /// + public List DbFwUpdateConfigFiles { get; private set; } + /// /// Cordonel FW packages. /// @@ -316,14 +325,14 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// public Boolean GetAllBuilderOperatorsFromDb() { - + if (DbAllBuilderOperators == null) DbAllBuilderOperators = new List(); DbAllBuilderOperators.Clear(); try { var url = ServiceUrls.ListAllFwUpdateBuilderOperatorsServiceUrl(); - var requestResponse = LocalWebRequest.GetRequest(url, 1200); + var requestResponse = LocalWebRequest.GetRequest(url, 5000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -374,6 +383,126 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } } + /// + /// Load the latest FW update SW package from DB. + /// + /// true if successful + /// + /// - Initial. + /// + public Boolean DownloadFwUpdateSwContainerFromDb() + { + try + { + var url = ServiceUrls.ListAllSwPackages(); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); + if (string.IsNullOrEmpty(requestResponse)) + { + DbIsConnected = false; + return false; + } + + DbIsConnected = true; + + // get a list of all stored FW update SW packages + var dbCordonelSwPackages = JsonConvert.DeserializeObject>(requestResponse); + if (dbCordonelSwPackages == null || dbCordonelSwPackages.Count == 0) + { + return false; + } + + // get latest version + var fileId = dbCordonelSwPackages.Select(package => package.FileId).Prepend(0).Max(); + if (fileId == 0) + { + return false; + } + + if (DbFwUpdateSwPackage == null) DbFwUpdateSwPackage = new List(); + DbFwUpdateSwPackage.Clear(); + + // download content + url = ServiceUrls.DownloadFileParts(); + url += $"{fileId}&readContent=true"; + requestResponse = LocalWebRequest.GetRequest(url, 15000); + if (string.IsNullOrEmpty(requestResponse)) + { + DbIsConnected = false; + return false; + } + + DbIsConnected = true; + DbFwUpdateSwPackage = JsonConvert.DeserializeObject>(requestResponse); + return DbFwUpdateSwPackage != null && DbFwUpdateSwPackage.Count > 0; + + } + catch (Exception) + { + DbIsConnected = false; + return false; + } + } + + /// + /// Load the latest FW update configuration files from DB. + /// + /// true if successful + /// + /// - Initial. + /// + public Boolean DownloadFwUpdateConfigurationFilesFromDb() + { + try + { + var url = ServiceUrls.ListAllConfigurationFilePackages(); + var requestResponse = LocalWebRequest.GetRequest(url, 5000); + if (string.IsNullOrEmpty(requestResponse)) + { + DbIsConnected = false; + return false; + } + + DbIsConnected = true; + + // get a list of all stored FW update config file packages + var dbConfigFilePackages = JsonConvert.DeserializeObject>(requestResponse); + if (dbConfigFilePackages == null || dbConfigFilePackages.Count == 0) + { + return false; + } + + // get latest version + var fileId = dbConfigFilePackages.Select(package => package.FileId).Prepend(0).Max(); + if (fileId == 0) + { + return false; + } + + if (DbFwUpdateConfigFiles == null) DbFwUpdateConfigFiles = new List(); + DbFwUpdateConfigFiles.Clear(); + + // download content + url = ServiceUrls.DownloadFileParts(); + url += $"{fileId}&readContent=true"; + requestResponse = LocalWebRequest.GetRequest(url, 10000); + if (string.IsNullOrEmpty(requestResponse)) + { + DbIsConnected = false; + return false; + } + + DbIsConnected = true; + DbFwUpdateConfigFiles = JsonConvert.DeserializeObject>(requestResponse); + return DbFwUpdateConfigFiles != null && DbFwUpdateConfigFiles.Count > 0; + + } + catch (Exception) + { + DbIsConnected = false; + return false; + } + } + /// /// Get all Cordonel safe info files from DB. /// @@ -389,7 +518,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb try { var url = ServiceUrls.ListAllFwUpdateSafes(); - var requestResponse = LocalWebRequest.GetRequest(url, 5000); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -430,7 +559,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { var url = ServiceUrls.ListAllFwUpdateSafesForUserServiceUrl(); url += $"{userId}"; - var requestResponse = LocalWebRequest.GetRequest(url, 3000); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -468,7 +597,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { var url = ServiceUrls.DownloadFileParts(); url += $"{fileId}&readContent={readContent}"; - var requestResponse = LocalWebRequest.GetRequest(url, 5000); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -506,7 +635,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { var url = ServiceUrls.DownloadFileParts(); url += $"{fileId}&readContent={readContent}"; - var requestResponse = LocalWebRequest.GetRequest(url, 5000); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -524,7 +653,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } } - /// + /// /// Get all Cordonel customers from DB. The return can be used to select a specific customer and get /// the customer number which is the base for the order search. /// @@ -538,7 +667,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb // for the DB interface a specific search pattern will be used, so replace it from the user interface // as there is a "*" the placeholder for "all". searchPattern = searchPattern.Replace("*", "%"); - if (DbSearchedCordonelCustomers == null) + if (DbSearchedCordonelCustomers == null) DbSearchedCordonelCustomers = new List(); DbSearchedCordonelCustomers.Clear(); @@ -546,7 +675,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { var url = ServiceUrls.ListAllCordonelCustomersWithFilterServiceUrl(); url += searchPattern; - var requestResponse = LocalWebRequest.GetRequest(url, 1200); + var requestResponse = LocalWebRequest.GetRequest(url, 10000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -554,7 +683,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } DbIsConnected = true; - DbSearchedCordonelCustomers = + DbSearchedCordonelCustomers = JsonConvert.DeserializeObject>(requestResponse); return DbSearchedCordonelCustomers != null && DbSearchedCordonelCustomers.Count != 0; } @@ -574,9 +703,9 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// /// - Initial. /// - public Boolean GetAllCordonelCustomerOrdersFromDb(Int64 customerNumber ) + public Boolean GetAllCordonelCustomerOrdersFromDb(Int64 customerNumber) { - if (DbCordonelCustomerOrders == null) + if (DbCordonelCustomerOrders == null) DbCordonelCustomerOrders = new List(); DbCordonelCustomerOrders.Clear(); @@ -592,7 +721,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } DbIsConnected = true; - DbCordonelCustomerOrders = + DbCordonelCustomerOrders = JsonConvert.DeserializeObject>(requestResponse); return DbCordonelCustomerOrders != null && DbCordonelCustomerOrders.Count != 0; } @@ -611,9 +740,9 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// /// - Initial. /// - public Boolean GetAllCordonelSerialNumbersFromDb(Int64 orderNumber, Int64 orderPos ) + public Boolean GetAllCordonelSerialNumbersFromDb(Int64 orderNumber, Int64 orderPos) { - if (DbCordonelSerialNumbers == null) + if (DbCordonelSerialNumbers == null) DbCordonelSerialNumbers = new List(); DbCordonelSerialNumbers.Clear(); @@ -629,7 +758,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } DbIsConnected = true; - DbCordonelSerialNumbers = + DbCordonelSerialNumbers = JsonConvert.DeserializeObject>(requestResponse); return DbCordonelSerialNumbers != null && DbCordonelSerialNumbers.Count != 0; } @@ -694,7 +823,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { // The fully specified user has to be defined by FullName, LogInName, Domain, Hw Id and User Pwd Hash. // The user id mustn't be set as this will be returned by the DB search. - if (dbCheckFullSpecUpdateOperator == null || DbAllUpdateOperators == null || + if (dbCheckFullSpecUpdateOperator == null || DbAllUpdateOperators == null || DbAllUpdateOperators.Count == 0 || string.IsNullOrEmpty(dbCheckFullSpecUpdateOperator.FullName) || string.IsNullOrEmpty(dbCheckFullSpecUpdateOperator.LogInName) || @@ -1164,6 +1293,40 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb } } + /// + /// Download all pcbIds contained in a special FW update safe for information referenced by container id + /// + /// + /// true if file content exists + /// + /// - Initial. + /// + public List GetFwUpdateSafePcbIdsFromDb(Int32 containerId) + { + var fwUpdateSafesPcbIds = new List(); + try + { + var url = ServiceUrls.ListAllPcbIdsFromSafe(); + url += $"{containerId}"; + var requestResponse = LocalWebRequest.GetRequest(url, 10000); + if (string.IsNullOrEmpty(requestResponse)) + { + DbIsConnected = false; + return fwUpdateSafesPcbIds; + } + + DbIsConnected = true; + fwUpdateSafesPcbIds = JsonConvert.DeserializeObject>(requestResponse); + + return fwUpdateSafesPcbIds; + } + catch (Exception) + { + DbIsConnected = false; + return fwUpdateSafesPcbIds; + } + } + /// /// Getting file contents referenced by file part id. /// -http://localhost:56011/GetFileContent?FileId=3831 @@ -1204,20 +1367,25 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// Get reports from DB. /// It can be searched for: /// PCB ID, - /// User ID or - /// Order Number. + /// User ID, + /// Order Number, + /// Read content ( if false, a preview is available only). /// Leaving all empty will search all reports. /// /// list of reports /// optional pcbId /// optional userId /// optional order number - /// true if app list could be loaded + /// if false a preview of the reports will be loaded + /// true reports could be loaded /// /// - Initial. /// + /// + /// - Read content. + /// public Boolean DownloadFwUpdateReportsFromDb(out List fwUpdRpt, Int64 pcbId = 0, - Int32 userId = 0, Int64 orderNr = 0) + Int32 userId = 0, Int64 orderNr = 0, Boolean readContent = false) { fwUpdRpt = new List(); try @@ -1226,20 +1394,22 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb if (pcbId > 0) { url += $"PcbId={pcbId}"; - if( userId > 0 ) url += $"&UserId={userId}"; - if( orderNr > 0 ) url += $"&OrderNr={orderNr}"; + if (userId > 0) url += $"&UserId={userId}"; + if (orderNr > 0) url += $"&OrderNr={orderNr}"; } else if (userId > 0) { url += $"UserId={userId}"; - if( orderNr > 0 ) url += $"&OrderNr={orderNr}"; + if (orderNr > 0) url += $"&OrderNr={orderNr}"; } else if (orderNr > 0) { url += $"OrderNr={orderNr}"; } - var requestResponse = LocalWebRequest.GetRequest(url, 10000); + url += $"&readContent={readContent}"; + + var requestResponse = LocalWebRequest.GetRequest(url, 20000); if (string.IsNullOrEmpty(requestResponse)) { DbIsConnected = false; @@ -1304,7 +1474,7 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// /// - Set container Id, needed to assign PCB IDs. /// - public Boolean UploadFwUpdateSafeToDb(FwUpdateSafeDb fwUpdateSafeDb, List pcbIds ) + public Boolean UploadFwUpdateSafeToDb(FwUpdateSafeDb fwUpdateSafeDb, List pcbIds) { if (fwUpdateSafeDb == null) return false; fwUpdateSafeDb.ContainerId = 0; @@ -1316,16 +1486,16 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb url += $"&PValidDate={fwUpdateSafeDb.ValidDate:yyyy-MM-ddTHH:mm:ss}"; url += $"&PBuilderOperatorName={fwUpdateSafeDb.OperatorNameBuilder}"; - var success = LocalWebRequest.PostBinaryFileRequestAsync(url, fwUpdateSafeDb.Name,fwUpdateSafeDb.Content, out var requestResponse); - + var success = LocalWebRequest.PostBinaryFileRequestAsync(url, fwUpdateSafeDb.Name, fwUpdateSafeDb.Content, out var requestResponse); + var containerId = JsonConvert.DeserializeObject(requestResponse); - if (success && !string.IsNullOrEmpty(requestResponse) && containerId > 0) + if (success && !string.IsNullOrEmpty(requestResponse) && containerId > 0) { fwUpdateSafeDb.ContainerId = containerId; url = ServiceUrls.AddPcbIdsToSafeServiceUrl(); url += containerId; - if (LocalWebRequest.PostRequestAsync(url, 1200, pcbIds)) + if (LocalWebRequest.PostRequestAsync(url, 10000, pcbIds)) { DbIsConnected = true; return true; diff --git a/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateSafeDb.cs b/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateSafeDb.cs index 6bcd58cc..3405e5d3 100644 --- a/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateSafeDb.cs +++ b/ServiceFwUpdate/Common/FwUpdateDb/FwUpdateSafeDb.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb { @@ -39,6 +40,11 @@ namespace Xylem.ServiceFwUpdate.Common.FwUpdateDb /// public Int32 FilePartId { get; set; } + /// + /// List of PcbIds + /// + public List PcbIds { get; set; } + /// /// automatic (DB-job) delete all FwUpdateSafeContainer with invalid date /// diff --git a/ServiceFwUpdate/Documents/2021-10-15 Quick Reference Cordonel Service FW-Update Loader - Rev C.pdf b/ServiceFwUpdate/Documents/2021-10-15 Quick Reference Cordonel Service FW-Update Loader - Rev C.pdf new file mode 100644 index 00000000..56665b80 Binary files /dev/null and b/ServiceFwUpdate/Documents/2021-10-15 Quick Reference Cordonel Service FW-Update Loader - Rev C.pdf differ diff --git a/ServiceFwUpdate/Documents/2021-10-27 Quick Reference Cordonel Service FW-Update Builder - Rev B.pdf b/ServiceFwUpdate/Documents/2021-10-27 Quick Reference Cordonel Service FW-Update Builder - Rev B.pdf new file mode 100644 index 00000000..9efe2398 Binary files /dev/null and b/ServiceFwUpdate/Documents/2021-10-27 Quick Reference Cordonel Service FW-Update Builder - Rev B.pdf differ diff --git a/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Builder.docx b/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Builder.docx index 46526eff..7176ac5f 100644 Binary files a/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Builder.docx and b/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Builder.docx differ diff --git a/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Loader.docx b/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Loader.docx index 4ab26063..477d84ce 100644 Binary files a/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Loader.docx and b/ServiceFwUpdate/Documents/Quick Reference Cordonel Service FW-Update Loader.docx differ diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Const/ProcessState.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Const/ProcessState.cs index 75062e04..cf98c05e 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Const/ProcessState.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Const/ProcessState.cs @@ -58,6 +58,20 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Const /// GetCordonelProductionOrdersFromDb, + /// + /// Load all Cordonel FW update safes from DB + /// + GetFwUpdateSafesInfosFromDb, + + /// + /// Load all Cordonel FW update report files from DB + /// + GetReportsFromDb, + + /// + /// Load selected Cordonel FW update report file from DB and display it + /// + GetAndDisplaySingleReportFromDb, /// /// Load all Cordonel serial numbers off a specific order from DB /// diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.Designer.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.Designer.cs index cda57dd0..10c472f2 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.Designer.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.Designer.cs @@ -91,7 +91,13 @@ this.tabPageSafeBuildReport = new System.Windows.Forms.TabPage(); this.rtbReport = new System.Windows.Forms.RichTextBox(); this.tabPageFwUpdateSafes = new System.Windows.Forms.TabPage(); + this.tblFwUpdateSafeSelection = new System.Windows.Forms.TableLayoutPanel(); + this.tblPanelFwUpdateSafeSearch = new System.Windows.Forms.TableLayoutPanel(); + this.gridViewFwUpdateSafeSelection = new System.Windows.Forms.DataGridView(); this.tabPageReports = new System.Windows.Forms.TabPage(); + this.tblPanelFwUpdateReports = new System.Windows.Forms.TableLayoutPanel(); + this.tblPanelFwUpdateReportsSearch = new System.Windows.Forms.TableLayoutPanel(); + this.gridViewFwUpdateReportSelection = new System.Windows.Forms.DataGridView(); this.tblPanelLayer1Top = new System.Windows.Forms.TableLayoutPanel(); this.tblPanelSafeInfo = new System.Windows.Forms.TableLayoutPanel(); this.lblCustomerNameText = new System.Windows.Forms.Label(); @@ -154,6 +160,12 @@ this.tabPagePreBuildSummary.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.gridViewPreBuildSummary)).BeginInit(); this.tabPageSafeBuildReport.SuspendLayout(); + this.tabPageFwUpdateSafes.SuspendLayout(); + this.tblFwUpdateSafeSelection.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridViewFwUpdateSafeSelection)).BeginInit(); + this.tabPageReports.SuspendLayout(); + this.tblPanelFwUpdateReports.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridViewFwUpdateReportSelection)).BeginInit(); this.tblPanelLayer1Top.SuspendLayout(); this.tblPanelSafeInfo.SuspendLayout(); this.tableLayoutPanel1.SuspendLayout(); @@ -194,9 +206,7 @@ // radioBtnEnglishLanguage // resources.ApplyResources(this.radioBtnEnglishLanguage, "radioBtnEnglishLanguage"); - this.radioBtnEnglishLanguage.Checked = true; this.radioBtnEnglishLanguage.Name = "radioBtnEnglishLanguage"; - this.radioBtnEnglishLanguage.TabStop = true; this.radioBtnEnglishLanguage.UseVisualStyleBackColor = true; this.radioBtnEnglishLanguage.Click += new System.EventHandler(this.RadioBtnEnglishLanguage_Click); // @@ -645,16 +655,71 @@ // this.tabPageFwUpdateSafes.BackColor = System.Drawing.SystemColors.Control; this.tabPageFwUpdateSafes.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.tabPageFwUpdateSafes.Controls.Add(this.tblFwUpdateSafeSelection); resources.ApplyResources(this.tabPageFwUpdateSafes, "tabPageFwUpdateSafes"); this.tabPageFwUpdateSafes.Name = "tabPageFwUpdateSafes"; // + // tblFwUpdateSafeSelection + // + resources.ApplyResources(this.tblFwUpdateSafeSelection, "tblFwUpdateSafeSelection"); + this.tblFwUpdateSafeSelection.Controls.Add(this.tblPanelFwUpdateSafeSearch, 0, 0); + this.tblFwUpdateSafeSelection.Controls.Add(this.gridViewFwUpdateSafeSelection, 0, 1); + this.tblFwUpdateSafeSelection.Name = "tblFwUpdateSafeSelection"; + // + // tblPanelFwUpdateSafeSearch + // + resources.ApplyResources(this.tblPanelFwUpdateSafeSearch, "tblPanelFwUpdateSafeSearch"); + this.tblPanelFwUpdateSafeSearch.Name = "tblPanelFwUpdateSafeSearch"; + // + // gridViewFwUpdateSafeSelection + // + this.gridViewFwUpdateSafeSelection.AllowUserToAddRows = false; + this.gridViewFwUpdateSafeSelection.AllowUserToDeleteRows = false; + this.gridViewFwUpdateSafeSelection.AllowUserToResizeColumns = false; + this.gridViewFwUpdateSafeSelection.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; + this.gridViewFwUpdateSafeSelection.BackgroundColor = System.Drawing.SystemColors.Control; + this.gridViewFwUpdateSafeSelection.BorderStyle = System.Windows.Forms.BorderStyle.None; + resources.ApplyResources(this.gridViewFwUpdateSafeSelection, "gridViewFwUpdateSafeSelection"); + this.gridViewFwUpdateSafeSelection.EnableHeadersVisualStyles = false; + this.gridViewFwUpdateSafeSelection.GridColor = System.Drawing.SystemColors.ControlLight; + this.gridViewFwUpdateSafeSelection.Name = "gridViewFwUpdateSafeSelection"; + this.gridViewFwUpdateSafeSelection.ReadOnly = true; + // // tabPageReports // this.tabPageReports.BackColor = System.Drawing.SystemColors.Control; this.tabPageReports.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.tabPageReports.Controls.Add(this.tblPanelFwUpdateReports); resources.ApplyResources(this.tabPageReports, "tabPageReports"); this.tabPageReports.Name = "tabPageReports"; // + // tblPanelFwUpdateReports + // + resources.ApplyResources(this.tblPanelFwUpdateReports, "tblPanelFwUpdateReports"); + this.tblPanelFwUpdateReports.Controls.Add(this.tblPanelFwUpdateReportsSearch, 0, 0); + this.tblPanelFwUpdateReports.Controls.Add(this.gridViewFwUpdateReportSelection, 0, 1); + this.tblPanelFwUpdateReports.Name = "tblPanelFwUpdateReports"; + // + // tblPanelFwUpdateReportsSearch + // + resources.ApplyResources(this.tblPanelFwUpdateReportsSearch, "tblPanelFwUpdateReportsSearch"); + this.tblPanelFwUpdateReportsSearch.Name = "tblPanelFwUpdateReportsSearch"; + // + // gridViewFwUpdateReportSelection + // + this.gridViewFwUpdateReportSelection.AllowUserToAddRows = false; + this.gridViewFwUpdateReportSelection.AllowUserToDeleteRows = false; + this.gridViewFwUpdateReportSelection.AllowUserToResizeRows = false; + this.gridViewFwUpdateReportSelection.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; + this.gridViewFwUpdateReportSelection.BackgroundColor = System.Drawing.SystemColors.Control; + this.gridViewFwUpdateReportSelection.BorderStyle = System.Windows.Forms.BorderStyle.None; + resources.ApplyResources(this.gridViewFwUpdateReportSelection, "gridViewFwUpdateReportSelection"); + this.gridViewFwUpdateReportSelection.EnableHeadersVisualStyles = false; + this.gridViewFwUpdateReportSelection.GridColor = System.Drawing.SystemColors.ControlLight; + this.gridViewFwUpdateReportSelection.Name = "gridViewFwUpdateReportSelection"; + this.gridViewFwUpdateReportSelection.ReadOnly = true; + this.gridViewFwUpdateReportSelection.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.gridViewFwUpdateReportSelection_CellClick); + // // tblPanelLayer1Top // resources.ApplyResources(this.tblPanelLayer1Top, "tblPanelLayer1Top"); @@ -933,6 +998,12 @@ this.tabPagePreBuildSummary.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.gridViewPreBuildSummary)).EndInit(); this.tabPageSafeBuildReport.ResumeLayout(false); + this.tabPageFwUpdateSafes.ResumeLayout(false); + this.tblFwUpdateSafeSelection.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridViewFwUpdateSafeSelection)).EndInit(); + this.tabPageReports.ResumeLayout(false); + this.tblPanelFwUpdateReports.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridViewFwUpdateReportSelection)).EndInit(); this.tblPanelLayer1Top.ResumeLayout(false); this.tblPanelSafeInfo.ResumeLayout(false); this.tblPanelSafeInfo.PerformLayout(); @@ -1047,6 +1118,12 @@ private System.Windows.Forms.Label lblCordonelSelectedCountText; private System.Windows.Forms.Label lblCordonelsSelectedCount; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.TableLayoutPanel tblPanelFwUpdateReports; + private System.Windows.Forms.TableLayoutPanel tblPanelFwUpdateReportsSearch; + private System.Windows.Forms.DataGridView gridViewFwUpdateReportSelection; + private System.Windows.Forms.TableLayoutPanel tblFwUpdateSafeSelection; + private System.Windows.Forms.TableLayoutPanel tblPanelFwUpdateSafeSearch; + private System.Windows.Forms.DataGridView gridViewFwUpdateSafeSelection; } } diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs index 3f135a86..b2411ea4 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs @@ -97,12 +97,34 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder private DataTable _dataTableCordonels; private DataTable _dataTableUpdateOperators; private DataTable _dataTableCustomers; + private DataTable _dataTableReportFiles; + private DataTable _dataTableUpdateSafes; + + // external update remarks form + + // external update remarks form + private readonly FrmHistory _frmFwUpdateReport = new FrmHistory(); /// /// Collection of software needed for the FW-Update safe! /// private SoftwareContainer _fwUpdateSwContainer; /// + /// All report files from the DB! + /// This information will only be used by the FW Update Builder! + /// + private readonly List _fwUpdateReports = new List(); + /// + /// One selected report file on grid view by the user from the DB! + /// This information will only be used by the FW Update Builder! + /// + private readonly FwUpdateReportDb _selectedReport = new FwUpdateReportDb(); + /// + /// All FW update safes from the DB! + /// This information will only be used by the FW Update Builder! + /// + private readonly List _fwUpdateSafesInfos = new List(); + /// /// All customer specific production order numbers to search mask from the DB! /// This information will only be used by the FW Update Builder! /// @@ -176,6 +198,8 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder private Boolean _customersPropertyChanged; private Boolean _cordonelsPropertyChanged; private Boolean _fwPackagePropertyChanged; + private Boolean _fwReportsPropertyChanged; + private Boolean _fwUpdateSafesPropertyChanged; private Boolean _preBuildSummaryPropertyChanged; /// @@ -187,7 +211,6 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// private const Int32 DbConnectionTimeoutMs = 5000; private Int32 _dbAccessDelayCtrMs; - private Boolean _dbAccessIsLocked; /// /// Project name for the DLL to load: @@ -219,7 +242,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder ProgramConfig.NlogConfig); /// - /// Source folder of binaries + /// Source folder of software package if taken from local [user]/downloads/ServiceFwUpdateSw /// private static readonly String FwUpdateSwSourcePath = Path.Combine(Environment.GetFolderPath( Environment.SpecialFolder.UserProfile), FwUpdateConfig.DefaultFwUpdateSwSourcePath); @@ -239,6 +262,9 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// /// - Sleep on equal process state to force suspend of actual thread. /// + /// + /// - Added report files and FW-Update safes load from DB. + /// private void FwUpdateBuilderStateMachine() { while (!_processToken.IsCancellationRequested) @@ -281,6 +307,18 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder LoadDbCordonelCustomersTask(); break; + case ProcessState.GetReportsFromDb: + LoadDbReportsTask(); + break; + + case ProcessState.GetAndDisplaySingleReportFromDb: + LoadDbReportAndDisplayTask(); + break; + + case ProcessState.GetFwUpdateSafesInfosFromDb: + LoadDbFwUpdateSafesInfosTask(); + break; + case ProcessState.GetFwUpdateOperatorsFromDb: LoadDbFwUpdateOperatorsTask(); break; @@ -361,6 +399,9 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// /// - Checks exported /// + /// + /// - Added checks for FW-update safes and report files. + /// private void TmrProgressUpdate_Tick(Object sender, EventArgs e) { Thread.CurrentThread.CurrentUICulture = _cultureInfo; @@ -380,6 +421,8 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder CheckCustomerChange(); CheckCordonelChange(); CheckFwPackageChange(); + CheckFwUpdateSafesChange(); + CheckReportsChange(); break; case ProcessState.BuildFwUpdateSafe: SetStatusProgressBar(ProgressBarStatus.Value + 1 > 100 ? 0 : ProgressBarStatus.Value + 1); @@ -390,6 +433,9 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder case ProcessState.GetCustomersFromDb: case ProcessState.GetFwPackagesFromDb: case ProcessState.GetCordonelSerialNumbersFromDb: + case ProcessState.GetFwUpdateSafesInfosFromDb: + case ProcessState.GetReportsFromDb: + case ProcessState.GetAndDisplaySingleReportFromDb: case ProcessState.UploadFwUpdateSafeToDb: CheckDbConnectionTimeout(); SetStatusProgressBar(ProgressBarStatus.Value + 1 > 100 ? 0 : ProgressBarStatus.Value + 1); @@ -452,7 +498,6 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder private void infoToolStripMenuItem_Click(Object sender, EventArgs e) { _processState = ProcessState.UserRegistration; - _dbAccessIsLocked = true; var frmRegister = new FrmRegister(_regUser); DisableAllControlsInvoked(); frmRegister.Show(); @@ -472,7 +517,6 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder Show(); Update(); CheckUserRegistration(); - _dbAccessIsLocked = false; } /// /// Exit the program @@ -663,6 +707,26 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// private void tabControlSelection_Selected(Object sender, TabControlEventArgs e) { + if (e.TabPage == tabPageFwUpdateSafes) + { + DisableAllControlsInvoked(); + UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingFwUpdateSafes); + SetStatusProgressBar(); + _dbAccessDelayCtrMs = 0; + _processState = ProcessState.GetFwUpdateSafesInfosFromDb; + + } + + if (e.TabPage == tabPageReports) + { + DisableAllControlsInvoked(); + UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingReports); + SetStatusProgressBar(); + _dbAccessDelayCtrMs = 0; + _processState = ProcessState.GetReportsFromDb; + + } + if (e.TabPage == tabPageCordonelSelection) { // avoid reading of DB contents and reset of selection if customer remains identical @@ -692,7 +756,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder if (e.TabPage == tabPageFwPackageSelection) { // Load fw packages only if not selected indicated in count - if (_fwUpdatePackages.Count > 0 || + if (_fwUpdatePackages.Count > 0 || _cordonelFwPackageInfoSearch != null && _cordonelFwPackageInfoSearch.Count > 0) return; DisableAllControlsInvoked(); @@ -903,9 +967,10 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// public FrmFwUpdateBuilder() { + _cultureInfo = Thread.CurrentThread.CurrentCulture; var fwUpdateBuilderExePath = AppDomain.CurrentDomain.BaseDirectory; - var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath, "Library"); - var fwUpdateBuilderConfigPath = Path.Combine(fwUpdateBuilderExePath, "Config"); + var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath, FwUpdateConfig.LibrarySubFolderName); + var fwUpdateBuilderConfigPath = Path.Combine(fwUpdateBuilderExePath, FwUpdateConfig.ConfigSubFolderName); var nLogConfigSourcePathName = Path.Combine(fwUpdateBuilderConfigPath, ProgramConfig.NlogConfig); @@ -926,9 +991,9 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder if (File.Exists(nLogConfigSourcePathName) && !File.Exists(NLogConfigurationDestPathFile)) SystemControl.CopyFile(nLogConfigSourcePathName, NLogConfigurationDestPathFile); - var rulerPathName = Path.Combine(fwUpdateBuilderLibraryPath, + var rulerPathName = Path.Combine(fwUpdateBuilderLibraryPath, FwUpdateConfig.MeterFwUpdateRulerConfigFileName); - if (!File.Exists(rulerPathName)) rulerPathName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, + if (!File.Exists(rulerPathName)) rulerPathName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FwUpdateConfig.MeterFwUpdateRulerConfigFileName); if (File.Exists(rulerPathName)) { @@ -951,12 +1016,9 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder InitializeComponent(); - _cultureInfo = Thread.CurrentThread.CurrentCulture; - radioBtnEnglishLanguage.Checked = true; - if (_cultureInfo.IetfLanguageTag == "de-DE") - { - radioBtnGermanLanguage.Checked = true; - } + if (_cultureInfo.IetfLanguageTag.Contains("de-")) radioBtnGermanLanguage.Checked = true; + else radioBtnEnglishLanguage.Checked = true; + lblFwUpdateInfo.Text = $@"Version: {_version.Major}.{_version.Minor}.{_version.Build}"; lblStatusDbConnect.ForeColor = ColorDefault; @@ -1044,6 +1106,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// private void FrmFwUpdateBuilder_FormClosing(Object sender, FormClosingEventArgs e) { + _frmFwUpdateReport?.Close(); _datePicker?.Dispose(); _cbxFwReleaseSelection?.Dispose(); _processToken?.Cancel(); @@ -1088,6 +1151,12 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// /// - Added FwUpdateSafeDb preparation /// + /// + /// - Added BuildFwUpdateSwContainerFromDb, not longer taken from locally file system! + /// + /// + /// - Skip loading of FW upadte SW if already done in preceding run. + /// public Boolean BuildFwUpdateSafe() { if (string.IsNullOrEmpty(lblUpdateOperator.Text)) return false; @@ -1129,8 +1198,8 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder } GetFwUpdateSwLicenseFromDb(FwUpdateSwFullName, out fwUpdateSafe.License); - -if (fwUpdateSafe.License == null) + + if (fwUpdateSafe.License == null) { LogErrorText(Resources.StrSwLicenseMissing); MessageBoxShow(Resources.StrSwLicenseMissing, Resources.StrError, MessageBoxButtons.OK, @@ -1139,16 +1208,15 @@ if (fwUpdateSafe.License == null) return false; } - // overwrite license as operator has decided for FW-Update Valid date + // overwrite license validation date as operator has selected this fwUpdateSafe.License.ValidTo = DateTimeServer.GetDateTimeFromDateString(lblFwUpdateDutyDate.Text + " 23:59:59", _cultureInfo); LogSuccessText($@"{Resources.StrSwLicenseLoadedSuccessfully} {FwUpdateProjectName}" + $" {fwUpdateSafe.License.Major}.{fwUpdateSafe.License.Minor}.{fwUpdateSafe.License.Build}"); - //GetFwUpdateSwContainerFromDb(); - if (!BuildFwUpdateSwContainer(fwUpdateSafe.License) || - _fwUpdateSwContainer?.RegisterDefinitionFile == null || + // Skip loading of FW update SW if already done in preceding run + if (_fwUpdateSwContainer?.RegisterDefinitionFile == null || _fwUpdateSwContainer.SoftwareSetupFile == null || _fwUpdateSwContainer.MeterFilesEraseRestore == null || string.IsNullOrEmpty(_fwUpdateSwContainer.RegisterDefinitionFile.FileName) || @@ -1157,12 +1225,26 @@ if (fwUpdateSafe.License == null) _fwUpdateSwContainer.SoftwareDynLinkLibs == null || _fwUpdateSwContainer.SoftwareDynLinkLibs.Count == 0) { - LogErrorText(Resources.StrSwContainerCollectionFailed); - MessageBoxShow(Resources.StrSwContainerCollectionFailed, Resources.StrError, MessageBoxButtons.OK, - MessageBoxIcon.Error); - _processState = ProcessState.Error; - return false; + // local files: if (!BuildFwUpdateSwContainer(fwUpdateSafe.License) || + if (!BuildFwUpdateSwContainerFromDb(fwUpdateSafe.License) || + _fwUpdateSwContainer?.RegisterDefinitionFile == null || + _fwUpdateSwContainer.SoftwareSetupFile == null || + _fwUpdateSwContainer.MeterFilesEraseRestore == null || + string.IsNullOrEmpty(_fwUpdateSwContainer.RegisterDefinitionFile.FileName) || + string.IsNullOrEmpty(_fwUpdateSwContainer.SoftwareSetupFile.FileName) || + string.IsNullOrEmpty(_fwUpdateSwContainer.MeterFilesEraseRestore.FileName) || + _fwUpdateSwContainer.SoftwareDynLinkLibs == null || + _fwUpdateSwContainer.SoftwareDynLinkLibs.Count == 0) + { + LogErrorText(Resources.StrSwContainerCollectionFailed); + MessageBoxShow(Resources.StrSwContainerCollectionFailed, Resources.StrError, + MessageBoxButtons.OK, + MessageBoxIcon.Error); + _processState = ProcessState.Error; + return false; + } } + fwUpdateSafe.Software = _fwUpdateSwContainer; LogSuccessText(Resources.StrSwContainerCollectionSuccess); @@ -1285,113 +1367,6 @@ if (fwUpdateSafe.License == null) } } - ///// - ///// Take user input to fill the FW-Update collection information. - ///// - ///// - ///// - Initial. - ///// - ///// - ///// - Clear update info on entry. - ///// - ///// - ///// - Checkbox to enable DEBUG Cordonels for development. - ///// - ///// - ///// - Added DEBUG Cordonels to CordonelProductionInfos. - ///// - //public void DebugDeviceAndFwPackageSelection() - //{ - // _cordonelProductionInfos.Clear(); - // if (!cbxAddDebugCordonels.Checked) return; - - // var updateInfo = new CordonelDeviceInfo - // { - // PcbId = "182100041", - // CustomerSerialNumber = @"Octopus 1", - // RequiredRelease = "EMEA R106D 868MHz" - // //RequiredRelease = "EMEA R106B TEST (it is R106D)" - // //RequiredRelease = "EMEA R106B 433MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // updateInfo = new CordonelDeviceInfo - // { - // PcbId = "192000001", - // CustomerSerialNumber = @"Octopus 2", - // RequiredRelease = "EMEA R1066 433MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // updateInfo = new CordonelDeviceInfo - // { - // PcbId = "192000004", - // CustomerSerialNumber = @"Octopus 3", - // RequiredRelease = "EMEA R106D 868MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // updateInfo = new CordonelDeviceInfo - // { - // PcbId = "192000006", - // CustomerSerialNumber = @"Octopus 4", - // RequiredRelease = "EMEA R106D 868MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // updateInfo = new CordonelDeviceInfo - // { - // PcbId = "192000007", - // CustomerSerialNumber = @"Octopus 5", - // RequiredRelease = "EMEA R106D 868MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // updateInfo = new CordonelDeviceInfo - // { - // PcbId = "192000009", - // CustomerSerialNumber = @"Octopus 6", - // RequiredRelease = "EMEA R106D 868MHz" - // }; - // if (_cordonelDeviceInfos.All(d => d.PcbId != updateInfo.PcbId)) _cordonelDeviceInfos.Add(updateInfo); - - // foreach (var cordonelUpdateInfo in _cordonelDeviceInfos) - // { - // var cordonel = new CordonelProductionInfosDb - // { - // IsSelected = true, - // CatalogNumber = "OCTOPUS", - // CustomerOrderNumber = 999999, - // CustomerOrderPos = 99, - // Diameter = "0", - // Length = "0", - // PcbId = cordonelUpdateInfo.PcbId, - // CustomerSerialNumber = cordonelUpdateInfo.CustomerSerialNumber, - // SensusSerialNumber = @"Test-Cordonel", - // RequiredReleaseNameVersion = cordonelUpdateInfo.RequiredRelease - // }; - // if (_fwUpdateDbAccess != null && - // _fwUpdateDbAccess.DownloadCordonelAppVersionsFromDb(cordonel.PcbId, out var cordonelAppVersions)) - // { - // foreach (var appVersion in cordonelAppVersions) - // { - // if (appVersion.Id == -1) cordonel.CoreRevision = appVersion.Version; - // if (appVersion.Id == 0x0F) - // { - // cordonel.Metrology = appVersion.Version; - // cordonel.MetrologyIsUpdateable = appVersion.IsUpdateable; - // } - - // if (appVersion.Id == 0x18) - // cordonel.InstalledReleaseNameVersion = appVersion.Version; - // } - // } - // if (_cordonelProductionInfos.All(d => d.PcbId != cordonel.PcbId)) - // _cordonelProductionInfos.Add(cordonel); - // } - - // _cordonelsPropertyChanged = true; - //} #endregion --------------------------------------- Build FW-Update Safe --------------------------------------- @@ -1404,9 +1379,6 @@ if (fwUpdateSafe.License == null) /// private void CheckUserRegistration() { - - - if (_fwUpdateDbAccess == null || _regUser == null) return; _regUser.Domain = CryptInformation.GetSysDomain(); _regUser.LogInName = CryptInformation.GetSysUserLoginName(); @@ -1519,7 +1491,6 @@ if (fwUpdateSafe.License == null) if (_fwUpdateDbAccess.DbIsConnected) { // DB is free to use - _dbAccessIsLocked = false; if (_dbLicenseRefreshDelayCtrMs > DbLicenseRefreshTimeoutMs) { @@ -1608,14 +1579,16 @@ if (fwUpdateSafe.License == null) // Check the order numbers (add one for the "*" ) if (_fwUpdateDbAccess?.DbCordonelCustomerOrders != null) { - if (cbxCordonelProductionOrdersSearch.Items.Count != _fwUpdateDbAccess.DbCordonelCustomerOrders.Count + 1) + if (cbxCordonelProductionOrdersSearch.Items.Count != + _fwUpdateDbAccess.DbCordonelCustomerOrders.Count + 1) { cbxCordonelProductionOrdersSearch.Items.Clear(); cbxCordonelProductionOrdersSearch.Text = @"*"; cbxCordonelProductionOrdersSearch.Items.Add("*"); foreach (var order in _fwUpdateDbAccess.DbCordonelCustomerOrders) { - cbxCordonelProductionOrdersSearch.Items.Add($@"{order.CustomerOrderNumber}-{order.CustomerOrderPos}"); + cbxCordonelProductionOrdersSearch.Items.Add( + $@"{order.CustomerOrderNumber}-{order.CustomerOrderPos}"); } } } @@ -1883,6 +1856,7 @@ if (fwUpdateSafe.License == null) // update output information FillDataGridWithUpdateOperatorInfos(); } + /// /// Check for change of customer. /// @@ -1901,6 +1875,7 @@ if (fwUpdateSafe.License == null) // update output information FillDataGridWithCustomerInfos(); } + /// /// Check for change of Cordonels. /// @@ -1947,9 +1922,40 @@ if (fwUpdateSafe.License == null) // update output information FillDataGridWithFwPackageInfos(); } + + /// + /// Check for change of report files. + /// + /// + /// - Initial + /// + private void CheckReportsChange() + { + if (!_fwReportsPropertyChanged) return; + + _fwReportsPropertyChanged = false; + // update output information + FillDataGridWithReportsInfos(); + } + + /// + /// Check for change of Fw update safes. + /// + /// + /// - Initial + /// + private void CheckFwUpdateSafesChange() + { + if (!_fwUpdateSafesPropertyChanged) return; + + _fwUpdateSafesPropertyChanged = false; + // update output information + FillDataGridWithFwUpdateSafesInfos(); + } #endregion --------------------------------------- Checks ----------------------------------------------------- #region ------------------------------------------ Tools ------------------------------------------------------ + ///// ///// Build the meter file update ruler to define releases which can be updated to another release. ///// @@ -2104,13 +2110,15 @@ if (fwUpdateSafe.License == null) break; } } + /// /// Common message window. /// /// /// - Forcing message box being modal and on top. /// - private static void MessageBoxShow(String text, String caption, MessageBoxButtons buttons = MessageBoxButtons.OK, + private static void MessageBoxShow(String text, String caption, + MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxIcon icon = MessageBoxIcon.Asterisk) { MessageBox.Show(text, caption, buttons, icon, MessageBoxDefaultButton.Button1, @@ -2373,7 +2381,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); } @@ -2383,7 +2390,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _processState = ProcessState.Idle; }); } @@ -2409,7 +2415,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); GetAllUpdateOperatorsFromDb(); @@ -2420,7 +2425,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _fwUpdateOperatorsPropertyChanged = true; _processState = ProcessState.Idle; }); @@ -2441,7 +2445,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); GetLicenseFromDb(); @@ -2452,7 +2455,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; if (_regUser.AccountActive) { _licenseValidDateTimeOffset = DateTimeServer.GetDateTimeTodayUntilMidnight(); @@ -2468,6 +2470,12 @@ if (fwUpdateSafe.License == null) /// /// - Initial /// + /// + /// - Load configuration files from DB as the latest MeterFwUpdateRuler.json is needed for the + /// FwUpdateBuilder FW package check and validation routine! This step has to be done in advance + /// to the FW package load, as the Builder uses the information of the MeterFwUpdateRuler to + /// create the package information! + /// private void LoadDbCordonelFwPackagesTask() { _invokerProcessState = _processState; @@ -2477,9 +2485,11 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); + // has to be done first to extract the MeterFwUpdateRuler + GetFwUpdateConfigFilesFromDb(); + // load the packages and use the MeterFwUpdateRuler to assign the DN, EMEA, NA, 868, 433.. GetCordonelFwPackagesFromDb(); } catch (Exception) @@ -2488,12 +2498,101 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _fwPackagePropertyChanged = true; _processState = ProcessState.Idle; }); } + /// + /// Acquire one report file from DB and display it. + /// + /// + /// - Initial + /// + private void LoadDbReportAndDisplayTask() + { + _invokerProcessState = _processState; + + Task.Factory.StartNew(() => + { + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + try + { + // check DB connection in advance to overcome the timing issues for DB service startup + _fwUpdateDbAccess.CheckDbConnection(); + GetAndDisplaySingleReportFromDb(); + } + catch (Exception) + { + _processState = ProcessState.Error; + } + }).ContinueWith(delegate + { + _processState = ProcessState.Idle; + }); + } + + /// + /// Acquire all report files from DB. + /// + /// + /// - Initial + /// + private void LoadDbReportsTask() + { + _invokerProcessState = _processState; + Task.Factory.StartNew(() => + { + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + try + { + // check DB connection in advance to overcome the timing issues for DB service startup + _fwUpdateDbAccess.CheckDbConnection(); + GetReportsFromDb(); + } + catch (Exception) + { + _processState = ProcessState.Error; + } + }).ContinueWith(delegate + { + _fwReportsPropertyChanged = true; + _processState = ProcessState.Idle; + }); + } + + /// + /// Acquire all FW-Update safes from DB. + /// + /// + /// - Initial + /// + private void LoadDbFwUpdateSafesInfosTask() + { + _invokerProcessState = _processState; + Task.Factory.StartNew(() => + { + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + try + { + // check DB connection in advance to overcome the timing issues for DB service startup + _fwUpdateDbAccess.CheckDbConnection(); + GetFwUpdateSafesInfosFromDb(); + } + catch (Exception) + { + _processState = ProcessState.Error; + } + }).ContinueWith(delegate + { + _fwUpdateSafesPropertyChanged = true; + _processState = ProcessState.Idle; + }); + } + /// /// Acquire all Customers specified by search mask from DB. /// @@ -2515,7 +2614,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); GetAllCordonelCustomersFromDb(); @@ -2526,7 +2624,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _customersPropertyChanged = true; _processState = ProcessState.Idle; }); @@ -2553,7 +2650,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); GetAllCordonelSerialNumbersOfOrderFromDb(); @@ -2564,7 +2660,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _cordonelsPropertyChanged = true; _processState = ProcessState.Idle; }); @@ -2588,7 +2683,6 @@ if (fwUpdateSafe.License == null) Thread.CurrentThread.CurrentCulture = _cultureInfo; try { - _dbAccessIsLocked = true; // check DB connection in advance to overcome the timing issues for DB service startup _fwUpdateDbAccess.CheckDbConnection(); GetAllCordonelOrdersOfCustomerFromDb(); @@ -2599,7 +2693,6 @@ if (fwUpdateSafe.License == null) } }).ContinueWith(delegate { - _dbAccessIsLocked = false; _cordonelsPropertyChanged = true; _processState = ProcessState.Idle; }); @@ -2794,9 +2887,229 @@ if (fwUpdateSafe.License == null) grpLanguageSelection.Enabled = true; } } - #endregion --------------------------------------- Data Grid FW Packages --------------------------------------- + #region ------------------------------------------ Data Grid Update Safes -------------------------------------- + /// + /// Build data grid for FW-Update update safes + /// + /// + /// - Initial. + /// + private void FillDataGridWithFwUpdateSafesInfos() + { + grpLanguageSelection.Enabled = false; + + _dataTableUpdateSafes?.Dispose(); + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + _dataTableUpdateSafes = new DataTable(); + + _dataTableUpdateSafes.Columns.Add(Resources.StrTableUserValidDate, typeof(DateTime)); + _dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String)); + + _dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelUpdateOrder, typeof(Int64)); + _dataTableUpdateSafes.Columns.Add(Resources.StrTableCordonelProductionPos, typeof(Int64)); + + _dataTableUpdateSafes.Columns.Add(Resources.StrTableCustomerName, typeof(String)); + _dataTableUpdateSafes.Columns.Add(Resources.StrTableUserFullName, typeof(String)); + + try + { + foreach (var safeInfo in _fwUpdateSafesInfos) + { + + // create one line per PcbId + foreach (var pcbId in safeInfo.PcbIds) + { + var row = _dataTableUpdateSafes.NewRow(); + + row[Resources.StrTableUserValidDate] = safeInfo.ValidDate.DateTime; + row[Resources.StrTableCordonelPcbId] = pcbId; + + // extract customer name , order and position from file name + var info = safeInfo.Name.Split(FwUpdateConfig.FwUpdateFileFieldSeparator); + var replace = info[1].Replace(FwUpdateConfig.FwUpdateFileExtension, ""); + var orderPos = replace.Split(FwUpdateConfig.FwUpdateFileOrderPosSeparator); + + + row[Resources.StrTableCordonelUpdateOrder] = orderPos[0]; + row[Resources.StrTableCordonelProductionPos] = orderPos[1]; + + row[Resources.StrTableCustomerName] = info[0]; + var userName = "?"; + foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Where(user => + user.Id == safeInfo.UserId)) + { + userName = user.FullName; + break; + } + + row[Resources.StrTableUserFullName] = userName; + _dataTableUpdateSafes.Rows.Add(row); + } + } + + gridViewFwUpdateSafeSelection.DataSource = _dataTableUpdateSafes; + + foreach (DataGridViewColumn column in gridViewFwUpdateSafeSelection.Columns) + { + column.SortMode = DataGridViewColumnSortMode.Automatic; + } + + FwUpdateSafesInfosStyleSet(); + } + catch (Exception) + { + _processState = ProcessState.Error; + } + finally + { + grpLanguageSelection.Enabled = true; + } + } + + /// + /// Color the rows depending on the state + /// + /// + /// - Initial. + /// + private void FwUpdateSafesInfosStyleSet() + { + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + + foreach (DataGridViewRow dataGridRow in gridViewFwUpdateSafeSelection.Rows) + { + dataGridRow.DefaultCellStyle = DateTimeServer.GetDateTimeOffsetFromDateString( + dataGridRow.Cells[Resources.StrTableUserValidDate].Value.ToString()) >= DateTimeOffset.Now ? + _styleValid : _styleInvalid; + } + } + #endregion --------------------------------------- Data Grid Update Safes -------------------------------------- + + #region ------------------------------------------ Data Grid Report Files -------------------------------------- + /// + /// Overwrite cell click, because edit of cells is denied (read only == true). + /// + /// + /// + /// + /// - Initial. + /// + private void gridViewFwUpdateReportSelection_CellClick(Object sender, DataGridViewCellEventArgs e) + { + try + { + if (e.ColumnIndex < 0 || e.RowIndex < 0 || _dataTableReportFiles == null) + { + return; + } + + for (var columnIndex = 0; columnIndex < gridViewFwUpdateReportSelection.ColumnCount; columnIndex++) + { + if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableUpdateOperatorId) + _selectedReport.UserId = + Convert.ToInt32(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value); + if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableDate) + _selectedReport.Date = Convert.ToDateTime( + gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value); + if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == Resources.StrTableCordonelPcbId) + _selectedReport.PcbId = + Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value); + if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == + Resources.StrTableCordonelUpdateOrder) + _selectedReport.OrderNr = + Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value); + if (gridViewFwUpdateReportSelection.Columns[columnIndex].Name == + Resources.StrTableCordonelProductionPos) + _selectedReport.OrderPos = + Convert.ToInt64(gridViewFwUpdateReportSelection.Rows[e.RowIndex].Cells[columnIndex].Value); + } + DisableAllControlsInvoked(); + UiInvoker.ToolStripLabelInvoker(lblStatusDbConnect, ColorSuccess, Resources.StrReadingReports); + SetStatusProgressBar(); + _dbAccessDelayCtrMs = 0; + + _processState = ProcessState.GetAndDisplaySingleReportFromDb; + } + catch (Exception) + { + _processState = ProcessState.Error; + } + } + + /// + /// Build data grid for FW-Update report files + /// + /// + /// - Initial. + /// + private void FillDataGridWithReportsInfos() + { + grpLanguageSelection.Enabled = false; + + _dataTableReportFiles?.Dispose(); + Thread.CurrentThread.CurrentUICulture = _cultureInfo; + Thread.CurrentThread.CurrentCulture = _cultureInfo; + _dataTableReportFiles = new DataTable(); + + _dataTableReportFiles.Columns.Add(Resources.StrTableDate, typeof(DateTime)); + _dataTableReportFiles.Columns.Add(Resources.StrTableCordonelPcbId, typeof(String)); + + _dataTableReportFiles.Columns.Add(Resources.StrTableCordonelUpdateOrder, typeof(Int64)); + _dataTableReportFiles.Columns.Add(Resources.StrTableCordonelProductionPos, typeof(Int64)); + + _dataTableReportFiles.Columns.Add(Resources.StrTableUserFullName, typeof(String)); + + _dataTableReportFiles.Columns.Add(Resources.StrTableUpdateOperatorId, typeof(Int32)); + + try + { + foreach (var report in _fwUpdateReports) + { + + var row = _dataTableReportFiles.NewRow(); + + row[Resources.StrTableDate] = report.Date.Date; + row[Resources.StrTableCordonelPcbId] = report.PcbId; + + row[Resources.StrTableCordonelUpdateOrder] = report.OrderNr; + row[Resources.StrTableCordonelProductionPos] = report.OrderPos; + + var userName = "?"; + foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Where(user => user.Id == report.UserId)) + { + userName = user.FullName; + break; + } + + row[Resources.StrTableUserFullName] = userName; + row[Resources.StrTableUpdateOperatorId] = report.UserId; + + _dataTableReportFiles.Rows.Add(row); + } + + gridViewFwUpdateReportSelection.DataSource = _dataTableReportFiles; + + foreach (DataGridViewColumn column in gridViewFwUpdateReportSelection.Columns) + { + column.SortMode = DataGridViewColumnSortMode.Automatic; + } + } + catch (Exception) + { + _processState = ProcessState.Error; + } + finally + { + grpLanguageSelection.Enabled = true; + } + } + + #endregion --------------------------------------- Data Grid Report Files -------------------------------------- + #region ------------------------------------------ Data Grid Pre Build Summary -------------------------------- /// /// Overwrite cell click, because edit of cells is denied (read only == true). This is needed for @@ -3559,7 +3872,7 @@ if (fwUpdateSafe.License == null) //} // color the results of the compare - UpdateUpdateOperatorsInformationStyleSet(); + UpdateOperatorsInformationStyleSet(); } catch (Exception) { @@ -3631,7 +3944,7 @@ if (fwUpdateSafe.License == null) } // color the results of the compare - UpdateUpdateOperatorsInformationStyleSet(); + UpdateOperatorsInformationStyleSet(); } catch (Exception) { @@ -3649,7 +3962,7 @@ if (fwUpdateSafe.License == null) /// /// - Initial. /// - private void UpdateUpdateOperatorsInformationStyleSet() + private void UpdateOperatorsInformationStyleSet() { Thread.CurrentThread.CurrentUICulture = _cultureInfo; Thread.CurrentThread.CurrentCulture = _cultureInfo; @@ -3677,7 +3990,7 @@ if (fwUpdateSafe.License == null) /// private void gridViewUpdateOperators_Sorted(Object sender, EventArgs e) { - UpdateUpdateOperatorsInformationStyleSet(); + UpdateOperatorsInformationStyleSet(); } #endregion --------------------------------------- Data Grid Controls Update Operators ------------------------ @@ -3833,7 +4146,7 @@ if (fwUpdateSafe.License == null) } var initialSortColumn = gridViewCustomerSelection.Columns[Resources.StrTableCustomerName]; - if (initialSortColumn != null) + if (initialSortColumn != null) gridViewCustomerSelection.Sort(initialSortColumn, ListSortDirection.Ascending); } catch (Exception) @@ -3859,10 +4172,10 @@ if (fwUpdateSafe.License == null) /// /// - Getting orders directly from DB. /// - private Boolean GetAllCordonelOrdersOfCustomerFromDb() + private void GetAllCordonelOrdersOfCustomerFromDb() { // get the customer ID - if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text)) return false; + if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text)) return; if (Int64.TryParse(lblCustomerNumber.Text, out var customerId)) { @@ -3870,14 +4183,11 @@ if (fwUpdateSafe.License == null) } _processState = ProcessState.Idle; - return _fwUpdateDbAccess?.DbCordonelCustomerOrders != null && - _fwUpdateDbAccess.DbCordonelCustomerOrders.Count > 0; } /// /// Get the Cordonel serial numbers from DB. /// - /// true if successful /// /// - Initial. /// @@ -3893,10 +4203,10 @@ if (fwUpdateSafe.License == null) /// /// - Clear search info on new search. /// - private Boolean GetAllCordonelSerialNumbersOfOrderFromDb() + private void GetAllCordonelSerialNumbersOfOrderFromDb() { // get the customer ID - if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text)) return false; + if (_fwUpdateDbAccess == null || string.IsNullOrEmpty(lblCustomerNumber.Text)) return; // remove last search infos _cordonelProductionSearchInfos.Clear(); @@ -3966,47 +4276,48 @@ if (fwUpdateSafe.License == null) }// orders from customer could be acquired _processState = ProcessState.Idle; - return _cordonelProductionSearchInfos.Count > 0; } /// /// Get the Cordonel customers from DB. /// - /// true if successful /// /// - Initial. /// /// /// - Search pattern added. /// - private Boolean GetAllCordonelCustomersFromDb() + private void GetAllCordonelCustomersFromDb() { var searchPattern = tbxCustomerSearchMask.Text.Replace(" ", ""); - var returnValue = _fwUpdateDbAccess != null && - _fwUpdateDbAccess.GetAllCordonelCustomersFromDb(searchPattern) && - _fwUpdateDbAccess.DbSearchedCordonelCustomers.Count > 0; + _fwUpdateDbAccess?.GetAllCordonelCustomersFromDb(searchPattern); _processState = ProcessState.Idle; - return returnValue; } /// /// Get Cordonel FW packages from DB end extract all needed information to select a package to the /// CordonelFwPackageInfo search list. /// - /// true if successful /// /// - Initial. /// /// /// - Meter FW update ruler. /// - private Boolean GetCordonelFwPackagesFromDb() + /// + /// - Configuration files loading from DB: - MeterFwUpdateRuler, configuration.json and MeterEraseRestore. + /// + private void GetCordonelFwPackagesFromDb() { if (_fwUpdateDbAccess == null || !_fwUpdateDbAccess.GetAllCordonelFwInfoFilesFromDb() || _fwUpdateDbAccess.DbCordonelFwPackages.Count == 0 || _cordonelFwPackageInfoSearch == null) - return false; + return; _cordonelFwPackageInfoSearch.Clear(); + // The configuration files contain the latest MeterFwUpdateRuler.json (needed for the FwUpdateBuilder), + // the latest configuration.json and the latest MeterEraseRestore.json (needed for the FwUpdateSw). + // GetConfigurationFilesFromDb(); + // Start with the last package, as this will be the latest for (var idx = _fwUpdateDbAccess.DbCordonelFwPackages.Count - 1; idx > _fwUpdateDbAccess.DbCordonelFwPackages.Count - 40; idx--) @@ -4020,71 +4331,72 @@ if (fwUpdateSafe.License == null) fwPackageFilesInfo != null && fwPackageFilesInfo.Count > 0) { // parse file information - var fwPackInfo = new CordonelFwPackageInfo + if (dbCordonelFwFile.CordonelFwFile_Dn != null) { - ReleaseNameVersion = dbCordonelFwFile.FileName, - Region = dbCordonelFwFile.FileName.Contains("EMEA") ? "EMEA" : "NA", - RadioFrequencyMhz = dbCordonelFwFile.FileName.Contains("433") ? "433" : - dbCordonelFwFile.FileName.Contains("868") ? "868" : "-", - FileIsLatest = dbCordonelFwFile.FileIsLatest, - MeterSize = MeterSizeConverter.ConvertOrderSizeNumberToSizeName( - MeterSizeConverter.ConvertToOrder((MeterSize)dbCordonelFwFile.CordonelFwFile_Dn)), - ReleaseDate = dbCordonelFwFile.FileDate, - ReleaseVersion = $"{nameSplit[nameSplit.Length - 1].Substring(0, 3)}." + - $"{nameSplit[nameSplit.Length - 1].Substring(3, 2)}" - }; - // the release version is always the last element of the name split - foreach (var binfile in fwPackageFilesInfo) - { - // extract metrology version - if (binfile.FileName.Contains("binfile0F_")) + var fwPackInfo = new CordonelFwPackageInfo { - var msb = binfile.FileName.Substring(10, 2); - // remove leading 0 - var msbMsb = msb.Substring(0, 1); - if (msbMsb == "0") msb = msb.Remove(0, 1); - var lsb = binfile.FileName.Substring(12, 2); - fwPackInfo.MetrologyVersion = $"{msb}.{lsb}"; - break; - } - } - // take the meter fw update ruler to extract core min /max and released - foreach (var rule in _meterFwUpdateRuler) - { - var releaseVersion = $"{rule.Release.Substring(0, 3)}." + - $"{rule.Release.Substring(3, 2)}"; - if (releaseVersion == fwPackInfo.ReleaseVersion) + ReleaseNameVersion = dbCordonelFwFile.FileName, + Region = dbCordonelFwFile.FileName.Contains("EMEA") ? "EMEA" : "NA", + RadioFrequencyMhz = dbCordonelFwFile.FileName.Contains("433") ? "433" : + dbCordonelFwFile.FileName.Contains("868") ? "868" : "-", + FileIsLatest = dbCordonelFwFile.FileIsLatest, + MeterSize = MeterSizeConverter.ConvertOrderSizeNumberToSizeName( + MeterSizeConverter.ConvertToOrder((MeterSize)dbCordonelFwFile.CordonelFwFile_Dn)), + ReleaseDate = dbCordonelFwFile.FileDate, + ReleaseVersion = $"{nameSplit[nameSplit.Length - 1].Substring(0, 3)}." + + $"{nameSplit[nameSplit.Length - 1].Substring(3, 2)}" + }; + // the release version is always the last element of the name split + foreach (var binfile in fwPackageFilesInfo) { - Int32.TryParse(rule.CoreVersionMin, out var x); - fwPackInfo.CoreVersionMin = x; - x = 0; - Int32.TryParse(rule.CoreVersionMax, out x); - fwPackInfo.CoreVersionMax = x; - fwPackInfo.FwIsReleased = !string.IsNullOrEmpty(rule.ApproverName); + // extract metrology version + if (binfile.FileName.Contains("binfile0F_")) + { + var msb = binfile.FileName.Substring(10, 2); + // remove leading 0 + var msbMsb = msb.Substring(0, 1); + if (msbMsb == "0") msb = msb.Remove(0, 1); + var lsb = binfile.FileName.Substring(12, 2); + fwPackInfo.MetrologyVersion = $"{msb}.{lsb}"; + break; + } + } + // take the meter fw update ruler to extract core min /max and released + foreach (var rule in _meterFwUpdateRuler) + { + var releaseVersion = $"{rule.Release.Substring(0, 3)}." + + $"{rule.Release.Substring(3, 2)}"; + if (releaseVersion == fwPackInfo.ReleaseVersion) + { + int.TryParse(rule.CoreVersionMin, out var x); + fwPackInfo.CoreVersionMin = x; + int.TryParse(rule.CoreVersionMax, out x); + fwPackInfo.CoreVersionMax = x; + fwPackInfo.FwIsReleased = !string.IsNullOrEmpty(rule.ApproverName); + } } - } - _cordonelFwPackageInfoSearch.Add(fwPackInfo); + _cordonelFwPackageInfoSearch.Add(fwPackInfo); + } } } - return _cordonelFwPackageInfoSearch.Count > 0; } /// /// Get the license information from DB. In DEBUG mode the license of the software will be skipped, /// but user license is of importance. /// - /// true if successful /// /// - Initial. /// - private Boolean GetLicenseFromDb() + private void GetLicenseFromDb() { // FW-Update Builder validation with DB access var access = false; var msg = $"{Resources.StrStartMessageSwLicenseExpired}\n\n{_versionString}"; try { + // returns true in DEBUG configuration access = Xylem.Common.Logic.SoftwareAccessHelper.Access.HasAccess(_assemblyName); } catch (Exception) @@ -4102,7 +4414,6 @@ if (fwUpdateSafe.License == null) _licenseUnchecked = false; CheckUserRegistration(); - return true; } /// @@ -4118,10 +4429,168 @@ if (fwUpdateSafe.License == null) return _fwUpdateDbAccess != null && _fwUpdateDbAccess.UploadFwUpdateSafeToDb(_fwUpdateSafeDb, pcbIds); } + /// + /// Get the content of one selected FW update report from DB. + /// + /// report filled with content + /// + /// + /// + /// + /// + /// true if text is set with valid content + /// + /// - Initial. + /// + private Boolean GetOneSelectedReportFromDb(out FwUpdateReportDb reportDb, Int64 pcbId, Int32 userId, Int64 orderNo, + Int64 position, DateTimeOffset dateTime) + { + reportDb = null; + // The DB access will load a list of all reports assigned to the input. + if (_fwUpdateDbAccess == null || + !_fwUpdateDbAccess.DownloadFwUpdateReportsFromDb(out var fwUpdateReports, pcbId, userId, orderNo)) + { + return false; + } + + //The order number has to be extracted and the date has to match! + foreach (var report in fwUpdateReports.Where(report => report.Date == dateTime && + report.OrderPos == position)) + { + reportDb = report; + break; + } + + return reportDb != null; + } + /// + /// Get one selected FW update report from DB and display it. + /// + /// + /// - Initial. + /// + private void GetAndDisplaySingleReportFromDb() + { + //open rich text view with report details + if (_frmFwUpdateReport == null) return; + Invoke(new Action(() => + { + _frmFwUpdateReport.rtbHistory?.Clear(); + _frmFwUpdateReport.Show(); + })); + + if (!GetOneSelectedReportFromDb(out var reportDb, _selectedReport.PcbId, _selectedReport.UserId, + _selectedReport.OrderNr, _selectedReport.OrderPos, _selectedReport.Date)) return; + + //open rich text view with report details + Invoke(new Action(() => + { + if (_frmFwUpdateReport.rtbHistory != null) + { + _frmFwUpdateReport.ApplyLabels(reportDb, _cultureInfo); + _frmFwUpdateReport.rtbHistory.AppendText(reportDb.Content); + var fwIsUpToDate = false; + foreach (var searchString in FwUpdateConfig.FirmwareUpToDateSearchStrings) + { + if (reportDb.Content.Contains(searchString)) fwIsUpToDate = true; + } + + _frmFwUpdateReport.rtbHistory.ForeColor = fwIsUpToDate ? ColorSuccess : ColorProcessFailed; + _frmFwUpdateReport.rtbHistory.ScrollToCaret(); + } + + })); + } + /// + /// Search "Firmware is up to date!" string in file to guarantee the successfully execution of the update + /// process. Get success string for all language settings! + /// + /// + /// - Initial + /// + private Boolean IsSuccessStringInFile(String fileNamePath) + { + try + { + // Get search strings from resources StrFwUpToDateMessage from ServiceFwUpdateSw + var fileLines = File.ReadAllLines(fileNamePath); + var fwIsUpToDate = false; + foreach (var searchString in FwUpdateConfig.FirmwareUpToDateSearchStrings) + { + if (fileLines.Any(line => line.Contains(searchString))) fwIsUpToDate = true; + } + + return fwIsUpToDate; + } + catch (Exception) + { + return false; + } + } + + /// + /// Get all FW update report files from DB. Loading only the preview (readContent = false as default) to speed up + /// the access, as the content will only be needed on inspection of the report. + /// + /// + /// - Initial. + /// + private void GetReportsFromDb() + { + if (_fwUpdateDbAccess == null) return; + + _fwUpdateReports.Clear(); + // if the users are not acquired, get these first + if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null || + _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count == 0) + { + GetAllUpdateOperatorsFromDb(); + } + + if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null) return; + foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators) + { + var fwUpdateReportsOfUser = new List(); + _fwUpdateDbAccess?.DownloadFwUpdateReportsFromDb(out fwUpdateReportsOfUser, userId: user.Id); + _fwUpdateReports.AddRange(fwUpdateReportsOfUser); + } + } + + /// + /// Get all active FW update safes from DB. Outdated safes cannot be accessed. + /// + /// + /// - Initial. + /// + private void GetFwUpdateSafesInfosFromDb() + { + if (_fwUpdateDbAccess == null) return; + + _fwUpdateSafesInfos.Clear(); + // if the users are not acquired, get these first + if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null || + _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count == 0) + { + GetAllUpdateOperatorsFromDb(); + } + + if (_fwUpdateDbAccess.DbFullQualifiedUpdateOperators == null) return; + foreach (var user in _fwUpdateDbAccess.DbFullQualifiedUpdateOperators) + { + _fwUpdateDbAccess.ListAllFwUpdateSafesOfUserFromDb(user.Id, out var fwUpdateSafesOfUser); + + foreach (var safe in fwUpdateSafesOfUser) + { + var pcbIdsOfSafe = _fwUpdateDbAccess.GetFwUpdateSafePcbIdsFromDb(safe.ContainerId); + var fwUpdateSafe = safe; + fwUpdateSafe.PcbIds = pcbIdsOfSafe; + _fwUpdateSafesInfos.Add(fwUpdateSafe); + } + } + } /// /// Get the full qualified user information from DB to generate the primary key for encryption. /// - /// true if successful /// /// - Initial. /// @@ -4134,10 +4603,9 @@ if (fwUpdateSafe.License == null) /// /// - Removed DB status. /// - private Boolean GetAllUpdateOperatorsFromDb() + private void GetAllUpdateOperatorsFromDb() { - return _fwUpdateDbAccess != null && _fwUpdateDbAccess.GetAllUpdateOperatorsFromDb() && - _fwUpdateDbAccess.DbFullQualifiedUpdateOperators.Count > 0; + _fwUpdateDbAccess?.GetAllUpdateOperatorsFromDb(); } /// @@ -4146,7 +4614,6 @@ if (fwUpdateSafe.License == null) /// HW Id, the domain, the LogInName and the users password hash. /// The user registration has to be done in advance in the FW-Update Loader! /// - /// true if successful /// /// - Initial. /// @@ -4156,18 +4623,16 @@ if (fwUpdateSafe.License == null) /// /// - Replaced userInfo by name of update operator. /// - private Boolean BuildPrimaryKey(String updateOperator) + private void BuildPrimaryKey(String updateOperator) { if (_fwUpdateDbAccess == null || !_fwUpdateDbAccess.GetFullQualifiedUserByFullName(updateOperator, out var userInfo)) { - return false; + return; } _primaryKey = FwUpdateCrypt.BuildPrimaryKey(userInfo.HardwareId, userInfo.Domain, userInfo.LogInName, userInfo.PasswordHash); - return true; - } /// @@ -4216,6 +4681,137 @@ if (fwUpdateSafe.License == null) return false; } + /// + /// Get Cordonel Fa update configuration files from DB. + /// The configuration files contain the latest MeterFwUpdateRuler.json (needed for the FwUpdateBuilder), + /// the latest configuration.json and the latest MeterEraseRestore.json (needed for the FwUpdateSw). + /// Copies the MeterFwUpdateRuler.json to the [exe-root] or [exe-root]/Library of the FwUpdateBuilder. + /// + /// + /// - Initial. + /// + private void GetFwUpdateConfigFilesFromDb() + { + if (_fwUpdateDbAccess == null || + !_fwUpdateDbAccess.DownloadFwUpdateConfigurationFilesFromDb() || + _fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0) + return; + + try + { + // extract the MeterFwUpdateRuler + foreach (var f in _fwUpdateDbAccess.DbFwUpdateConfigFiles) + { + if (f.FileName == FwUpdateConfig.MeterFwUpdateRulerConfigFileName) + { + // Copy MeterFwUpdateRuler either to exe-path or if existing to Library-subfolder + var fwUpdateBuilderExePath = AppDomain.CurrentDomain.BaseDirectory; + var fwUpdateBuilderLibraryPath = Path.Combine(fwUpdateBuilderExePath, + FwUpdateConfig.LibrarySubFolderName); + + // check the Library path existence (will be used in Release build) + var meterFwUpdateRulerPath = Directory.Exists(fwUpdateBuilderLibraryPath) ? + fwUpdateBuilderLibraryPath : fwUpdateBuilderExePath; + + var sourceFile = Path.Combine(meterFwUpdateRulerPath, f.FileName); + var fs = File.Open(sourceFile, FileMode.Create); + fs.Write(f.FileContent, 0, f.FileContent.Length); + fs.Close(); + } + } + } + + catch (Exception) + { + // nothing to do + } + } + + /// + /// Get Cordonel SW and configuration files from DB. + /// The software is a container of dll files, language packages and logging setups. + /// The configuration files contain the latest MeterFwUpdateRuler.json (needed for the FwUpdateBuilder), + /// the latest configuration.json and the latest MeterEraseRestore.json (needed for the FwUpdateSw). + /// Creates License, FileCrc, FileLength and SubDiractories. + /// + /// license information of valid software + /// true if successful + /// + /// - Initial. + /// + private Boolean BuildFwUpdateSwContainerFromDb(SoftwareLicense fwUpdateSwLicense) + { + if (_fwUpdateDbAccess?.DbFwUpdateConfigFiles == null || + _fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0) + GetFwUpdateConfigFilesFromDb(); + + if (_fwUpdateDbAccess?.DbFwUpdateConfigFiles == null || + !_fwUpdateDbAccess.DownloadFwUpdateSwContainerFromDb() || + _fwUpdateDbAccess.DbFwUpdateSwPackage.Count == 0 || + _fwUpdateDbAccess.DbFwUpdateConfigFiles.Count == 0) + return false; + + _fwUpdateSwContainer = new SoftwareContainer + { + Major = fwUpdateSwLicense.Major, + Minor = fwUpdateSwLicense.Minor, + Build = fwUpdateSwLicense.Build, + Program = fwUpdateSwLicense.Program, + SoftwareDynLinkLibs = new List(), + RegisterDefinitionFile = new FilePart(), + SoftwareSetupFile = new FilePart(), + MeterFilesEraseRestore = new FilePart() + }; + + foreach (var f in _fwUpdateDbAccess.DbFwUpdateConfigFiles) + { + // load the register definition + if (f.FileName == ProgramConfig.RegisterDefinitionFileName) + { + f.FileContentLength = f.FileContent.Length; + f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent); + _fwUpdateSwContainer.RegisterDefinitionFile = f; + } + + // load the meter files to erase and restore + if (f.FileName == FwUpdateConfig.MeterFilesEraseRestoreConfigFileName) + { + f.FileContentLength = f.FileContent.Length; + f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent); + _fwUpdateSwContainer.MeterFilesEraseRestore = f; + } + } + + foreach (var f in _fwUpdateDbAccess.DbFwUpdateSwPackage) + { + // load the logging configuration + if (f.FileName == ProgramConfig.NlogConfig) + { + f.FileContentLength = f.FileContent.Length; + f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent); + _fwUpdateSwContainer.SoftwareSetupFile = f; + } + // load the DLLs + if (f.FileName.EndsWith(".dll")) + { + // extract sub-directory from file name in DB for sub-directory creation in FwUpdateLoader + // supports only depth of one level + if (f.FileName.Contains("\\")) + { + var fileName = f.FileName.Split('\\'); + var subDirectory = fileName[0]; + f.FileName = fileName[fileName.Length - 1]; + f.SubDirectory = subDirectory; + } + + f.FileContentLength = f.FileContent.Length; + f.FileContentCrc16CcittMsb = Crc16Ccitt.CalculateMsb1021(f.FileContent); + _fwUpdateSwContainer.SoftwareDynLinkLibs.Add(f); + } + } + return true; + } + /// /// Build the FW-Update SW container /// @@ -4232,6 +4828,7 @@ if (fwUpdateSafe.License == null) /// /// - Take license from DB. /// + // ReSharper disable once UnusedMember.Local private Boolean BuildFwUpdateSwContainer(SoftwareLicense fwUpdateSwLicense) { _fwUpdateSwContainer = new SoftwareContainer @@ -4247,7 +4844,7 @@ if (fwUpdateSafe.License == null) }; try { - //TODO THW for debug purposes the locally values are taken + // for debug purposes the locally stored files from download folder are taken // copy all elements of software release in the main directory var fileList = new List(); @@ -4359,13 +4956,13 @@ if (fwUpdateSafe.License == null) /// /// - Modified for flexible licenses. /// - private Boolean SetFwUpdateSwLicenseToDb(SoftwareLicense license) + private void SetFwUpdateSwLicenseToDb(SoftwareLicense license) { if (_fwUpdateDbAccess != null && _fwUpdateDbAccess.SetSwLicenseToDb(license)) { LogSuccessText($"{Resources.StrSwLicenseSetSuccessfully} {license.Program} " + $"{license.Major}.{license.Minor}.{license.Build}"); - return true; + return; } if (_fwUpdateDbAccess != null && !_fwUpdateDbAccess.DbIsConnected) @@ -4383,7 +4980,6 @@ if (fwUpdateSafe.License == null) MessageBoxShow(Resources.StrSwLicenseSetFailed, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error); } - return false; } /// @@ -4403,14 +4999,14 @@ if (fwUpdateSafe.License == null) /// /// - Messages removed. /// - private Boolean GetFwUpdateSwLicenseFromDb(String programName, out SoftwareLicense license) + private void GetFwUpdateSwLicenseFromDb(String programName, out SoftwareLicense license) { if (_fwUpdateDbAccess != null && - _fwUpdateDbAccess.GetSwLicenseFromDb(programName, out license)) return true; + _fwUpdateDbAccess.GetSwLicenseFromDb(programName, out license)) + return; license = null; - return false; } /// @@ -4498,84 +5094,6 @@ if (fwUpdateSafe.License == null) return false; } - ///// - ///// Load firmware package from local HDD. - ///// - ///// - ///// true if succeeded - ///// - ///// - Initial. - ///// - ///// - ///// - Returns bool. - ///// - ///// - ///// - Logging added. - ///// - //private Boolean LoadFirmwarePackage(String releaseNameVersion) - //{ - // // if this packages has already been loaded, exit immediately - // if (_fwUpdatePackages.Any(version => version.ReleaseNameVersion == releaseNameVersion)) - // { - // return true; - // } - - // var cordonelFwPackage = new CordonelFirmware - // { - // ReleaseNameVersion = releaseNameVersion, - // PackageDescriptionFile = new FilePart(), - // BinaryApplicationFiles = new List() - // }; - - // try - // { - // // copy all firmware releases which later will be the "Cordonel Firmware" container - // var files = Directory.GetFiles(FwUpdateFwSourceFolder + releaseNameVersion); - // if (files.Length == 0) - // { - // var msg = Resources.StrFwPackageLoadFailed + @" " + releaseNameVersion; - // LogErrorText(msg); - // MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error); - // return false; - // } - - // foreach (var f in files) - // { - // // extract the file name - // var fileName = Path.GetFileName(f); - // // load the ADF - // if (f.Contains("product") && f.EndsWith(".txt")) - // { - // cordonelFwPackage.PackageDescriptionFile.FileName = fileName; - // var file = File.ReadAllBytes(f); - // cordonelFwPackage.PackageDescriptionFile.FileContent = new Byte[file.Length]; - // cordonelFwPackage.PackageDescriptionFile.FileContent = file; - // } - // // load the binaries - // if (f.Contains("binfile") && f.EndsWith(".bin")) - // { - // var filePart = new FilePart { FileName = fileName }; - // var file = new List(File.ReadAllBytes(f)); - // filePart.FileContent = new Byte[file.Count]; - // filePart.FileContent = file.ToArray(); - // cordonelFwPackage.BinaryApplicationFiles.Add(filePart); - // } - // } - // _fwUpdatePackages.Add(cordonelFwPackage); - // LogSuccessText(Resources.StrFwPackageLoadSuccess + " " + releaseNameVersion); - // } - // catch (Exception e) - // { - // var msg = Resources.StrFwPackageLoadFailed + @" " + releaseNameVersion; - // LogErrorText(msg); - // MessageBoxShow(msg, Resources.StrError, MessageBoxButtons.OK, MessageBoxIcon.Error); - // MessageBoxShow(e.ToString(), Resources.StrError, MessageBoxButtons.OK, - // MessageBoxIcon.Error); - // _processState = ProcessState.Error; - // return false; - // } - // return true; - //} #endregion --------------------------------------- Load DB Contents ------------------------------------------- #region ------------------------------------------ Language --------------------------------------------------- @@ -4683,6 +5201,8 @@ if (fwUpdateSafe.License == null) _customersPropertyChanged = true; _cordonelsPropertyChanged = true; _fwPackagePropertyChanged = true; + _fwReportsPropertyChanged = true; + _fwUpdateSafesPropertyChanged = true; _preBuildSummaryPropertyChanged = true; lblFwUpdateDutyDate.Text = _datePicker.Value.ToShortDateString(); diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.resx index a9053e67..b6c3d6ee 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.resx +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.resx @@ -1684,6 +1684,105 @@ 5 + + 1 + + + 2 + + + Fill + + + 0, 0 + + + 0, 0, 0, 0 + + + 1 + + + 986, 31 + + + 0 + + + tblPanelFwUpdateSafeSearch + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tblFwUpdateSafeSelection + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls /><Columns Styles="Percent,50,Percent,50" /><Rows Styles="Percent,50" /></TableLayoutSettings> + + + Fill + + + 0, 31 + + + 0, 0, 0, 0 + + + 986, 390 + + + 1 + + + gridViewFwUpdateSafeSelection + + + System.Windows.Forms.DataGridView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tblFwUpdateSafeSelection + + + 1 + + + Fill + + + 3, 3 + + + 0, 0, 0, 0 + + + 2 + + + 986, 421 + + + 0 + + + tblFwUpdateSafeSelection + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPageFwUpdateSafes + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="tblPanelFwUpdateSafeSearch" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="gridViewFwUpdateSafeSelection" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100" /><Rows Styles="Absolute,31,Percent,100" /></TableLayoutSettings> + 4, 22 @@ -1711,6 +1810,105 @@ 6 + + 1 + + + 2 + + + Fill + + + 0, 0 + + + 0, 0, 0, 0 + + + 1 + + + 986, 31 + + + 0 + + + tblPanelFwUpdateReportsSearch + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tblPanelFwUpdateReports + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls /><Columns Styles="Percent,50,Percent,50" /><Rows Styles="Percent,50" /></TableLayoutSettings> + + + Fill + + + 0, 31 + + + 0, 0, 0, 0 + + + 986, 390 + + + 1 + + + gridViewFwUpdateReportSelection + + + System.Windows.Forms.DataGridView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tblPanelFwUpdateReports + + + 1 + + + Fill + + + 3, 3 + + + 0, 0, 0, 0 + + + 2 + + + 986, 421 + + + 0 + + + tblPanelFwUpdateReports + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPageReports + + + 0 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="tblPanelFwUpdateReportsSearch" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="gridViewFwUpdateReportSelection" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100" /><Rows Styles="Absolute,31,Percent,100" /></TableLayoutSettings> + 4, 22 diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.Designer.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.Designer.cs new file mode 100644 index 00000000..b70ad7b6 --- /dev/null +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.Designer.cs @@ -0,0 +1,179 @@ +namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder +{ + partial class FrmHistory + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmHistory)); + this.rtbHistory = new System.Windows.Forms.RichTextBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.picBoxLogo = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.lblPcbIdLabel = new System.Windows.Forms.Label(); + this.lblDateLabel = new System.Windows.Forms.Label(); + this.lblOperatorIdLabel = new System.Windows.Forms.Label(); + this.lblPcbId = new System.Windows.Forms.Label(); + this.lblDate = new System.Windows.Forms.Label(); + this.lblOperatorId = new System.Windows.Forms.Label(); + this.lblOrder = new System.Windows.Forms.Label(); + this.lblCustomerName = new System.Windows.Forms.Label(); + this.lblCustomerLabel = new System.Windows.Forms.Label(); + this.lblOrderLabel = new System.Windows.Forms.Label(); + this.tableLayoutPanel1.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picBoxLogo)).BeginInit(); + this.tableLayoutPanel3.SuspendLayout(); + this.SuspendLayout(); + // + // rtbHistory + // + resources.ApplyResources(this.rtbHistory, "rtbHistory"); + this.rtbHistory.Name = "rtbHistory"; + this.rtbHistory.TextChanged += new System.EventHandler(this.rtbHistory_TextChanged); + // + // tableLayoutPanel1 + // + resources.ApplyResources(this.tableLayoutPanel1, "tableLayoutPanel1"); + this.tableLayoutPanel1.Controls.Add(this.rtbHistory, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + // + // tableLayoutPanel2 + // + resources.ApplyResources(this.tableLayoutPanel2, "tableLayoutPanel2"); + this.tableLayoutPanel2.Controls.Add(this.picBoxLogo, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.tableLayoutPanel3, 0, 0); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + // + // picBoxLogo + // + resources.ApplyResources(this.picBoxLogo, "picBoxLogo"); + this.picBoxLogo.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + this.picBoxLogo.Name = "picBoxLogo"; + this.picBoxLogo.TabStop = false; + // + // tableLayoutPanel3 + // + resources.ApplyResources(this.tableLayoutPanel3, "tableLayoutPanel3"); + this.tableLayoutPanel3.Controls.Add(this.lblPcbIdLabel, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.lblDateLabel, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.lblOperatorIdLabel, 0, 2); + this.tableLayoutPanel3.Controls.Add(this.lblPcbId, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.lblDate, 1, 1); + this.tableLayoutPanel3.Controls.Add(this.lblOperatorId, 1, 2); + this.tableLayoutPanel3.Controls.Add(this.lblOrder, 4, 0); + this.tableLayoutPanel3.Controls.Add(this.lblCustomerName, 4, 2); + this.tableLayoutPanel3.Controls.Add(this.lblCustomerLabel, 3, 2); + this.tableLayoutPanel3.Controls.Add(this.lblOrderLabel, 3, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + // + // lblPcbIdLabel + // + resources.ApplyResources(this.lblPcbIdLabel, "lblPcbIdLabel"); + this.lblPcbIdLabel.Name = "lblPcbIdLabel"; + // + // lblDateLabel + // + resources.ApplyResources(this.lblDateLabel, "lblDateLabel"); + this.lblDateLabel.Name = "lblDateLabel"; + // + // lblOperatorIdLabel + // + resources.ApplyResources(this.lblOperatorIdLabel, "lblOperatorIdLabel"); + this.lblOperatorIdLabel.Name = "lblOperatorIdLabel"; + // + // lblPcbId + // + resources.ApplyResources(this.lblPcbId, "lblPcbId"); + this.lblPcbId.Name = "lblPcbId"; + // + // lblDate + // + resources.ApplyResources(this.lblDate, "lblDate"); + this.lblDate.Name = "lblDate"; + // + // lblOperatorId + // + resources.ApplyResources(this.lblOperatorId, "lblOperatorId"); + this.lblOperatorId.Name = "lblOperatorId"; + // + // lblOrder + // + resources.ApplyResources(this.lblOrder, "lblOrder"); + this.lblOrder.Name = "lblOrder"; + // + // lblCustomerName + // + resources.ApplyResources(this.lblCustomerName, "lblCustomerName"); + this.lblCustomerName.Name = "lblCustomerName"; + // + // lblCustomerLabel + // + resources.ApplyResources(this.lblCustomerLabel, "lblCustomerLabel"); + this.lblCustomerLabel.Name = "lblCustomerLabel"; + // + // lblOrderLabel + // + resources.ApplyResources(this.lblOrderLabel, "lblOrderLabel"); + this.lblOrderLabel.Name = "lblOrderLabel"; + // + // FrmHistory + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.MaximizeBox = false; + this.Name = "FrmHistory"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmHistory_FormClosing); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picBoxLogo)).EndInit(); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.PictureBox picBoxLogo; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + public System.Windows.Forms.RichTextBox rtbHistory; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.Label lblPcbIdLabel; + private System.Windows.Forms.Label lblDateLabel; + private System.Windows.Forms.Label lblOperatorIdLabel; + private System.Windows.Forms.Label lblPcbId; + private System.Windows.Forms.Label lblDate; + private System.Windows.Forms.Label lblOperatorId; + private System.Windows.Forms.Label lblOrderLabel; + private System.Windows.Forms.Label lblCustomerLabel; + private System.Windows.Forms.Label lblOrder; + private System.Windows.Forms.Label lblCustomerName; + } +} \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.cs new file mode 100644 index 00000000..2f32b80d --- /dev/null +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.cs @@ -0,0 +1,58 @@ +using System; +using System.Globalization; +using System.Windows.Forms; +using Xylem.Common.Utils.DateTimeServer; +using Xylem.ServiceFwUpdate.Common.FwUpdateConfig.Consts; +using Xylem.ServiceFwUpdate.Common.FwUpdateDb; + +namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder +{ + /// + /// History display of update process + /// + [Serializable] + public partial class FrmHistory : Form + { + /// + /// Ctor + /// + public FrmHistory() + { + InitializeComponent(); + } + + private void FrmHistory_FormClosing(Object sender, FormClosingEventArgs e) + { + //avoid destroying of object + e.Cancel = true; + //instead just hide it + Hide(); + } + + /// + /// Apply labels + /// + public void ApplyLabels(FwUpdateReportDb report, CultureInfo currentCulture) + { + if (report == null) return; + if (report.FileName != null) + { + var splitName = report.FileName.Split(FwUpdateConfig.FwUpdateFileFieldSeparator); + lblCustomerName.Text = splitName[1]; + } + + lblDate.Text = DateTimeServer.GetDateStringFromDateTimeOffset(report.Date, currentCulture); + lblOperatorId.Text = report.UserId.ToString(); + lblOrder.Text = $@"{report.OrderNr}-{report.OrderPos}"; + lblPcbId.Text = report.PcbId.ToString(); + } + /// + /// Select always the last line for the display. + /// + private void rtbHistory_TextChanged(Object sender, EventArgs e) + { + //rtbHistory.SelectionStart = rtbHistory.Text.Length; + //rtbHistory.ScrollToCaret(); + } + } +} diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de-DE.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de-DE.resx new file mode 100644 index 00000000..7b363d42 --- /dev/null +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de-DE.resx @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 528, 626 + + + 534, 729 + + + 528, 91 + + + + /9j/4AAQSkZJRgABAQEAYABgAAD/4QC8RXhpZgAATU0AKgAAAAgABAESAAMAAAABAAEAAAE7AAIAAAAH + AAAAPodpAAQAAAABAAAARpydAAEAAAAOAAAApgAAAABUaG9tYXMAAAAEkAMAAgAAABQAAAB8kAQAAgAA + ABQAAACQkpEAAgAAAAM1MwAAkpIAAgAAAAM1MwAAAAAAADIwMjE6MDQ6MDEgMTQ6NTk6MjkAMjAyMTow + NDowMSAxNDo1OToyOQAAAFQAaABvAG0AYQBzAAAA/9sAQwACAQECAQECAgICAgICAgMFAwMDAwMGBAQD + BQcGBwcHBgcHCAkLCQgICggHBwoNCgoLDAwMDAcJDg8NDA4LDAwM/9sAQwECAgIDAwMGAwMGDAgHCAwM + DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAIwBkAwEi + AAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAAB + fQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNE + RUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1 + tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEA + AAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRC + kaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpz + dHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ + 2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/fi5vYbML50scW7gb2C5p28Yrzr9qv8AZm0H + 9rX4Map4O8QK0cV0vm2d5GP32nXKg+XOnuMkEfxKWXoa/M7wp8XfjF8ZtT0j9j288SafptxpGsz6Xqvi + SC/3TXWm24LfZlOQX2qrYUHewCIwUK+foMpyOOPpSnCqouDvNNbQt8S11ts1o9j4viTi6eT4mFGrQc1V + Vqbi/iqXSVNpr3b3upXatfS61/XDTdYtNYjZ7O6t7pEbazQyCQKfQkGpZ7iO2TdI6xr6scCvzR8e/BeD + /gkF+2N8M/EnhPVNbPwx8cOND1+G+ufOVJMhWkcgKvAdZV4yDHIB8pxXoP8AwWD12++NPxH+EPwF0W4e + O78aaumo6kY/vQ26Exo5/wBkAzuf+uINbx4djUxFKNGrelUTlztWso35rq+6t36o4ZccVKOCxM8Vh+XE + UJRg6alfmc7ez5Zcq0lf+W6s9NDU8P8AjTVpv+C4mtaP/a+pPoi+EFnSx+1ubQN5EB3iPOzPJOcdz619 + rX+pW+lW7TXU8NtCvWSVwij8TxXwZ8PPD9p4V/4Ll32lWEIt7HTfAkNpbRDpFEltbKq/gABXzx8Uv2g/ + AP7UH7afju5+PHiTxZb+B/B9/Jpnh7w9pEE8kMvlyvGXkMYO0nZuY8MxkADBUxXq18jePqUuRtRhRpt2 + jeTvokordv1surPncLxcsnoYj2iUqlXFVoxUp8sFazblNp2iulk220kj9fLS9h1C3Wa3ljmhkGVeNgys + PYjg1FqWs2ejRq15dW9qrnarTSCMMfQZNfll+w9+0B4Z+B/7f+ieEfhL4h8Va18JfH0fkXGm6xbyxnSr + 0rIVMe8DOGRPnAGVkKtkoGrpPA37Pen/APBTL/goB8cIviVrGvT6P8PLs6To+n2V15MdsnnSwqRkEDAh + LEAfM8hJz0PFW4WVCrJ4io40owU78vvWb5UuW+jvvrbqevhfESWLoU44Ogp151JUuX2i5LxjzuSqKLvH + l1Xu3vpbQ/Si/wBbs9Kije6u7a2SU4RpZVQOfbJ5q0GzX5I/sI/sD6L+138T/ip4Z8feKPFuraX8Kbk+ + HtDRL8r5Cme5XzAG3BQPJyEUBcuc54r6W/4Id/ErXPFPwA8WeG9Z1G51aLwT4gk07T57hy8iQFFYR5JJ + 2qwYgZ4DY6AVlmnDlLC0qk6VbnlT5eZctlaesWnd36XVjp4d44xGY4ihTxGF9lCuqnI+dSd6TtNSXKrK + 97O7vbbU+2KKKK+VP0QKKKKAPF/23o/jJqHwyt9O+C8eix65qk7Wt9e6hMIm063ZGHnQknHmBsc7Wx1A + zXzH4p/4IxN4U/ZZ0RvCGqhfjj4bvf7dXX0nMX9oXZIZoPMblUXapjZv4lJOPMav0ExmivawOfYrCU40 + 8PaKTu9NZeUu6s2rbanyubcH5fmdedfHc03KPKk3pDZuUF9mTaT5tXp20PmD45fs1+Mv24f2Dm8J/EDT + NN8N/EiFUuInjuUntBfQZCzK0edscyllK4ynmNwcDPzp/wAEkPD3ij9o39q7xP8AFDx1dW+qXnw70mDw + jYXUDb4ZZlUxGRHyQxESOWYcMbndxnFfY/7Z/wAGPiL8c/h5a6H8PPHUXgKa4mePVLprbznubV4ypjQg + blbJzlSp9xWj+x1+ynof7G3wQsPBmiTS33kyNdX19KgSS/uXxvlKjIUYVVC5OFVRknJPpUc4jSyurSUo + 81Rvlik/cTfv6vZSSSSTfc+fxPC88TxDhsQ4S9nQinOcpL97KK/d6LeUHKTcmlrojwP9oj9k74weG/8A + goHpvxo+Fo8N6pb6lYQaVqtnqcvltbRDakpUEqGBjVWUhtwYEEEdcz4i/safGL9mb9p7xN8SPgK/hnXN + L8dyfaNb8M623lIJyxdnRiVBXczspDqy+Yy4YV9C+If2k1+HVz8UtQ16EyaL4EurG3tks4d1zcG4trdw + hy20s00wUH5QARnoTXJ3X7Y3iPxnfX2neG/A2qWdxZ6LNq0s+oqskkZt7wQ3EUdujb7gmMMYmQ7ZHZFy + o3EVh8wzFxguSDioqDutJRspJS11cbppqzRONyfI1UqN1akakqkqi5W+aE7yhJw912U2mmpXi7bKxnfs + peGP2kNa+L114o+LGoeDdB8Mmza2g8K6TbrORJnKzCUMSjDufMfcONq8EZn7DP7K3jP4G/tXfHjxX4is + bS20Xx5q/wBs0eWK7SZ5o/tFw+WVTlDtkQ4PrXceJP2i/EnxE/Z+0vxV4B0me3urrUzaajbyW8OqX+lw + R+YJitrHcIJZ1ZEBh8wSKGY7Cy7Dy3jz9vqDTvgzq2o6LDdajJDpr2tn4pWzSLS59Y/sr+0Ui+yvKbhE + MWGyylVJ2Fsgms+bHVVVpwpwj7S0GkrcvLJPp1uurbaubKGUYaVCtWrVJujepGU3dzc4OL3V7JPooxi2 + rtN2Mz/gnZ+yn40/Z4+NHxw1rxRY2lpp/jjXxqGkvDdpO00Xn3T5YLyh2yocHnn2rF/YA/ZM+K/7G/x+ + 8b6LdR+HNS+FviW8n1WHU45v9OE2QIVKEgrlCQ4KsMrw3PPpOp/8FBfD2kTW+nroPiC+15pzp89jEsKt + bXgluUEEjGTarPHZ3M65ODEin+NQaXxu/a18S+G7fw7J4X0u1874keH1bwnaazayW9wusG4gXyLld2VU + Q3PmlRggWsxyRitKlbMq1SpCrCK9sknfb3Fo1rdWSvfbdmVHC5DhaNCpQqzf1WUpJxd3+8d5RlpZptqN + lqm0tGz6Oor5d8A/8FFLfX9XgurjSZrzRdaurOx04ae0RuLSV0top2nV5A+wX10LbKptVoJMkkYrT+H/ + APwUSsfEuieHZNT8G+IrO+1TS7bU9RSz8q8h0pLkzeQWZW3MriB2LBcRggvjnHjzyTGR1cPxX9abPz06 + o+npcXZVUaSq73to+jSve1rO913V3snb6PornfhP49k+KPw70nxC+kX+hrrEC3UNpevE06RON0bP5Tuo + LKQ2AxIzg4IIory6kHCThLdH0FGrGpBVIbNXXTR+T1OioooqTQKKKKAON8Rfs8eBfF3iy617VPCeg6hr + F9Aba4u7izSSW4iMZj2OSPmGwlee1OsP2fvA+l2tnDb+E9Bjj0+0ubCBRZp+7t7k5uIunKSHlwchjyc0 + UVt9Yq25eZ29Wcv1HDczn7ON3u7K71v27pP1RDcfs3eAbv4fW/hSTwf4fbw5a3BuodPNmnkxzEsTIBjh + zubLdTuOTyaW6/Zv+H97qzX0vgvwy921h/ZZk/s6LP2XyvJ8np93yv3eP7ny/d4oop/Wq387+99d/vJ/ + s/CO16UdLfZXTbp06dizr/wJ8F+KbTVINQ8L6Hdx63cRXl+JLNM3c0SLHHK5xkuqKqhuoUY6VqP8PtCk + TRFbR9NK+GnEmkg26401hE0IMPH7vEbsny4+ViKKKj21Rqzk/v8AK35aehosLQTclBXfku9/z19dTDuf + 2c/AV3f6bdSeD/DrXGjzSXFlJ9gj3W0kk/2h2U44Jn/eZ/v/ADdeajt/2afh9aX9ndReC/Dcdxp5mNs6 + WEamHzWd5Mcd2kkb2LsRjJooq/rVbbnf3sz/ALPwt7+yj/4CulrdPJfcux2Omabb6Np1vZ2kMdva2saw + wxRrtSJFACqo7AAAAUUUVhvqzsSSVkf/2Q== + + + + 422, 3 + + + 103, 41 + + + 419, 91 + + + 41, 31 + + + Datum: + + + 270, 0 + + + 270, 62 + + + 41, 29 + + + Kunde: + + + 65, 31 + + + Auftrag-Pos: + + + 534, 729 + + + + AAABAAEAICAQAAAAAADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP// + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3d3cAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAA + AAAABwAAAAAAAAAAAAAAAAB3cAcAAAAAAAAAAAAHcHAAd3AHAABwAAAAAAAAdwAHAHhwAAAABwAAAAAA + B3CAAAd4dwAAcABwAAAAAAcIiAd3d3d3B3cABwAAAAAAj4iHf///B3iHcAcAAAAAAAiIiPiIiP8IhwBw + AAAAAAAAiAiIh3d48HAAcAAAAAd3CIiIiAAHd493AHd3cABwAAjwiAB3dwd/BwAAAHAHAACPCIgIAAd3 + ePdwAABwBwiIjwiA8I+AcHj3d3cAcAcI+I8HgPBw8HB494h3AHAHCIiPB4Dwd4BwiPd3dwBwBwAAjweI + /wAICIj3cAAAcAAAAAjweA//8AiPdwBwAAAAAAAI8HeIAAiIiHcAcAAAAAAAAI8HeIiIiAhwAHAAAAAA + AAiP8Ad3iAiIhwAHAAAAAACPiI/wAAD4eIdwBwAAAAAHCPgIj///iAeHAHAAAAAAB3CAAAiIiAAAcAcA + AAAAAAB3AHAAiIAHAABwAAAAAAAAB3cAAI+ABwAHAAAAAAAAAAAAAACIgAcAAAAAAAAAAAAAAAAAAAAH + AAAAAAAAAAAAAAAAB3d3dwAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////wP///8D///+A////gP//4Y + Dn/8AAQ/+AAAH/gAAA/4AAAP/AAAH/4AAB/gAAABwAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB/AAAH/wA + AB/+AAAf/AAAD/gAAA/4AAAf+AAAP/wYDH/+OA7///gP///4D///+A///////w== + + + \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de.resx new file mode 100644 index 00000000..bba31d09 --- /dev/null +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.de.resx @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 428, 673 + + + 434, 729 + + + 434, 729 + + + + AAABAAEAICAQAAAAAADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP// + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3d3cAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAA + AAAABwAAAAAAAAAAAAAAAAB3cAcAAAAAAAAAAAAHcHAAd3AHAABwAAAAAAAAdwAHAHhwAAAABwAAAAAA + B3CAAAd4dwAAcABwAAAAAAcIiAd3d3d3B3cABwAAAAAAj4iHf///B3iHcAcAAAAAAAiIiPiIiP8IhwBw + AAAAAAAAiAiIh3d48HAAcAAAAAd3CIiIiAAHd493AHd3cABwAAjwiAB3dwd/BwAAAHAHAACPCIgIAAd3 + ePdwAABwBwiIjwiA8I+AcHj3d3cAcAcI+I8HgPBw8HB494h3AHAHCIiPB4Dwd4BwiPd3dwBwBwAAjweI + /wAICIj3cAAAcAAAAAjweA//8AiPdwBwAAAAAAAI8HeIAAiIiHcAcAAAAAAAAI8HeIiIiAhwAHAAAAAA + AAiP8Ad3iAiIhwAHAAAAAACPiI/wAAD4eIdwBwAAAAAHCPgIj///iAeHAHAAAAAAB3CAAAiIiAAAcAcA + AAAAAAB3AHAAiIAHAABwAAAAAAAAB3cAAI+ABwAHAAAAAAAAAAAAAACIgAcAAAAAAAAAAAAAAAAAAAAH + AAAAAAAAAAAAAAAAB3d3dwAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////wP///8D///+A////gP//4Y + Dn/8AAQ/+AAAH/gAAA/4AAAP/AAAH/4AAB/gAAABwAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB/AAAH/wA + AB/+AAAf/AAAD/gAAA/4AAAf+AAAP/wYDH/+OA7///gP///4D///+A///////w== + + + + FW-Update Info + + \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.resx new file mode 100644 index 00000000..22b0d6a6 --- /dev/null +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmHistory.resx @@ -0,0 +1,723 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 65, 29 + + + + GrowAndShrink + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0, 0 + + + tableLayoutPanel3 + + + tableLayoutPanel3 + + + MiddleCenter + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Left + + + Order-Pos: + + + NoControl + + + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 74, 31 + + + 255, 0 + + + tableLayoutPanel3 + + + 36 + + + 31 + + + Customer: + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fill + + + 00000000 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Left + + + 35 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="picBoxLogo" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="tableLayoutPanel3" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,79,54546,Percent,20,45455" /><Rows Styles="Percent,100,Absolute,20" /></TableLayoutSettings> + + + FW-Update Report + + + 105, 39 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="lblPcbIdLabel" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="lblDateLabel" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="lblOperatorIdLabel" Row="2" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="lblPcbId" Row="0" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="lblDate" Row="1" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="lblOperatorId" Row="2" RowSpan="1" Column="1" ColumnSpan="1" /><Control Name="lblOrder" Row="0" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="lblCustomerName" Row="2" RowSpan="1" Column="4" ColumnSpan="1" /><Control Name="lblCustomerLabel" Row="2" RowSpan="1" Column="3" ColumnSpan="1" /><Control Name="lblOrderLabel" Row="0" RowSpan="1" Column="3" ColumnSpan="1" /></Controls><Columns Styles="Absolute,71,Absolute,89,Absolute,28,Absolute,79,Absolute,242" /><Rows Styles="Absolute,31,Absolute,31,Absolute,20" /></TableLayoutSettings> + + + Left + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Left + + + 0 + + + 6, 13 + + + lblCustomerName + + + 2 + + + tableLayoutPanel2 + + + 1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel1 + + + 33, 31 + + + tableLayoutPanel3 + + + lblOperatorId + + + 1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel3 + + + 0, 0, 0, 0 + + + 40, 31 + + + lblDate + + + 0 + + + 5 + + + 11 + + + 3, 0 + + + True + + + 54, 29 + + + 13, 29 + + + tableLayoutPanel1 + + + 430, 3 + + + Operator ID: + + + 538, 91 + + + System.Windows.Forms.RichTextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Left + + + Fill + + + Fill + + + + + + tableLayoutPanel3 + + + FrmHistory + + + 4 + + + 3 + + + tableLayoutPanel3 + + + 0 + + + MiddleCenter + + + 57, 31 + + + 82, 31 + + + tableLayoutPanel1 + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + rtbHistory + + + Manual + + + $this + + + Date: + + + 82, 29 + + + <?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls><Control Name="rtbHistory" Row="1" RowSpan="1" Column="0" ColumnSpan="1" /><Control Name="tableLayoutPanel2" Row="0" RowSpan="1" Column="0" ColumnSpan="1" /></Controls><Columns Styles="Percent,100,Absolute,20" /><Rows Styles="Absolute,97,Percent,100,Absolute,111" /></TableLayoutSettings> + + + MiddleCenter + + + Left + + + 1 + + + 191, 0 + + + 1 + + + 54, 31 + + + 55, 31 + + + 3 + + + True + + + 0 + + + Top + + + 427, 91 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 8 + + + MiddleCenter + + + 2 + + + + + + lblOrder + + + tableLayoutPanel2 + + + PcbID: + + + System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + 1 + + + MiddleCenter + + + tableLayoutPanel2 + + + 74, 62 + + + True + + + 255, 62 + + + Customer Name + + + True + + + 3 + + + Left + + + MiddleCenter + + + 9 + + + tableLayoutPanel3 + + + True + + + lblPcbIdLabel + + + 9 + + + 3, 62 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + True + + + MiddleCenter + + + 5 + + + lblOperatorIdLabel + + + 544, 729 + + + Fill + + + 38 + + + 3, 31 + + + lblCustomerLabel + + + + AAABAAEAICAQAAAAAADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP// + AAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3d3cAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAA + AAAABwAAAAAAAAAAAAAAAAB3cAcAAAAAAAAAAAAHcHAAd3AHAABwAAAAAAAAdwAHAHhwAAAABwAAAAAA + B3CAAAd4dwAAcABwAAAAAAcIiAd3d3d3B3cABwAAAAAAj4iHf///B3iHcAcAAAAAAAiIiPiIiP8IhwBw + AAAAAAAAiAiIh3d48HAAcAAAAAd3CIiIiAAHd493AHd3cABwAAjwiAB3dwd/BwAAAHAHAACPCIgIAAd3 + ePdwAABwBwiIjwiA8I+AcHj3d3cAcAcI+I8HgPBw8HB494h3AHAHCIiPB4Dwd4BwiPd3dwBwBwAAjweI + /wAICIj3cAAAcAAAAAjweA//8AiPdwBwAAAAAAAI8HeIAAiIiHcAcAAAAAAAAI8HeIiIiAhwAHAAAAAA + AAiP8Ad3iAiIhwAHAAAAAACPiI/wAAD4eIdwBwAAAAAHCPgIj///iAeHAHAAAAAAB3CAAAiIiAAAcAcA + AAAAAAB3AHAAiIAHAABwAAAAAAAAB3cAAI+ABwAHAAAAAAAAAAAAAACIgAcAAAAAAAAAAAAAAAAAAAAH + AAAAAAAAAAAAAAAAB3d3dwAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////wP///8D///+A////gP//4Y + Dn/8AAQ/+AAAH/gAAA/4AAAP/AAAH/4AAB/gAAABwAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB/AAAH/wA + AB/+AAAf/AAAD/gAAA/4AAAf+AAAP/wYDH/+OA7///gP///4D///+A///////w== + + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + picBoxLogo + + + 1 + + + lblOrderLabel + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tableLayoutPanel3 + + + + /9j/4AAQSkZJRgABAQEAYABgAAD/4QC8RXhpZgAATU0AKgAAAAgABAESAAMAAAABAAEAAAE7AAIAAAAH + AAAAPodpAAQAAAABAAAARpydAAEAAAAOAAAApgAAAABUaG9tYXMAAAAEkAMAAgAAABQAAAB8kAQAAgAA + ABQAAACQkpEAAgAAAAM1MwAAkpIAAgAAAAM1MwAAAAAAADIwMjE6MDQ6MDEgMTQ6NTk6MjkAMjAyMTow + NDowMSAxNDo1OToyOQAAAFQAaABvAG0AYQBzAAAA/9sAQwACAQECAQECAgICAgICAgMFAwMDAwMGBAQD + BQcGBwcHBgcHCAkLCQgICggHBwoNCgoLDAwMDAcJDg8NDA4LDAwM/9sAQwECAgIDAwMGAwMGDAgHCAwM + DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAIwBkAwEi + AAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAAB + fQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNE + RUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1 + tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEA + AAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRC + kaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpz + dHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ + 2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/fi5vYbML50scW7gb2C5p28Yrzr9qv8AZm0H + 9rX4Map4O8QK0cV0vm2d5GP32nXKg+XOnuMkEfxKWXoa/M7wp8XfjF8ZtT0j9j288SafptxpGsz6Xqvi + SC/3TXWm24LfZlOQX2qrYUHewCIwUK+foMpyOOPpSnCqouDvNNbQt8S11ts1o9j4viTi6eT4mFGrQc1V + Vqbi/iqXSVNpr3b3upXatfS61/XDTdYtNYjZ7O6t7pEbazQyCQKfQkGpZ7iO2TdI6xr6scCvzR8e/BeD + /gkF+2N8M/EnhPVNbPwx8cOND1+G+ufOVJMhWkcgKvAdZV4yDHIB8pxXoP8AwWD12++NPxH+EPwF0W4e + O78aaumo6kY/vQ26Exo5/wBkAzuf+uINbx4djUxFKNGrelUTlztWso35rq+6t36o4ZccVKOCxM8Vh+XE + UJRg6alfmc7ez5Zcq0lf+W6s9NDU8P8AjTVpv+C4mtaP/a+pPoi+EFnSx+1ubQN5EB3iPOzPJOcdz619 + rX+pW+lW7TXU8NtCvWSVwij8TxXwZ8PPD9p4V/4Ll32lWEIt7HTfAkNpbRDpFEltbKq/gABXzx8Uv2g/ + AP7UH7afju5+PHiTxZb+B/B9/Jpnh7w9pEE8kMvlyvGXkMYO0nZuY8MxkADBUxXq18jePqUuRtRhRpt2 + jeTvokordv1surPncLxcsnoYj2iUqlXFVoxUp8sFazblNp2iulk220kj9fLS9h1C3Wa3ljmhkGVeNgys + PYjg1FqWs2ejRq15dW9qrnarTSCMMfQZNfll+w9+0B4Z+B/7f+ieEfhL4h8Va18JfH0fkXGm6xbyxnSr + 0rIVMe8DOGRPnAGVkKtkoGrpPA37Pen/APBTL/goB8cIviVrGvT6P8PLs6To+n2V15MdsnnSwqRkEDAh + LEAfM8hJz0PFW4WVCrJ4io40owU78vvWb5UuW+jvvrbqevhfESWLoU44Ogp151JUuX2i5LxjzuSqKLvH + l1Xu3vpbQ/Si/wBbs9Kije6u7a2SU4RpZVQOfbJ5q0GzX5I/sI/sD6L+138T/ip4Z8feKPFuraX8Kbk+ + HtDRL8r5Cme5XzAG3BQPJyEUBcuc54r6W/4Id/ErXPFPwA8WeG9Z1G51aLwT4gk07T57hy8iQFFYR5JJ + 2qwYgZ4DY6AVlmnDlLC0qk6VbnlT5eZctlaesWnd36XVjp4d44xGY4ihTxGF9lCuqnI+dSd6TtNSXKrK + 97O7vbbU+2KKKK+VP0QKKKKAPF/23o/jJqHwyt9O+C8eix65qk7Wt9e6hMIm063ZGHnQknHmBsc7Wx1A + zXzH4p/4IxN4U/ZZ0RvCGqhfjj4bvf7dXX0nMX9oXZIZoPMblUXapjZv4lJOPMav0ExmivawOfYrCU40 + 8PaKTu9NZeUu6s2rbanyubcH5fmdedfHc03KPKk3pDZuUF9mTaT5tXp20PmD45fs1+Mv24f2Dm8J/EDT + NN8N/EiFUuInjuUntBfQZCzK0edscyllK4ynmNwcDPzp/wAEkPD3ij9o39q7xP8AFDx1dW+qXnw70mDw + jYXUDb4ZZlUxGRHyQxESOWYcMbndxnFfY/7Z/wAGPiL8c/h5a6H8PPHUXgKa4mePVLprbznubV4ypjQg + blbJzlSp9xWj+x1+ynof7G3wQsPBmiTS33kyNdX19KgSS/uXxvlKjIUYVVC5OFVRknJPpUc4jSyurSUo + 81Rvlik/cTfv6vZSSSSTfc+fxPC88TxDhsQ4S9nQinOcpL97KK/d6LeUHKTcmlrojwP9oj9k74weG/8A + goHpvxo+Fo8N6pb6lYQaVqtnqcvltbRDakpUEqGBjVWUhtwYEEEdcz4i/safGL9mb9p7xN8SPgK/hnXN + L8dyfaNb8M623lIJyxdnRiVBXczspDqy+Yy4YV9C+If2k1+HVz8UtQ16EyaL4EurG3tks4d1zcG4trdw + hy20s00wUH5QARnoTXJ3X7Y3iPxnfX2neG/A2qWdxZ6LNq0s+oqskkZt7wQ3EUdujb7gmMMYmQ7ZHZFy + o3EVh8wzFxguSDioqDutJRspJS11cbppqzRONyfI1UqN1akakqkqi5W+aE7yhJw912U2mmpXi7bKxnfs + peGP2kNa+L114o+LGoeDdB8Mmza2g8K6TbrORJnKzCUMSjDufMfcONq8EZn7DP7K3jP4G/tXfHjxX4is + bS20Xx5q/wBs0eWK7SZ5o/tFw+WVTlDtkQ4PrXceJP2i/EnxE/Z+0vxV4B0me3urrUzaajbyW8OqX+lw + R+YJitrHcIJZ1ZEBh8wSKGY7Cy7Dy3jz9vqDTvgzq2o6LDdajJDpr2tn4pWzSLS59Y/sr+0Ui+yvKbhE + MWGyylVJ2Fsgms+bHVVVpwpwj7S0GkrcvLJPp1uurbaubKGUYaVCtWrVJujepGU3dzc4OL3V7JPooxi2 + rtN2Mz/gnZ+yn40/Z4+NHxw1rxRY2lpp/jjXxqGkvDdpO00Xn3T5YLyh2yocHnn2rF/YA/ZM+K/7G/x+ + 8b6LdR+HNS+FviW8n1WHU45v9OE2QIVKEgrlCQ4KsMrw3PPpOp/8FBfD2kTW+nroPiC+15pzp89jEsKt + bXgluUEEjGTarPHZ3M65ODEin+NQaXxu/a18S+G7fw7J4X0u1874keH1bwnaazayW9wusG4gXyLld2VU + Q3PmlRggWsxyRitKlbMq1SpCrCK9sknfb3Fo1rdWSvfbdmVHC5DhaNCpQqzf1WUpJxd3+8d5RlpZptqN + lqm0tGz6Oor5d8A/8FFLfX9XgurjSZrzRdaurOx04ae0RuLSV0top2nV5A+wX10LbKptVoJMkkYrT+H/ + APwUSsfEuieHZNT8G+IrO+1TS7bU9RSz8q8h0pLkzeQWZW3MriB2LBcRggvjnHjzyTGR1cPxX9abPz06 + o+npcXZVUaSq73to+jSve1rO913V3snb6PornfhP49k+KPw70nxC+kX+hrrEC3UNpevE06RON0bP5Tuo + LKQ2AxIzg4IIory6kHCThLdH0FGrGpBVIbNXXTR+T1OioooqTQKKKKAON8Rfs8eBfF3iy617VPCeg6hr + F9Aba4u7izSSW4iMZj2OSPmGwlee1OsP2fvA+l2tnDb+E9Bjj0+0ubCBRZp+7t7k5uIunKSHlwchjyc0 + UVt9Yq25eZ29Wcv1HDczn7ON3u7K71v27pP1RDcfs3eAbv4fW/hSTwf4fbw5a3BuodPNmnkxzEsTIBjh + zubLdTuOTyaW6/Zv+H97qzX0vgvwy921h/ZZk/s6LP2XyvJ8np93yv3eP7ny/d4oop/Wq387+99d/vJ/ + s/CO16UdLfZXTbp06dizr/wJ8F+KbTVINQ8L6Hdx63cRXl+JLNM3c0SLHHK5xkuqKqhuoUY6VqP8PtCk + TRFbR9NK+GnEmkg26401hE0IMPH7vEbsny4+ViKKKj21Rqzk/v8AK35aehosLQTclBXfku9/z19dTDuf + 2c/AV3f6bdSeD/DrXGjzSXFlJ9gj3W0kk/2h2U44Jn/eZ/v/ADdeajt/2afh9aX9ndReC/Dcdxp5mNs6 + WEamHzWd5Mcd2kkb2LsRjJooq/rVbbnf3sz/ALPwt7+yj/4CulrdPJfcux2Omabb6Np1vZ2kMdva2saw + wxRrtSJFACqo7AAAAUUUVhvqzsSSVkf/2Q== + + + + 1234567890-10 + + + lblDateLabel + + + 4 + + + 36 + + + Left + + + MiddleCenter + + + 0 + + + 5 + + + 544, 729 + + + 74, 0 + + + Date Text + + + lblPcbId + + + 6 + + + 2 + + + MiddleCenter + + + 7 + + + Left + + + 3, 3 + + + 0 + + + True + + + 191, 62 + + + Left + + + 3, 100 + + + 6 + + + MiddleCenter + + + 8 + + + 538, 626 + + + True + + + tableLayoutPanel3 + + + tableLayoutPanel3 + + + 0, 0 + + + 400, 768 + + + True + + \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FwUpdateBuilder.csproj b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FwUpdateBuilder.csproj index 1150ba31..3579c9f5 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FwUpdateBuilder.csproj +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FwUpdateBuilder.csproj @@ -58,10 +58,10 @@ false - D8B4896173CF7130DF43C53CECCE6E4A7595CA5C + 3D39BF7375F751B96081DE64F2A442ABD8A73321 - FwUpdateBuilder_TemporaryKey.pfx + FwUpdateBuilder_1_TemporaryKey.pfx true @@ -101,6 +101,12 @@ FrmFwUpdateBuilder.cs + + Form + + + FrmHistory.cs + Form @@ -118,6 +124,16 @@ FrmFwUpdateBuilder.cs Designer + + FrmHistory.cs + + + FrmHistory.cs + + + FrmHistory.cs + Designer + FrmRegister.cs @@ -145,6 +161,7 @@ Resources.resx True + PreserveNewest diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.Designer.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.Designer.cs index 4f663353..07e148b1 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.Designer.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.Designer.cs @@ -341,6 +341,15 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } } + /// + /// Looks up a localized string similar to Acquiring FW Update Safes..... + /// + internal static string StrReadingFwUpdateSafes { + get { + return ResourceManager.GetString("StrReadingFwUpdateSafes", resourceCulture); + } + } + /// /// Looks up a localized string similar to Acquiring Production Orders..... /// @@ -350,6 +359,15 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } } + /// + /// Looks up a localized string similar to Acquiring Report Files..... + /// + internal static string StrReadingReports { + get { + return ResourceManager.GetString("StrReadingReports", resourceCulture); + } + } + /// /// Looks up a localized string similar to Acquiring update operators..... /// @@ -611,6 +629,15 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } } + /// + /// Looks up a localized string similar to FW-Update Order Number. + /// + internal static string StrTableCordonelUpdateOrder { + get { + return ResourceManager.GetString("StrTableCordonelUpdateOrder", resourceCulture); + } + } + /// /// Looks up a localized string similar to Customer Location. /// @@ -638,6 +665,15 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } } + /// + /// Looks up a localized string similar to Date. + /// + internal static string StrTableDate { + get { + return ResourceManager.GetString("StrTableDate", resourceCulture); + } + } + /// /// Looks up a localized string similar to Core Max. /// @@ -710,6 +746,15 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } } + /// + /// Looks up a localized string similar to Update Operator ID. + /// + internal static string StrTableUpdateOperatorId { + get { + return ResourceManager.GetString("StrTableUpdateOperatorId", resourceCulture); + } + } + /// /// Looks up a localized string similar to Active. /// @@ -729,7 +774,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder.Properties { } /// - /// Looks up a localized string similar to Full Name. + /// Looks up a localized string similar to Update Operator. /// internal static string StrTableUserFullName { get { diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.de.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.de.resx index bdf86aa6..46d50209 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.de.resx +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.de.resx @@ -153,6 +153,12 @@ Ermittelle FW-Pakete.... + + Ermittelle FW Update Safes.... + + + Ermittelle Berichte.... + Ermittelle Kunden.... @@ -240,6 +246,9 @@ Auswahl + + Update Operator ID + Genehmigt @@ -273,6 +282,9 @@ Produktionsnummer + + FW-Update Auftragsnummer + Position @@ -315,6 +327,9 @@ Releasedatum + + Datum + Region @@ -322,7 +337,7 @@ Funkfrequenz [MHz] - Benutzername + Update Operator Domain diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.resx index 30254d81..b6c79c16 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.resx +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/Properties/Resources.resx @@ -159,6 +159,12 @@ Acquiring FW packages.... + + Acquiring FW Update Safes.... + + + Acquiring Report Files.... + Acquiring Cordonels.... @@ -243,6 +249,9 @@ Select + + Update Operator ID + Approved @@ -276,6 +285,9 @@ Order Number + + FW-Update Order Number + Position @@ -318,6 +330,9 @@ Release Date + + Date + Region @@ -325,7 +340,7 @@ Radio Frequency [MHz] - Full Name + Update Operator Domain diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FrmFwUpdateLoader.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FrmFwUpdateLoader.cs index b78ab6b3..f248702d 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FrmFwUpdateLoader.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FrmFwUpdateLoader.cs @@ -104,6 +104,16 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader /// private const String FwUpdateProjectName = "ServiceFwUpdateSw"; + ///// + ///// Search strings for "Firmware up to date!" messages in report file, copied from Resources.resx of all + ///// language packages from "ServiceFwUpdateSw" + ///// + //private readonly String[] _firmwareUpToDateSearchStrings = + //{ + // "Firmware is up to date!", + // "Firmware ist aktuell!" + //}; + /// /// Name of the file which contains the meter file names that can be erased before the FW-Update /// to free disk space and have to be restored after the FW-Update @@ -499,7 +509,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader public FrmFwUpdateLoader() { var fwUpdateLoaderExePath = AppDomain.CurrentDomain.BaseDirectory; - var fwUpdateLoaderConfigPath = Path.Combine(fwUpdateLoaderExePath, "Config"); + var fwUpdateLoaderConfigPath = Path.Combine(fwUpdateLoaderExePath, FwUpdateConfig.ConfigSubFolderName); // Set the FW-Update SW destination folder to the FW-Update Loader exe path _fwUpdateSwDestinationPath = Path.Combine(fwUpdateLoaderExePath, FwUpdateProjectName); @@ -691,13 +701,44 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader #region ------------------------------------------ Checks ----------------------------------------------------- + /// + /// Search "Firmware is up to date!" string in file to guarantee the successfully execution of the update + /// process. Get success string for all language settings! + /// + /// + /// - Initial + /// + private Boolean IsSuccessStringInFile(String fileNamePath) + { + try + { + // Get search strings from resources StrFwUpToDateMessage from ServiceFwUpdateSw + var fileLines = File.ReadAllLines(fileNamePath); + var fwIsUpToDate = false; + foreach (var searchString in FwUpdateConfig.FirmwareUpToDateSearchStrings) + { + if (fileLines.Any(line => line.Contains(searchString))) fwIsUpToDate = true; + } + + return fwIsUpToDate; + } + catch (Exception) + { + return false; + } + } + /// /// Search for report files /// /// /// - Initial /// - private Boolean IsPcbIdProcessed(String pcbId) + /// + /// - Check file content for "success" string to mark exclusively the validated updates. + /// - Check order number to enable more than one update for a specific pcbId. + /// + private Boolean IsPcbIdProcessed(String pcbId, String orderNo) { try { @@ -707,7 +748,8 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader var fileList = new List(); SystemControl.GetFilesOfDirectoryAndSubDirectory(FwUpdateConfig.UnreportedPath, fileList, $"*{FwUpdateConfig.ReportFileExtension}"); - if (fileList.Any(file => file.Contains(pcbId))) return true; + if (fileList.Any(file => file.Contains(pcbId) && file.Contains(orderNo) + && IsSuccessStringInFile(file))) return true; } // If this directory is existent and contains files, these files have to be checked if (SystemControl.FilesExistingInPath(FwUpdateConfig.ReportedPath)) @@ -715,7 +757,8 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader var fileList = new List(); SystemControl.GetFilesOfDirectoryAndSubDirectory(FwUpdateConfig.ReportedPath, fileList, $"*{FwUpdateConfig.ReportFileExtension}"); - if (fileList.Any(file => file.Contains(pcbId))) return true; + if (fileList.Any(file => file.Contains(pcbId) && file.Contains(orderNo) + && IsSuccessStringInFile(file))) return true; } } catch (Exception) @@ -1721,9 +1764,13 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader /// /// - Initial. /// + /// + /// - Added order number to search for successfully updated device in linked to this safe. + /// private void FillDataGridWithPcbIdInfos() { if (_fwUpdateSafe?.Updates?.CordonelDeviceInfos == null) return; + grpLanguageSelection.Enabled = false; _dataTablePcbIds?.Dispose(); @@ -1739,7 +1786,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateLoader foreach (var cordSearch in _fwUpdateSafe.Updates.CordonelDeviceInfos) { var row = _dataTablePcbIds.NewRow(); - row[Resources.StrTableUpdated] = IsPcbIdProcessed(cordSearch.PcbId); + row[Resources.StrTableUpdated] = IsPcbIdProcessed(cordSearch.PcbId, _customerAndOrderInfo); row[Resources.StrTableCordonelPcbId] = cordSearch.PcbId ?? "?"; _dataTablePcbIds.Rows.Add(row); diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FwUpdateLoader.csproj b/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FwUpdateLoader.csproj index 8afa929e..c678d98b 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FwUpdateLoader.csproj +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateLoader/FwUpdateLoader.csproj @@ -58,10 +58,10 @@ false - 550FE4A801FCFB0A36EB3B198C4A6E6A92020511 + 5ED6B0B9BFFE7DD309362274CB9BF34BAE31CEEE - FwUpdateLoader_TemporaryKey.pfx + FwUpdateLoader_1_TemporaryKey.pfx true @@ -146,6 +146,7 @@ Resources.de.resx True +