From e22c50edebd0ea42d6fdeaf9c4dfdfc2de798790 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 28 May 2025 11:32:48 +0200 Subject: [PATCH 1/8] Initial Dev_ProdUiCord --- Common/.vs/config/applicationhost.config | 2 +- Common/Common.sln.DotSettings.user | 2 +- .../Debug/WaterMeterRegisters.csproj.CoreCompileInputs.cache | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Common/.vs/config/applicationhost.config b/Common/.vs/config/applicationhost.config index a894c3cf..883679a3 100644 --- a/Common/.vs/config/applicationhost.config +++ b/Common/.vs/config/applicationhost.config @@ -155,7 +155,7 @@ - + diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index d3d71323..f04ddf61 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -30,7 +30,7 @@ True NewVersion True - C:\Users\Thomas Müller\AppData\Local\Temp\JetBrains\ReSharperPlatformVs17\vAny_ab6433f6\CoverageData\_Common.-1885154465\Snapshot\snapshot.utdcvr + True <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from Solution" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> 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 4163759b..9389613c 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 @@ -8cb55c312de586b683d72cf58c13e2801d10e14b767777d98338d3e1473a1213 +7df2ad6be70922b931820861acc675522243ee78 From e73799f7a144e3d9f79e019336409f871c2275e3 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 28 May 2025 11:39:55 +0200 Subject: [PATCH 2/8] ProductionUiCordonel: - PickingProcessState removed --- Common/Common.sln.DotSettings.user | 1 + .../Enum/PickingProcessState.cs | 73 ------------------- .../ProductionUiCordonel.csproj | 1 - 3 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/PickingProcessState.cs diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index f04ddf61..525053d6 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -30,6 +30,7 @@ True NewVersion True + C:\Users\Thomas Müller\AppData\Local\Temp\JetBrains\ReSharperPlatformVs17\vAny_ab6433f6\CoverageData\_Common.-1885154465\Snapshot\snapshot.utdcvr True diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/PickingProcessState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/PickingProcessState.cs deleted file mode 100644 index 894fff3a..00000000 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/Enum/PickingProcessState.cs +++ /dev/null @@ -1,73 +0,0 @@ -namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum -{ - /// - /// Genesis meter final test states - /// - public enum PickingProcessState - { - /// - /// Idle (nothing to do) - /// - Idle, - - /// - /// Idle (nothing to do) - /// - ScanOrder, - /// - /// New meter detected for marker to clear all process contents like production status - /// and programming parameters. - /// - CheckNewMeter, - /// - /// Error handling - /// - Error, - /// - /// Abort final test execution - /// - Abort, - /// - /// Repeat the entire final test - /// - RepeatFailedTests, - /// - /// Final test failed - /// - PickingFailed, - /// - /// User stopped process - /// - Stop, - /// - /// Check the actual production state if all steps are executed - /// - DetectCordonel, - /// - /// Connect to Cordonel - /// - ConnectCordonel, - /// - /// Request the serial number and radio address from DB - /// - GetPickingParameters, - /// - /// Check the radio functionality - /// - CompareMeterDetails, - InstallLut, - //todo ad excisting processstates - - - - PrintReturnReport, - /// - /// Print success report - /// - PrintSuccessReport, - /// - /// Delimiter for list - /// - StateListDelimiter - } -} \ No newline at end of file diff --git a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj index 4ab773c3..49bba7fa 100644 --- a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj +++ b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj @@ -284,7 +284,6 @@ ctlMultiModePressure.xaml - From c81be68d8c3a710738522fed2ff40f7f7ec6e60e Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 28 May 2025 16:06:03 +0200 Subject: [PATCH 3/8] ProductionUiCordonel: - generic checks, - Kitron radio parameter --- .../Genesis/GenesisCore/GenesisMeter.cs | 26 +++ .../Genesis/GenesisCore/IGenesisMeter.cs | 16 ++ .../Genesis/MockGenesis/MockGenesis.cs | 18 ++ .../WaterMeter/Genesis/Registers/Registers.cs | 1 + ...erRegisters.csproj.CoreCompileInputs.cache | 2 +- .../CheckOrderNumber.cs | 2 +- .../EolProcesses/CheckProductionState.cs | 141 ++++++--------- .../CheckSerialNumber.cs | 2 +- .../EolProcesses/EolProcessStatesDef.cs | 39 ++--- .../EolProcesses/ExecFinalParametrization.cs | 1 + .../GenericModules/GenericChecks.cs | 164 ++++++++++++++++++ .../GetFinalParametrization.cs | 4 +- .../PickingProcesses/CheckOrderNumber.cs | 96 ++++++++++ .../PickingProcesses/CheckProductionState.cs | 132 +++++--------- .../PickingProcessStatesDef.cs | 29 +++- .../ProductionProcesses/ProcessController.cs | 1 - .../ProductionUiCordonel.csproj | 8 +- .../Properties/Resources.Designer.cs | 47 ++++- .../Properties/Resources.de.resx | 15 ++ .../Properties/Resources.resx | 17 +- 20 files changed, 548 insertions(+), 213 deletions(-) rename Common/Production/ProductionUiCordonel/ProductionProcesses/{GenericProcesses => EolProcesses}/CheckOrderNumber.cs (99%) rename Common/Production/ProductionUiCordonel/ProductionProcesses/{GenericProcesses => EolProcesses}/CheckSerialNumber.cs (99%) create mode 100644 Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs rename Common/Production/ProductionUiCordonel/ProductionProcesses/{EolProcesses => GenericProcesses}/GetFinalParametrization.cs (99%) create mode 100644 Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckOrderNumber.cs diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index 6e5a9917..5afad7c5 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -234,6 +234,18 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore protected set; get; } + /// + public String MeterLength { + protected set; + get; + } = "?"; + + /// + public Boolean PressureSensorAssembled + { + protected set; get; + } + /// /// Radio frequency in MHz (433 or 868 or null). /// @@ -1423,6 +1435,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// /// - Frequency indicator == 0 means it is a NA-Region Octopus with EMEA FW installed. /// + /// + /// - Pressure sensor detection. + /// public void CheckRegionSizeLutCrc() { //read metrology lookup table CRC @@ -1440,6 +1455,17 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore LutCrc = Constants.StrUnknown; } + //read pressure sensor assembled + try + { + PressureSensorAssembled = RegisterConverter.ByteArrayToValue( + ReadRegister(Register.Metrologyasst.PressurePresent)); + } + catch (Exception)// exception will be thrown if register is not present + { + PressureSensorAssembled = false; + } + //read meter size MeterSize = MeterSizeConverter.ConvertMeterSizeEnumToSizeName( (MeterSize)RegisterConverter.ByteArrayToValue( diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs index ef84cf09..ef4a2715 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs @@ -94,6 +94,22 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore get; } + /// + /// Length of the meter. + /// + String MeterLength + { + get; + } + + /// + /// Pressure sensor assembled to meter. + /// + Boolean PressureSensorAssembled + { + get; + } + /// /// Region (EMEA, NA or China). /// diff --git a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs index f113f773..1e8e30ff 100644 --- a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs +++ b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs @@ -157,6 +157,24 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.MockGenesis get => base.MeterSize; } + /// + /// Mock object can overwrite length for test purposes + /// + public new String MeterLength + { + set => base.MeterLength = value; + get => base.MeterLength; + } + + /// + /// Mock object can overwrite pressure sensor is assembled for test purposes + /// + public new Boolean PressureSensorAssembled + { + set => base.PressureSensorAssembled = value; + get => base.PressureSensorAssembled; + } + /// /// Mock object can overwrite FwVersion for test purposes /// diff --git a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs index 408c9f2a..17c4d7e7 100644 --- a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs +++ b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs @@ -107,6 +107,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers { public static readonly String PulseEvenDistribution = "METROLOGYASST_PulseEvenDistribution"; public static readonly String PulseMode = "METROLOGYASST_PulseMode"; + public static readonly String PressurePresent = "METROLOGYASST_PressurePresent"; public static readonly String StoreConfiguration = "METROLOGYASST_StoreConfiguration"; } 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 9389613c..4163759b 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 @@ -7df2ad6be70922b931820861acc675522243ee78 +8cb55c312de586b683d72cf58c13e2801d10e14b767777d98338d3e1473a1213 diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckOrderNumber.cs similarity index 99% rename from Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs rename to Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckOrderNumber.cs index 3b4a7056..97b8bb64 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckOrderNumber.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckOrderNumber.cs @@ -4,7 +4,7 @@ using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.Properties; using Xylem.Common.Production.ProductionUiCordonel.UserControls; -namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses +namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses { public class CheckOrderNumber : BaseProductionProcess { diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index 2bd5c005..8918b640 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs @@ -6,8 +6,6 @@ using System.Windows; using LaaPackages.Features.Cordonel.Models; using Logic.ProductionToProductMapper.Files.Fw; using Xylem.Common.CommonCore.Consts; -using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; -using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; @@ -16,6 +14,7 @@ using Xylem.Common.Logic.ProductionOrderCore.OrderData; using Xylem.Common.Logic.ProductionOrderCore.TestResults; using Xylem.Common.Production.ProductionUiCordonel.Model; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; +using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericModules; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; using Xylem.Common.Production.ProductionUiCordonel.Properties; @@ -315,6 +314,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// - Collect all requirement statuses before signalizing failed to summarize results starting with battery /// load. /// + /// + /// - Check radio signal levels in parameter list. + /// public override StatusReturn ExecuteProcess() { #region ----------------------------------- Check EOL Progress -------------------------------------------- @@ -404,6 +406,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr ActualProcessProgress++; #endregion + #region ----------------------------------- Check Kitron Radio Signal Levels ------------------------------ + + var statusReturn = CheckKitronRadioSignalLevels(out feedbackMsg); + if (StatusReturn.Failed == statusReturn) + { + ErrorMsgDispatcher(feedbackMsg); + return StatusReturn.Failed; + } + if (StatusReturn.Okay == statusReturn) + { + SuccessMsgDispatcher(feedbackMsg); + } + + ActualProcessProgress++; + #endregion + #region ----------------------------------- Check Firmware and Apps --------------------------------------- if (string.IsNullOrEmpty(CheckFwAndApps(out feedbackMsg))) @@ -506,7 +524,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // This step may exit with "skipped" here if "special-requirement" forces to skip the check of calibration. // All following checks will be skipped as well. - var statusReturn = CheckCalibrationValues(out feedbackMsg); + statusReturn = CheckCalibrationValues(out feedbackMsg); if (StatusReturn.Skipped == statusReturn) { WarningMsgDispatcher(feedbackMsg); @@ -855,6 +873,23 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr return EolProgress.ProductionStatusMeterSize; } + /// + /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. + /// + /// Software Requirement Specification: + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_008]_Check_Kitron_Radio_Levels + /// + /// + /// + /// + /// + /// - Initial. + /// + private StatusReturn CheckKitronRadioSignalLevels(out String feedbackMsg) + { + return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, out feedbackMsg); + } + /// /// Check the installed firmware (FW) and all individual applications (Apps) installed to the meter: /// - Take the FLEXNETVERSION as base information which FW is installed in the Cordonel and compare this with @@ -866,7 +901,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// Cordonel operational system (Breeze). /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_008]_Check_FW_and_Apps + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_009]_Check_FW_and_Apps /// /// /// @@ -874,91 +909,23 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Extracted from for better testability. /// + /// + /// - Exported to generic tests. + /// private String CheckFwAndApps(out String feedbackMsg) { - feedbackMsg = ""; - // Check installed FW version with FLEXNET information - var fwUpdate = new MeterFwUpdate(Meter); - if (EolProgress == null || - Meter == null || - ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.FwVersion) || - string.IsNullOrEmpty(Meter.FwVersion) || - !Meter.FwVersion.Equals(ProductionRequirements.FwVersion) || - // Check if FW package has been loaded and contains at least the minimal required files - FwUpdatePackage == null || - FwUpdatePackage.Count < MeterFwUpdate.MinAppsRequiredForOperation) + var fwCheckMsg = GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, + out feedbackMsg); + + // Fill the EOL progress + if (string.IsNullOrEmpty(fwCheckMsg)) { if (EolProgress != null) EolProgress.ProductionStatusFwVersion = null; - feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; return ""; } - - var fileApps = new List(); - if (FwUpdatePackage != null) - { - foreach (var file in FwUpdatePackage) - { - // load the ABC (application binary container) - if (file.FileName.Contains("binfile") && - file.FileName.EndsWith(".bin") && - // Sometimes the * complete *.bin is part of the binaries containing all app in one file. - // As this is not part of the ADF it has to be skipped from loading!!!! - !file.FileName.Contains("complete")) - { - var fileApplication = new FileApplications(file.FileName) - { - BinData = new List(file.FileContent.ToList()) - }; - fileApps.Add(fileApplication); - } - // Load the ADF (application description file, containing the information - // of each application) - else if (file.FileName.Contains("product") && file.FileName.EndsWith(".txt")) - { - var enc = new System.Text.ASCIIEncoding(); - var adf = enc.GetString(file.FileContent.ToArray()); - fwUpdate.LoadPackageFileFromText(adf); - } - } - - fwUpdate.LoadFileApps(fileApps); - } - - var checkSucceeded = true; - // Compare every installed application for version and CRC with the required to be defined by the downloaded - // ABC (application binary container) - fwUpdate.CompareAllMeterAndFileApps(); - - if (// Validate package description file with required Apps (fileApps) and build the CORE REVISIONS MIN MAX - !fwUpdate.ValidateFileAppsWithPackageFile() || - // Check if any meter Apps is outdated or does contain an un-matching CRC - Meter.MeterAppListVersion.Any(app => app.Status != MeterAppState.MeterAppUpToDate && - app.Status != MeterAppState.MeterAppNotRequired)) - { - feedbackMsg += $"{Resources.StrErrorMsgAppVersionOrCrc}\n"; - checkSucceeded = false; - // Do not immediately return to summarize all errors following up - } - - // The package description file has to be parsed in advance using the fwUpdate.ValidateFileAppsWithPackageFile()!! - if (!fwUpdate.CheckCoreRevision(Meter.CoreRevision)) - { - feedbackMsg += $"{Resources.StrErrorMsgCoreRevision}\n"; - // Do not immediately return to summarize all errors following up - checkSucceeded = false; - } - - if (!checkSucceeded) - { - EolProgress.ProductionStatusFwVersion = null; - feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; - return EolProgress.ProductionStatusFwVersion; - } EolProgress.ProductionStatusFwVersion = Meter.FwVersion; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementFw} - Firmware: {Meter.FwVersion}"; - return EolProgress.ProductionStatusFwVersion; + return fwCheckMsg; } /// @@ -974,7 +941,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// calculation is being used. /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_009]_Check_Remaining_Battery_Load + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_010]_Check_Remaining_Battery_Load /// /// /// @@ -1075,7 +1042,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// Check the remaining lifetime /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_010]_Check_Remaining_Lifetime + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_011]_Check_Remaining_Lifetime /// /// /// @@ -1139,7 +1106,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// Check the months between first battery activation and now /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_011]_Check_Storage_Months + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_012]_Check_Storage_Months /// /// /// @@ -1215,7 +1182,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// don't match, the check of valid range and set to default values doesn't come in focus! /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_012]_Check_Calibration_Values + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_013]_Check_Calibration_Values /// /// /// @@ -1366,7 +1333,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// the according step has been successfully executed. /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_013]_Check_Preadjustment + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_014]_Check_Preadjustment /// /// /// @@ -1428,7 +1395,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// the according step has been successfully executed. /// /// Software Requirement Specification: - /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_014]_Check_Flow_Test_State + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_015]_Check_Flow_Test_State /// /// /// diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckSerialNumber.cs similarity index 99% rename from Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs rename to Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckSerialNumber.cs index ba488770..b3f87824 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/CheckSerialNumber.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckSerialNumber.cs @@ -4,7 +4,7 @@ using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.Properties; using Xylem.Common.Production.ProductionUiCordonel.UserControls; -namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses +namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses { public class CheckSerialNumber : BaseProductionProcess { diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs index 65fc798a..da4b4f3e 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs @@ -151,25 +151,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Kick off parallel process execution kickOffParallelState: ProcessState.GetProgrammingParameters), - // This scans the order number, it has to be executed exclusively with automatic - new ProcessStateStruct( - productionProcess: new CheckOrderNumber(Resources.StrStateCheckOrderNumber), - processState: ProcessState.CheckOrderNumber, - processInfo: Resources.StrStateCheckOrderNumber, - productionProcessNo: 11, - nextStateOnSuccess: ProcessState.CheckSerialNumber), - - // This scans the serial number, it has to be executed exclusively with automatic - new ProcessStateStruct( - productionProcess: new CheckSerialNumber( Resources.StrStateCheckSerialNumber), - processState: ProcessState.CheckSerialNumber, - processInfo: Resources.StrStateCheckSerialNumber, - productionProcessNo: 12, - nextStateOnSuccess: ProcessState.CheckAttachments), - - #endregion -------------------------------- GENERIC-STATES -------------------------------------------- - - #region ----------------------------------- EOL-STATES ------------------------------------------------ // Precondition: - The connection process has to be completed as a readout of some register // values from the Cordonel are needed to check the update capability: // - Wait on completed connection process before starting this process. @@ -186,6 +167,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Wait until this process has been successfully completed waitForSingleProcess: ProcessState.ConnectCordonel), + #endregion -------------------------------- GENERIC-STATES -------------------------------------------- + + #region ----------------------------------- EOL-STATES ------------------------------------------------ // Precondition: - The connection process has to be completed as a readout of some register // values from the Cordonel are needed to check the update capability: // - Wait on completed connection process before starting this process. @@ -201,7 +185,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr kickOffParallelState: ProcessState.ProcessPasswordFile, // Wait until this process has been successfully completed waitForSingleProcess: ProcessState.ConnectCordonel), - // Precondition: - The connection process has to be completed as a password change in the DB // will take place: Skeleton to Password Level 8. Not waiting for completion may cause side @@ -265,6 +248,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr productionProcessNo: 10, nextStateOnSuccess: ProcessState.CheckOrderNumber), + // This scans the order number, it has to be executed exclusively with automatic + new ProcessStateStruct( + productionProcess: new CheckOrderNumber(Resources.StrStateCheckOrderNumber), + processState: ProcessState.CheckOrderNumber, + processInfo: Resources.StrStateCheckOrderNumber, + productionProcessNo: 11, + nextStateOnSuccess: ProcessState.CheckSerialNumber), + + // This scans the serial number, it has to be executed exclusively with automatic + new ProcessStateStruct( + productionProcess: new CheckSerialNumber( Resources.StrStateCheckSerialNumber), + processState: ProcessState.CheckSerialNumber, + processInfo: Resources.StrStateCheckSerialNumber, + productionProcessNo: 12, + nextStateOnSuccess: ProcessState.CheckAttachments), + // Precondition: - All checks have to be executed with positive result new ProcessStateStruct( productionProcess: new CheckAttachments(Resources.StrStateCheckAttachments), diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs index b17d558d..cc882cba 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecFinalParametrization.cs @@ -3,6 +3,7 @@ using System.Linq; using LaaPackages.Features.Cordonel.Models; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; +using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; using Xylem.Common.Production.ProductionUiCordonel.Properties; namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs new file mode 100644 index 00000000..7bb35539 --- /dev/null +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -0,0 +1,164 @@ +using LaaPackages.Features.Cordonel.Models; +using Logic.ProductionToProductMapper.Files.Fw; +using System; +using System.Collections.Generic; +using System.Linq; +using Xylem.Common.CommonCore.Consts; +using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; +using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; +using Xylem.Common.Production.ProductionUiCordonel.Properties; + +namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericModules +{ + internal static class GenericChecks + { + /// + /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + /// + /// - Import from CheckProductionState for common use. + /// + public static StatusReturn CheckKitronRadioSignalLevels(IGenesisMeter meter, RegisterRestorer registerRestorer, + out String feedbackMsg) + { + feedbackMsg = ""; + if (meter == null || + string.IsNullOrEmpty(meter.MeterSize) || + string.IsNullOrEmpty(meter.Region)) + { + return StatusReturn.Failed; + } + // The NA region has no radio + if (meter.Region.Equals("NA")) + { + return StatusReturn.Skipped; + } + + // On unknown radio signal level parameters from Kitron those are not in the list of the programming parameters + if (!registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_PowerLevel"))) + { + var pressureSensorAssembled = meter.PressureSensorAssembled ? + $", {Resources.StrLblPressureSensorAssembledTxt}": + ""; + feedbackMsg = $"{Resources.StrErrorMsgRadioSignalLevels} " + + $"{Resources.StrLblRadioFrequencyTxt}: {meter.RadioFrequencyMhz} MHz," + + $"{Resources.StrLblMeterSizeTxt}: {meter.MeterSize}, " + + $"{Resources.StrLblMeterLengthTxt}: {meter.MeterLength} mm" + + $"{pressureSensorAssembled}"; + return StatusReturn.Failed; + } + feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels; + return StatusReturn.Okay; + } + + /// + /// Check the installed firmware (FW) and all individual applications (Apps) installed to the meter: + /// - Take the FLEXNETVERSION as base information which FW is installed in the Cordonel and compare this with + /// the production-requirement, + /// - The downloaded FW package containing all Apps as application-binary-container (ABC) will be compared with + /// the reported Apps by the Cordonel for their version and CRC using the " class, + /// - Crosscheck if the application-description-file (ADF) states all Apps which are installed in the Cordonel, + /// - Check the Core-Revision of the Cordonel against the ADF to guarantee that this FW is supported by the + /// Cordonel operational system (Breeze). + /// + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + /// + /// - Import from CheckProductionState for common use. + /// + public static String CheckFwAndApps(IGenesisMeter meter, CordonelRequirements requirements, + List fwUpdatePackage, out String feedbackMsg) + { + feedbackMsg = ""; + // Check installed FW version with FLEXNET information + var fwUpdate = new MeterFwUpdate(meter); + if (meter == null || + requirements == null || + string.IsNullOrEmpty(requirements.FwVersion) || + string.IsNullOrEmpty(meter.FwVersion) || + !meter.FwVersion.Equals(requirements.FwVersion) || + // Check if FW package has been loaded and contains at least the minimal required files + fwUpdatePackage == null || + fwUpdatePackage.Count < MeterFwUpdate.MinAppsRequiredForOperation) + { + feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; + return ""; + } + + var fileApps = new List(); + foreach (var file in fwUpdatePackage) + { + // load the ABC (application binary container) + if (file.FileName.Contains("binfile") && + file.FileName.EndsWith(".bin") && + // Sometimes the * complete *.bin is part of the binaries containing all app in one file. + // As this is not part of the ADF it has to be skipped from loading!!!! + !file.FileName.Contains("complete")) + { + var fileApplication = new FileApplications(file.FileName) + { + BinData = new List(file.FileContent.ToList()) + }; + fileApps.Add(fileApplication); + } + // Load the ADF (application description file, containing the information + // of each application) + else if (file.FileName.Contains("product") && file.FileName.EndsWith(".txt")) + { + var enc = new System.Text.ASCIIEncoding(); + var adf = enc.GetString(file.FileContent.ToArray()); + fwUpdate.LoadPackageFileFromText(adf); + } + } + + fwUpdate.LoadFileApps(fileApps); + + var checkSucceeded = true; + // Compare every installed application for version and CRC with the required to be defined by the downloaded + // ABC (application binary container) + fwUpdate.CompareAllMeterAndFileApps(); + + if (// Validate package description file with required Apps (fileApps) and build the CORE REVISIONS MIN MAX + !fwUpdate.ValidateFileAppsWithPackageFile() || + // Check if any meter Apps is outdated or does contain an un-matching CRC + meter.MeterAppListVersion.Any(app => app.Status != MeterAppState.MeterAppUpToDate && + app.Status != MeterAppState.MeterAppNotRequired)) + { + feedbackMsg += $"{Resources.StrErrorMsgAppVersionOrCrc}\n"; + checkSucceeded = false; + // Do not immediately return to summarize all errors following up + } + + // The package description file has to be parsed in advance using the fwUpdate.ValidateFileAppsWithPackageFile()!! + if (!fwUpdate.CheckCoreRevision(meter.CoreRevision)) + { + feedbackMsg += $"{Resources.StrErrorMsgCoreRevision}\n"; + // Do not immediately return to summarize all errors following up + checkSucceeded = false; + } + + if (!checkSucceeded) + { + feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; + return ""; + } + feedbackMsg = $"{Resources.StrSuccessMsgRequirementFw} - Firmware: {meter.FwVersion}"; + return meter.FwVersion; + } + } +} diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetFinalParametrization.cs similarity index 99% rename from Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs rename to Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetFinalParametrization.cs index e08cafe3..aeb4c482 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/GetFinalParametrization.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericProcesses/GetFinalParametrization.cs @@ -7,10 +7,10 @@ using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Logic.SoftwareAccessHelper; -using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; +using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses; using Xylem.Common.Production.ProductionUiCordonel.Properties; -namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolProcesses +namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses { /// /// Request for parameters for final programming including VAKO and CSD diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckOrderNumber.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckOrderNumber.cs new file mode 100644 index 00000000..7fc4b88f --- /dev/null +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckOrderNumber.cs @@ -0,0 +1,96 @@ +using System; +using Xylem.Common.CommonCore.Consts; +using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; +using Xylem.Common.Production.ProductionUiCordonel.Properties; +using Xylem.Common.Production.ProductionUiCordonel.UserControls; + +namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.PickingProcesses +{ + public class CheckOrderNumber : BaseProductionProcess + { + // string from scanner with string delimiter + private String _scan = ""; + // marker for scan input received + private Boolean _scanInputReceived; + /// + /// Ctor + /// + public CheckOrderNumber(String name) : base( name) + { + } + + /// + protected override void InitUserControl() + { + UserControl = new UcBarcodeInput + { + lblHeadLine = { Content = Resources.StrInstructionScanOrder }, + tbxScan = { Text = "" } + }; + } + + /// + /// Event handler taking the input from text box which should be scanned but also can be input manually. + /// + /// + /// + /// - Initial + /// + private void UserControlInput_Handler(Object sender, String input) + { + _scan = input; + _scanInputReceived = true; + } + + /// + /// Scanning of order number from production order sheet and comparing with DB. + /// + /// + /// + /// - Initial + /// + /// + /// - Removed signals for and as + /// these will be automatically set based on return value in + /// . + /// + public override StatusReturn ExecuteProcess() + { + if (Meter == null) + { + return StatusReturn.Failed; + } + + SignalRunningState(); + + if (UserControl == null) + { + ErrorMsgDispatcher(Resources.StrErrorMsgScanOrderNumber); + return StatusReturn.Failed; + } + + var ucBarCode = (UcBarcodeInput)UserControl; + ucBarCode.OnBarcodeInput += UserControlInput_Handler; + + // set focus to text input for scanner + ucBarCode.FocusMe(); + _scanInputReceived = false; + + // wait for new line + while (!_scanInputReceived) + { + } + + ucBarCode.OnBarcodeInput -= UserControlInput_Handler; + + if (!string.IsNullOrEmpty(_scan) && _scan.Length > 5) + { + //TODO Roland, Do something with the scanned order + return StatusReturn.Okay; + } + + ErrorMsgDispatcher(Resources.StrErrorMsgScanOrderNumber); + return StatusReturn.Failed; + } + } +} diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs index 1da6479e..75f02dde 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs @@ -1,15 +1,13 @@ -using System; +using Logic.ProductionToProductMapper.Files.Fw; +using System; using System.Collections.Generic; -using System.Linq; using System.Windows; -using Logic.ProductionToProductMapper.Files.Fw; using Xylem.Common.CommonCore.Consts; -using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; -using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Logic.ProductionOrderCore.OrderData; +using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericModules; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; using Xylem.Common.Production.ProductionUiCordonel.Properties; @@ -229,6 +227,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki ActualProcessProgress++; #endregion + #region ----------------------------------- Check Kitron Radio Signal Levels ------------------------------ + + statusReturn = CheckKitronRadioSignalLevels(out feedbackMsg); + if (StatusReturn.Failed == statusReturn) + { + ErrorMsgDispatcher(feedbackMsg); + return StatusReturn.Failed; + } + if (StatusReturn.Okay == statusReturn) + { + SuccessMsgDispatcher(feedbackMsg); + } + + ActualProcessProgress++; + #endregion + #region ----------------------------------- Check Firmware and Apps --------------------------------------- if (string.IsNullOrEmpty(CheckFwAndApps(out feedbackMsg))) @@ -531,6 +545,24 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki return ProductionRequirements.MeterSize; } + /// + /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. + /// + /// Software Requirement Specification: + /// [SRS_TBF_EOL_PP_CHECK_PROD_STATE_007]_Check_Kitron_Radio_Levels + /// + /// + /// + /// + /// + /// - Initial. + /// + private StatusReturn CheckKitronRadioSignalLevels(out String feedbackMsg) + { + return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, out feedbackMsg); + } + + /// /// Check the installed firmware (FW) and all individual applications (Apps) installed to the meter: /// - Take the FLEXNETVERSION as base information which FW is installed in the Cordonel and compare this with @@ -542,7 +574,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// Cordonel operational system (Breeze). /// /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_007]_Check_FW_and_Apps + /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_008]_Check_FW_and_Apps /// /// /// @@ -550,86 +582,12 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// /// - Initial. /// + /// + /// - Exported to generic tests. + /// private String CheckFwAndApps(out String feedbackMsg) { - feedbackMsg = ""; - // Check installed FW version with FLEXNET information - var fwUpdate = new MeterFwUpdate(Meter); - if (Meter == null || - ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.FwVersion) || - string.IsNullOrEmpty(Meter.FwVersion) || - !Meter.FwVersion.Equals(ProductionRequirements.FwVersion) || - // Check if FW package has been loaded and contains at least the minimal required files - FwUpdatePackage == null || - FwUpdatePackage.Count < MeterFwUpdate.MinAppsRequiredForOperation) - { - feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; - return ""; - } - - var fileApps = new List(); - if (FwUpdatePackage != null) - { - foreach (var file in FwUpdatePackage) - { - // load the ABC (application binary container) - if (file.FileName.Contains("binfile") && - file.FileName.EndsWith(".bin") && - // Sometimes the * complete *.bin is part of the binaries containing all app in one file. - // As this is not part of the ADF it has to be skipped from loading!!!! - !file.FileName.Contains("complete")) - { - var fileApplication = new FileApplications(file.FileName) - { - BinData = new List(file.FileContent.ToList()) - }; - fileApps.Add(fileApplication); - } - // Load the ADF (application description file, containing the information - // of each application) - else if (file.FileName.Contains("product") && file.FileName.EndsWith(".txt")) - { - var enc = new System.Text.ASCIIEncoding(); - var adf = enc.GetString(file.FileContent.ToArray()); - fwUpdate.LoadPackageFileFromText(adf); - } - } - - fwUpdate.LoadFileApps(fileApps); - } - - var checkSucceeded = true; - // Compare every installed application for version and CRC with the required to be defined by the downloaded - // ABC (application binary container) - fwUpdate.CompareAllMeterAndFileApps(); - - if (// Validate package description file with required Apps (fileApps) and build the CORE REVISIONS MIN MAX - !fwUpdate.ValidateFileAppsWithPackageFile() || - // Check if any meter Apps is outdated or does contain an un-matching CRC - Meter.MeterAppListVersion.Any(app => app.Status != MeterAppState.MeterAppUpToDate && - app.Status != MeterAppState.MeterAppNotRequired)) - { - feedbackMsg += $"{Resources.StrErrorMsgAppVersionOrCrc}\n"; - checkSucceeded = false; - // Do not immediately return to summarize all errors following up - } - - // The package description file has to be parsed in advance using the fwUpdate.ValidateFileAppsWithPackageFile()!! - if (!fwUpdate.CheckCoreRevision(Meter.CoreRevision)) - { - feedbackMsg += $"{Resources.StrErrorMsgCoreRevision}\n"; - // Do not immediately return to summarize all errors following up - checkSucceeded = false; - } - - if (!checkSucceeded) - { - feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; - return ""; - } - feedbackMsg = $"{Resources.StrSuccessMsgRequirementFw} - Firmware: {Meter.FwVersion}"; - return Meter.FwVersion; + return GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, out feedbackMsg); } /// @@ -645,7 +603,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// calculation is being used. /// /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_008]_Check_Remaining_Battery_Load + /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_009]_Check_Remaining_Battery_Load /// /// /// @@ -734,7 +692,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// Check the remaining lifetime /// /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_009]_Check_Remaining_Lifetime + /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_010]_Check_Remaining_Lifetime /// /// /// @@ -785,7 +743,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// Check the months between first battery activation and now /// /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_010]_Check_Storage_Months + /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_011]_Check_Storage_Months /// /// /// diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/PickingProcessStatesDef.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/PickingProcessStatesDef.cs index 2e124893..c75993b3 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/PickingProcessStatesDef.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/PickingProcessStatesDef.cs @@ -146,20 +146,33 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki processState: ProcessState.GetSerialNumberAndRadioAddress, processInfo: Resources.StrStateGetSerialAndRadioAddress, productionProcessNo: 2, - nextStateOnSuccess: ProcessState.CheckOrderNumber, - waitForAllProcesses: true), - + // Avoid automatic change after completion as parallel process is active + nextStateOnSuccess: BaseProductionProcess.DoNotChangeStateAfterCompletion, + // Kick off parallel process execution + kickOffParallelState: ProcessState.GetProgrammingParameters), + + // Precondition: - The connection process has to be completed as a readout of some register + // values from the Cordonel are needed to check the update capability: + // - Wait on completed connection process before starting this process. + new ProcessStateStruct( + productionProcess: new GetFinalParametrization(Resources.StrStateGetProgrammingParameters), + processState: ProcessState.GetProgrammingParameters, + processInfo: Resources.StrStateGetProgrammingParameters, + productionProcessNo: 3, + nextStateOnSuccess: ProcessState.CheckOrderNumber, + // Wait until this process has been successfully completed + waitForSingleProcess: ProcessState.ConnectCordonel), + #endregion -------------------------------- GENERIC-STATES -------------------------------------------- + + #region ----------------------------------- PICKING-STATES -------------------------------------------- // This scans the order number, it has to be executed exclusively with automatic new ProcessStateStruct( productionProcess: new CheckOrderNumber(Resources.StrStateCheckOrderNumber), processState: ProcessState.CheckOrderNumber, processInfo: Resources.StrStateCheckOrderNumber, - productionProcessNo: 3, + productionProcessNo: 4, nextStateOnSuccess: ProcessState.CheckProductionState), - #endregion -------------------------------- GENERIC-STATES -------------------------------------------- - - #region ----------------------------------- PICKING-STATES -------------------------------------------- // Precondition: - The connection process has to be completed as a readout of some register // values from the Cordonel are needed to check the update capability: // - Wait on completed connection process before starting this process. @@ -167,7 +180,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki productionProcess: new CheckProductionState(Resources.StrStateCheckProductionState), processState: ProcessState.CheckProductionState, processInfo: Resources.StrStateCheckProductionState, - productionProcessNo: 4, + productionProcessNo: 5, nextStateOnSuccess: ProcessState.Idle), //TODO Roland: implement your states here diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs index 5ff2e2e4..a416f514 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs @@ -9,7 +9,6 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EventArgs; -using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; using Timer = System.Threading.Timer; namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses diff --git a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj index 49bba7fa..03219dad 100644 --- a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj +++ b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj @@ -285,6 +285,7 @@ + @@ -298,6 +299,7 @@ + @@ -311,12 +313,12 @@ - - + + - + diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs b/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs index 128dfc26..a7a199bc 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -672,6 +672,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to ERROR: Missing radio signal levels from Kitron!. + /// + internal static string StrErrorMsgRadioSignalLevels { + get { + return ResourceManager.GetString("StrErrorMsgRadioSignalLevels", resourceCulture); + } + } + /// /// Looks up a localized string similar to ERROR: Read failed. /// @@ -1050,6 +1059,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to Meter Length. + /// + internal static string StrLblMeterLengthTxt { + get { + return ResourceManager.GetString("StrLblMeterLengthTxt", resourceCulture); + } + } + /// /// Looks up a localized string similar to Meter Size. /// @@ -1095,6 +1113,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to Pressure Sensor Assembled. + /// + internal static string StrLblPressureSensorAssembledTxt { + get { + return ResourceManager.GetString("StrLblPressureSensorAssembledTxt", resourceCulture); + } + } + /// /// Looks up a localized string similar to RadioAddress. /// @@ -1113,6 +1140,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to Radio Frequency. + /// + internal static string StrLblRadioFrequencyTxt { + get { + return ResourceManager.GetString("StrLblRadioFrequencyTxt", resourceCulture); + } + } + /// /// Looks up a localized string similar to SerialNumber. /// @@ -1941,6 +1977,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.Properties { } } + /// + /// Looks up a localized string similar to Success: Cordonel radio signal levels successfully loaded. + /// + internal static string StrSuccessMsgRadioSignalLevels { + get { + return ResourceManager.GetString("StrSuccessMsgRadioSignalLevels", resourceCulture); + } + } + /// /// Looks up a localized string similar to Success: Successfully read. /// diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx b/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx index f369a09e..7c87569e 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.de.resx @@ -400,6 +400,12 @@ Baugröße + + Baulänge + + + Drucksensor eingebaut + Kitron Produktionsdatum @@ -412,6 +418,9 @@ Monate + + Funkfrequenz + Funkadresse @@ -619,6 +628,9 @@ FEHLER: Falsche Nennweite + + FEHLER: Fehlende Funksignalpegel von Kitron! + FEHLER: Falsche Produktionsnummer @@ -679,6 +691,9 @@ Erfolg: Maximale Lagerzeit eingehalten + + Erfolg: Cordonel Funksignalpegel erfolgreich geladen + Erfolg: Nennweite erfolgreich validiert diff --git a/Common/Production/ProductionUiCordonel/Properties/Resources.resx b/Common/Production/ProductionUiCordonel/Properties/Resources.resx index 2a3d91c6..07bb7245 100644 --- a/Common/Production/ProductionUiCordonel/Properties/Resources.resx +++ b/Common/Production/ProductionUiCordonel/Properties/Resources.resx @@ -400,6 +400,12 @@ Meter Size + + Meter Length + + + Pressure Sensor Assembled + Kitron production date @@ -412,6 +418,9 @@ Months + + Radio Frequency + RadioAddress @@ -616,9 +625,12 @@ ERROR: Maximum Storage Month or battery assembly date unknown - + ERROR: Requirement Meter Size does not match + + ERROR: Missing radio signal levels from Kitron! + ERROR: Requirement Production Order does not match @@ -679,6 +691,9 @@ Success: Requirement for maximum storage time kept + + Success: Cordonel radio signal levels successfully loaded + Success: Requirement and Cordonel meter size successfully validated From 178cee08771a4297fe5293c5dceae4e1a6efe368 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Thu, 5 Jun 2025 13:01:11 +0200 Subject: [PATCH 4/8] configuration.json R1.4.E0 --- .../Genesis/GenesisCore/configuration.json | 198 +++++++++++++----- 1 file changed, 140 insertions(+), 58 deletions(-) diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json index 40b4a983..c457ab79 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json @@ -1,18 +1,4 @@ { -// "SUMMARY": { -// "schema": "1", -// "version": "350", -// "description": "...", -// "build": { -// "emea": "R1416 2025-04-09", -// "na": "B2011 2024-10-10" -// }, -// "CordonelRegisterResponsibilities.xlsx": { -// "version": "66.0", -// "timestamp": "2025-02-18 13:16" -// }, -// "date_modified": "2025-04-09 09:43" -// }, "CONFIGEXCHANGE": { "id": 4, "version": { @@ -629,7 +615,7 @@ "id": 9, "version": { "first": 1, - "last": 163 + "last": 164 }, "registers": { "AlarmStatus0": { @@ -650,7 +636,7 @@ "description": "8 bit counts corresponding to alarms 0-3.", "version": { "first": 1, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -688,7 +674,7 @@ "description": "8 bit counts corresponding to alarms 4-7.", "version": { "first": 1, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -745,7 +731,7 @@ "description": "Any set bits manually clear the corresponding alarm.", "version": { "first": 111, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -791,7 +777,7 @@ "description": "8 bit counts corresponding to alarms 8-11.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -829,7 +815,7 @@ "description": "8 bit counts corresponding to alarms 12-15.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -867,7 +853,7 @@ "description": "8 bit counts corresponding to alarms 16-19.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -905,7 +891,7 @@ "description": "8 bit counts corresponding to alarms 20-23.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -943,7 +929,7 @@ "description": "8 bit counts corresponding to alarms 24-27.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -981,7 +967,7 @@ "description": "8 bit counts corresponding to alarms 28-31.", "version": { "first": 26, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -1123,6 +1109,54 @@ } } } + }, + { + "type": "uint32_t", + "privilege": { + "lvl1": "RO", + "lvl2": "RO", + "lvl3": "RW", + "lvl4": "RO", + "lvl5": "RW", + "lvl6": "RW", + "lvl7": "RW", + "lvl8": "RW" + }, + "description": "Bit set of those alarms which are being monitored.", + "version": { + "first": 164, + "last": 164 + }, + "values": { + "default": 4294967295, + "minimum": 0, + "maximum": 4294967295 + }, + "statictype": "infrequentlyupdated", + "production": { + "required": true, + "kitron": false, + "csd": "default", + "vako": false, + "operation_calibration": false, + "runtime_ignore": false, + "responsible": [ + "J.S." + ], + "remarks": "Bitmask of the alarms that we are interested in. I can imagine some customers may have different requirements to others. The radio does change this.", + "region": { + "emea": { + "values": { + "default": 49235 + } + }, + "na": { + "values": { + "default": 0 + } + } + } + } } ] }, @@ -1168,7 +1202,7 @@ "description": "Bit set of those alarms which will generate events.", "version": { "first": 111, - "last": 163 + "last": 164 }, "values": { "default": 4294967295, @@ -1325,6 +1359,54 @@ } } } + }, + { + "type": "uint32_t", + "privilege": { + "lvl1": "RO", + "lvl2": "RO", + "lvl3": "RW", + "lvl4": "RO", + "lvl5": "RW", + "lvl6": "RW", + "lvl7": "RW", + "lvl8": "RW" + }, + "description": "Bit set of those alarms which are displayed with IDs and the alarm icon.", + "version": { + "first": 164, + "last": 164 + }, + "values": { + "default": 4294967295, + "minimum": 0, + "maximum": 4294967295 + }, + "statictype": "infrequentlyupdated", + "production": { + "required": false, + "kitron": false, + "csd": null, + "vako": false, + "operation_calibration": false, + "runtime_ignore": true, + "responsible": [ + "J.S" + ], + "remarks": "Bitmask of the alarms that will be shown on the display (both the alarm ID and the flag icon). Again, I can imagine different customers wanting different things. The radio seems to set this but it seems to be a hardwired value.", + "region": { + "emea": { + "values": { + "default": 16382 + } + }, + "na": { + "values": { + "default": 0 + } + } + } + } } ] }, @@ -1365,7 +1447,7 @@ "description": "Alarms that have their display automatically cleared", "version": { "first": 111, - "last": 163 + "last": 164 }, "statictype": "static", "production": { @@ -1475,7 +1557,7 @@ "description": "Flow rate above which broken pipe alarm is set in 1/256 l/h. Due to rounding the value read back may not be exactly the value written. This is why the statictype is given as 'approximate'", "version": { "first": 133, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Cubic Meters per Second: conversion of 1/256 l/h flow rate units, the volume (liters = (1 / 256) * 10^-3 m^3 = 3.90625 * 10^-6 m^3) and time (hours = 3600 s) into SI base units. Flow rate = (3.90625 * 10^-6 m^3) / (3600 s) = 1.085069444 * 10^-9 m^3/s.", @@ -1589,7 +1671,7 @@ "description": "Time threshold for leak alarm in minutes", "version": { "first": 119, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Seconds: time in minutes ...", @@ -1694,7 +1776,7 @@ "description": "Number of measurements in reverse flow required to set reverse flow alarm", "version": { "first": 143, - "last": 163 + "last": 164 }, "values": { "default": 15, @@ -1747,7 +1829,7 @@ "description": "Timezone in which this application is set to run.", "version": { "first": 24, - "last": 163 + "last": 164 }, "values": { "default": 0, @@ -1792,7 +1874,7 @@ "description": "A name for the arrangement of applications on the meter", "version": { "first": 130, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -1853,7 +1935,7 @@ "description": "The number of times the meter has rebooted", "version": { "first": 111, - "last": 163 + "last": 164 }, "values": { "minimum": 0, @@ -1943,7 +2025,7 @@ "description": "Time threshold for broken pipe alarm in minutes", "version": { "first": 119, - "last": 163 + "last": 164 }, "values": { "default": 180, @@ -2068,7 +2150,7 @@ "description": "Flow rate above which leak alarm can be set in 1/256 l/h. Due to rounding the value read back may not be exactly the value written. This is why the statictype is given as 'approximate'", "version": { "first": 133, - "last": 163 + "last": 164 }, "values": { "default": 6399, @@ -2125,7 +2207,7 @@ "description": "Charge in uAs available in manufacturing (read only)", "version": { "first": 84, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Coulombs: charge in uAs ...", @@ -2223,7 +2305,7 @@ "description": "High temperature alarm threshold in 0.1°C", "version": { "first": 111, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Degrees Celsius: temperature in 0.1 degrees C ...", @@ -2309,7 +2391,7 @@ "description": "Time threshold for high temperature alarm in seconds", "version": { "first": 111, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Seconds: time in seconds ...", @@ -2419,7 +2501,7 @@ "description": "Low temperature alarm threshold in 0.1°C", "version": { "first": 111, - "last": 163 + "last": 164 }, "values": { "default": 20, @@ -2496,7 +2578,7 @@ "description": "Time threshold for low temperature alarm in seconds", "version": { "first": 111, - "last": 163 + "last": 164 }, "values": { "default": 600, @@ -2597,7 +2679,7 @@ "description": "High pressure alarm threshold in Pa", "version": { "first": 122, - "last": 163 + "last": 164 }, "values": { "default": 1600000, @@ -2698,7 +2780,7 @@ "description": "Time threshold for high pressure alarm in seconds", "version": { "first": 119, - "last": 163 + "last": 164 }, "si_transform": { "remarks": "Seconds: ...", @@ -2808,7 +2890,7 @@ "description": "Low pressure alarm threshold in Pa", "version": { "first": 122, - "last": 163 + "last": 164 }, "values": { "default": 30000, @@ -2909,7 +2991,7 @@ "description": "Time threshold for low pressure alarm in seconds", "version": { "first": 119, - "last": 163 + "last": 164 }, "values": { "default": 600, @@ -2981,7 +3063,7 @@ "description": "Store all configuration items in non-volatile memory.", "version": { "first": 131, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -3019,7 +3101,7 @@ "description": "Customer serial number string", "version": { "first": 139, - "last": 163 + "last": 164 }, "statictype": "static", "production": { @@ -3060,7 +3142,7 @@ "description": "Internal backup of calendar seconds", "version": { "first": 145, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -3100,7 +3182,7 @@ "description": "Datetime in seconds since 1/1/2000 00:00:00. Time meter was determined to have been installed. 0 means not installed.", "version": { "first": 147, - "last": 163 + "last": 164 }, "statictype": "infrequentlyupdated", "production": { @@ -3148,7 +3230,7 @@ "description": "Read to view the string used as a decimal point for this locale", "version": { "first": 151, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -3188,7 +3270,7 @@ "description": "Read to view the string used as a thousands separarator for this locale", "version": { "first": 151, - "last": 163 + "last": 164 }, "statictype": "dynamic", "production": { @@ -3228,7 +3310,7 @@ "description": "Test whether the internal login works. Start test by writing '1' then log out to enable the test to run. Log back in and read back this register for result (see status codes)", "version": { "first": 157, - "last": 163 + "last": 164 }, "values": { "minimum": 0, @@ -3270,7 +3352,7 @@ "description": "time threshold in Minutes for NoFlowAlarm trigger NoFlowAlarm trigger", "version": { "first": 161, - "last": 163 + "last": 164 }, "values": { "default": 43200, @@ -3315,7 +3397,7 @@ "description": "number of consecutive samples (Minutes) before NoFlow Alarm gets cleared", "version": { "first": 161, - "last": 163 + "last": 164 }, "values": { "default": 5, @@ -3584,7 +3666,7 @@ "id": 26, "version": { "first": 1, - "last": 22 + "last": 24 }, "registers": { "UpgState": { @@ -3605,7 +3687,7 @@ "description": "General UPG states.", "version": { "first": 2, - "last": 22 + "last": 24 }, "statictype": "dynamic", "production": { @@ -3642,7 +3724,7 @@ "description": "Specifies the Bootloader State of operation.", "version": { "first": 2, - "last": 22 + "last": 24 }, "statictype": "dynamic", "production": { @@ -16299,7 +16381,7 @@ "id": 22, "version": { "first": 1, - "last": 199 + "last": 200 }, "registers": { "StoreConfiguration": { @@ -16320,7 +16402,7 @@ "description": "Store all configuration items in non-volatile memory.", "version": { "first": 147, - "last": 199 + "last": 200 }, "statictype": "dynamic", "production": { @@ -16359,7 +16441,7 @@ "description": "Override the maximum number of entries per log (0 keeps default)", "version": { "first": 147, - "last": 199 + "last": 200 }, "statictype": "static", "production": { From f77a87d9dd1b25d6bdeeaa8844f9994f99bbbc78 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Mon, 16 Jun 2025 14:51:28 +0200 Subject: [PATCH 5/8] ProductionUiCordonel: - Skip radio test will ignore Kitron radio calibrations --- Common/.shared/SharedAssemblyInfo.cs | 2 +- .../WaterMeterRegisters.csproj.CoreCompileInputs.cache | 2 +- .../EolProcesses/CheckProductionState.cs | 3 ++- .../ProductionProcesses/GenericModules/GenericChecks.cs | 7 ++++--- .../PickingProcesses/CheckProductionState.cs | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Common/.shared/SharedAssemblyInfo.cs b/Common/.shared/SharedAssemblyInfo.cs index 6c4ebd47..f97c684a 100644 --- a/Common/.shared/SharedAssemblyInfo.cs +++ b/Common/.shared/SharedAssemblyInfo.cs @@ -14,4 +14,4 @@ using System.Reflection; //[assembly: AssemblyVersion("1.2.*.0")] -[assembly: AssemblyVersion("2.7.0.*")] +[assembly: AssemblyVersion("2.7.1.*")] 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 8865d283..4163759b 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 @@ -89102b0142e574de38a9f47d370f3334e5e6c268 +8cb55c312de586b683d72cf58c13e2801d10e14b767777d98338d3e1473a1213 diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index 8918b640..f923459e 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs @@ -887,7 +887,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// private StatusReturn CheckKitronRadioSignalLevels(out String feedbackMsg) { - return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, out feedbackMsg); + return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, ProductionRequirements.SkipRadioCheck, + out feedbackMsg); } /// diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs index 7bb35539..45f4a449 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -18,6 +18,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. /// /// + /// /// /// /// @@ -28,7 +29,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// - Import from CheckProductionState for common use. /// public static StatusReturn CheckKitronRadioSignalLevels(IGenesisMeter meter, RegisterRestorer registerRestorer, - out String feedbackMsg) + Boolean skipRadioCheck, out String feedbackMsg) { feedbackMsg = ""; if (meter == null || @@ -37,8 +38,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener { return StatusReturn.Failed; } - // The NA region has no radio - if (meter.Region.Equals("NA")) + // The NA region has no radio or radio check should be ignored + if (meter.Region.Equals("NA") || skipRadioCheck) { return StatusReturn.Skipped; } diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs index 75f02dde..1373ced7 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs @@ -559,7 +559,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// private StatusReturn CheckKitronRadioSignalLevels(out String feedbackMsg) { - return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, out feedbackMsg); + return GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, ProductionRequirements.SkipRadioCheck, + out feedbackMsg); } From b0bd0dfeb95f3ffcf8d0c76912f574602402986a Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Tue, 17 Jun 2025 16:25:41 +0200 Subject: [PATCH 6/8] ProductionUiCordonel: - dynamic logging path as defined by GTB setup --- Common/Common.sln.DotSettings.user | 1 + .../Genesis/GenesisCore/RegisterRestorer.cs | 3 +- .../EolProcesses/CheckRadio.cs | 37 +++++-- .../ProductionUiCordonel.csproj | 1 + .../ProductionWindow.xaml.cs | 104 ++++++++++-------- 5 files changed, 94 insertions(+), 52 deletions(-) diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index f04ddf61..525053d6 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -30,6 +30,7 @@ True NewVersion True + C:\Users\Thomas Müller\AppData\Local\Temp\JetBrains\ReSharperPlatformVs17\vAny_ab6433f6\CoverageData\_Common.-1885154465\Snapshot\snapshot.utdcvr True diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs index 5e25bb8b..6bdf24f1 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/RegisterRestorer.cs @@ -1060,8 +1060,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore continue; //TODO THW check if error should be signalized } - // ATTENTION: Take the size of the read back value as this will be filled up to a chunk of 4 - // bytes and therefore the required write value may have a smaller byte list! + // ATTENTION: The size of the writtenValue and readBackValue may deviate! var dataSize = writtenValue.Length; var strRequiredRegisterValue = ""; diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs index d3f53451..70c8d404 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckRadio.cs @@ -1,12 +1,13 @@ -using System; +using LaaPackages.Features.Cordonel.Models; +using Newtonsoft.Json.Linq; +using SIRTCOM; +using System; using System.Configuration; using System.Linq; using System.Net; using System.Threading; using System.Windows.Threading; -using LaaPackages.Features.Cordonel.Models; -using Newtonsoft.Json.Linq; -using SIRTCOM; +using System.Xml.Linq; using Xylem.Common.CommonCore.Configuration; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; @@ -15,6 +16,7 @@ using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.Properties; using Xylem.Common.Production.ProductionUiCordonel.UserControls; +using Xylem.Common.Utils.Logging; using Button = System.Windows.Controls.Button; // ReSharper disable UnusedAutoPropertyAccessor.Local @@ -652,6 +654,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Optimized based on new documentations. /// + /// + /// - Logging path changed. + /// private void SendPamListenSemi(Int32 radioAddress, Int32 byteComPort, String strKey) { if (_dataContainer == null || _stateMachine == null) @@ -665,9 +670,27 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr _dataContainer.RadioAdress = radioAddress; _stateMachine.initialise((Byte)byteComPort); - var date = DateTime.Now.Date; - var loggingPath = $"C:\\GenesisLog\\{date:yyyy-MM-dd}\\ProductionUiCordonel\\{Meter.PcbId}_RadioCheck.log"; - _stateMachine.StartLoggin(loggingPath); + + try + { + var path = NLogHelper.GetApplicationDataPath(); + if (string.IsNullOrEmpty(path)) + { + path = NLogHelper.GetCurrentApplicationFolder(); + } + + var a = XElement.Load(path); + var baseLoggingPath = a.Elements().First(s => s.Name.LocalName == "variable").Attributes() + .First(s => s.Value == "BasePath").NextAttribute.Value; + + var loggingPath = + $"{baseLoggingPath}\\{DateTime.Now:yyyy-MM-dd}\\ProductionUiCordonel\\{Meter.PcbId}_RadioCheck.log"; + _stateMachine.StartLoggin(loggingPath); + } + catch (Exception) + { + // ignore + } LogNewStatusMsg($"{Resources.StrRadioMsgSendPam}: {radioAddress.ToString()}"); diff --git a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj index 03219dad..2bfd1c05 100644 --- a/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj +++ b/Common/Production/ProductionUiCordonel/ProductionUiCordonel.csproj @@ -259,6 +259,7 @@ 4.0 + diff --git a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs index 493733e2..d6542568 100644 --- a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs +++ b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs @@ -13,6 +13,7 @@ using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Threading; +using System.Xml.Linq; using LaaPackages.Features.Cordonel.Models; using Newtonsoft.Json; using NLog; @@ -59,7 +60,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel private String _lastLoggingTextToAvoidRepetition; private CordonelRequirements _productionRequirements; private UserAccessWindow _userAccessWindow; - private IProcessStateDef _processStateDef; + private readonly IProcessStateDef _processStateDef; #endregion @@ -835,6 +836,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel /// /// - Reduced printout. /// + /// + /// - Base logging path taken from NLogHelper as log-path setting made in GTB. + /// private void CreateFile(String headerInfo, Boolean shortReport = false, Boolean printReport = false) { var sb = new StringBuilder(); @@ -853,50 +857,64 @@ namespace Xylem.Common.Production.ProductionUiCordonel sb.AppendLine($"{Properties.Resources.StrLblOperatorNameText}: {Software.UserName}"); sb.AppendLine("------------------------------------------------------------------------"); - //TODO THW take the log path from setup (done with GTB) - var loggingPath = $"C:\\GenesisLog\\{DateTime.Now:yyyy-MM-dd}\\ProductionUiCordonel\\"; - var fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}_ExtendedReport_{genesisMeter.PcbId}.txt"; - - // Copy the header to the compressed string builder - var compressedSb = new StringBuilder(); - if (shortReport) + try { - compressedSb.Append(sb); + var path = NLogHelper.GetApplicationDataPath(); + if (string.IsNullOrEmpty(path)) + { + path = NLogHelper.GetCurrentApplicationFolder(); + } + var a = XElement.Load(path); + var baseLoggingPath = a.Elements().First(s => s.Name.LocalName == "variable").Attributes().First(s => s.Value == "BasePath").NextAttribute.Value; + + var loggingPath = $"{baseLoggingPath}\\{DateTime.Now:yyyy-MM-dd}\\ProductionUiCordonel\\"; + var fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}_ExtendedReport_{genesisMeter.PcbId}.txt"; + + // Copy the header to the compressed string builder + var compressedSb = new StringBuilder(); + if (shortReport) + { + compressedSb.Append(sb); + } + + var rtbText = new TextRange( + rtbLog.Document.ContentStart, + rtbLog.Document.ContentEnd + ); + sb.Append($"{rtbText.Text}"); + // Write the complete report to the file + File.WriteAllText(fileName, sb.ToString()); + + // Reduce sb content to compress it for printout + if (shortReport) + { + fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}" + + $"_ShortReport_{genesisMeter.PcbId}.txt"; + var sr = new StringReader(rtbText.Text); + var srLine = sr.ReadLine(); + while (srLine != null) + { + if (srLine.Contains(Properties.Resources.StrProcessStateError) || + srLine.Contains(Properties.Resources.StrProcessStateDone) || + srLine.Contains(Properties.Resources.StrProcessStateWarning) || + srLine.Contains(Properties.Resources.StrProcessStateSkipped) || + srLine.Contains(Properties.Resources.StrWarningMsgSpecialRequirementActive)) + compressedSb.AppendLine(srLine); + srLine = sr.ReadLine(); + } + + // Returns the compressed file for error report printout + File.WriteAllText(fileName, compressedSb.ToString()); + if (printReport) + { + Process.Start(fileName); + } + } + } - - var rtbText = new TextRange( - rtbLog.Document.ContentStart, - rtbLog.Document.ContentEnd - ); - sb.Append($"{rtbText.Text}"); - // Write the complete report to the file - File.WriteAllText(fileName, sb.ToString()); - - // Reduce sb content to compress it for printout - if (shortReport) + catch (Exception e) { - - fileName = $"{loggingPath}{DateTime.Now.ToString("yyyyMMddHHmmss")}" + - $"_ShortReport_{genesisMeter.PcbId}.txt"; - var sr = new StringReader(rtbText.Text); - var srLine = sr.ReadLine(); - while (srLine != null) - { - if (srLine.Contains(Properties.Resources.StrProcessStateError) || - srLine.Contains(Properties.Resources.StrProcessStateDone) || - srLine.Contains(Properties.Resources.StrProcessStateWarning) || - srLine.Contains(Properties.Resources.StrProcessStateSkipped) || - srLine.Contains(Properties.Resources.StrWarningMsgSpecialRequirementActive)) - compressedSb.AppendLine(srLine); - srLine = sr.ReadLine(); - } - - // Returns the compressed file for error report printout - File.WriteAllText(fileName, compressedSb.ToString()); - if (printReport) - { - Process.Start(fileName); - } + Console.WriteLine(e.Message); } } @@ -962,7 +980,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel } catch (Exception exception) { - Console.WriteLine(exception); + Console.WriteLine(exception.Message); } } From 1e198570ea0885fd609ceacd04769058e9d36207 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 18 Jun 2025 10:26:17 +0200 Subject: [PATCH 7/8] ProductionUiCordonel: - [START] locks display until Cordonel identified (may have changed) --- .../ProductionProcesses/ProcessController.cs | 2 +- .../ProductionUiCordonel/ProductionWindow.xaml.cs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs index a416f514..317a2679 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/ProcessController.cs @@ -653,7 +653,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses /// /// - Feed with processStateStruct. /// - protected void StartProcess(ProcessStateStruct processStateStruct) + private void StartProcess(ProcessStateStruct processStateStruct) { // deny access if uninitialized if (Processes == null || processStateStruct.ProductionProcess == null) diff --git a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs index d6542568..5cd7cd67 100644 --- a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs +++ b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml.cs @@ -45,6 +45,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel private static readonly Version _version = _assemblyName.Version; private readonly String _strSoftwareNameVersion; private RegisterLDAPUser _registerForm; + private Boolean _lockGenesisInfo; private Int32 Slot { @@ -447,6 +448,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel PrintSuccessNote(); BtnStop_Click(this, null); } + // Enable display of Genesis information on new detected + if (e.State == ProcessState.ConnectCordonel) + { + _lockGenesisInfo = false; + } } /// @@ -695,15 +701,18 @@ namespace Xylem.Common.Production.ProductionUiCordonel /// /// - Initial /// - /// + /// /// - Additional info of Cordonel. /// + /// + /// - Lock display of OLD Genesis after connect until the Genesis has been detected. + /// private void UpdateGuiWithProductInfos() { var genesisMeter = _processCtrl?.GetGenesisMeter(); _productionRequirements = _processCtrl?.GetProductionRequirements(); - if (genesisMeter == null) + if (genesisMeter == null || _lockGenesisInfo) return; UpdateContentControl(lblOrderNumberValue, @@ -799,6 +808,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel _startTime = DateTimeOffset.UtcNow; _timer?.Start(); + // Avoid display of genesis info before the detect new meter has been executed + _lockGenesisInfo = true; // remove last userControl dpSubProcess.Children.Clear(); From 0b683319c53b5112ac8c4d1bddfbfbab7b6f2a97 Mon Sep 17 00:00:00 2001 From: Thomas Wiedebusch Date: Wed, 18 Jun 2025 12:03:02 +0200 Subject: [PATCH 8/8] ProductionUiCordonel: - meter length --- .../Genesis/GenesisCore/GenesisMeter.cs | 2 +- .../Genesis/GenesisCore/IGenesisMeter.cs | 5 +- .../EolProcesses/CheckProductionState.cs | 51 +++++++++----- .../GenericModules/GenericChecks.cs | 68 +++++++++++++++---- .../PickingProcesses/CheckProductionState.cs | 11 ++- .../ProductionWindow.xaml | 2 + .../ProductionWindow.xaml.cs | 5 ++ .../Properties/Resources.Designer.cs | 9 +++ .../Properties/Resources.de.resx | 3 + .../Properties/Resources.resx | 5 +- 10 files changed, 122 insertions(+), 39 deletions(-) diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index 5afad7c5..5c0b46ae 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -236,7 +236,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// public String MeterLength { - protected set; + set; get; } = "?"; diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs index ef4a2715..f5563c77 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/IGenesisMeter.cs @@ -97,10 +97,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// /// Length of the meter. /// - String MeterLength - { - get; - } + String MeterLength { get; set; } /// /// Pressure sensor assembled to meter. diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index f923459e..3f203e66 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs @@ -28,7 +28,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// Maximum of expected processing steps for this process to feed the GUI progress bar. /// - private const Int32 MaxActualProgressSteps = 22; + private const Int32 MaxActualProgressSteps = 23; /// /// Successfully test on flow test bench will return this const value. @@ -120,13 +120,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr ActualProcessProgress++; // Get clustered FileId of firmware package for production or on special requirement release candidates - var isSpecialActive = ProductionRequirements.IsSpecialActive != null && + var isSpecialActive = ProductionRequirements.IsSpecialActive != null && (Boolean)ProductionRequirements.IsSpecialActive && - ProductionRequirements.IsSpecialApproved != null && + ProductionRequirements.IsSpecialApproved != null && (Boolean)ProductionRequirements.IsSpecialApproved; if (string.IsNullOrEmpty(ProductionRequirements.FwVersion) || - !MeterFwUpdate.SearchProdFwInDb(ProductionRequirements.FwVersion, out var parentFileId, out error, + !MeterFwUpdate.SearchProdFwInDb(ProductionRequirements.FwVersion, out var parentFileId, out error, !isSpecialActive) || parentFileId == null) { Meter.WriteLog(error); @@ -167,9 +167,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Exit if meanwhile cancellation is required if (CancellationToken.IsCancellationRequested) return CancellationProcedure(); - + ActualProcessProgress++; + // Get the meter length from VAKO needed for radio parameter message + if (!GenericChecks.GetMeterLengthFromDb(Meter)) + { + // Meter size unknown + ErrorMsgDispatcher(Resources.StrErrorMsgMeterLengthUnknown); + return StatusReturn.Failed; + } + + // Exit if meanwhile cancellation is required + if (CancellationToken.IsCancellationRequested) + return CancellationProcedure(); + + ActualProcessProgress++; // Check if requirement will force skipping of calibration if (!ProductionRequirements.SkipCalibration) { @@ -185,7 +198,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Exit if meanwhile cancellation is required if (CancellationToken.IsCancellationRequested) return CancellationProcedure(); - + ActualProcessProgress++; // Get the pre- and final flow test state. @@ -201,7 +214,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Exit if meanwhile cancellation is required if (CancellationToken.IsCancellationRequested) return CancellationProcedure(); - + ActualProcessProgress++; // Fill the results to calibration check register restorer which will be used to read the actual @@ -250,6 +263,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr CalibCheckRegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler; }// Not Skip calibration loop + ActualProcessProgress++; + return StatusReturn.Okay; } @@ -545,17 +560,17 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr erroneousSequenceStep = true; } #endregion -------------------------------- Check Calibration Values -------------------------------------- - + #region ----------------------------------- Summarize Check Results --------------------------------------- - + // One or more checks failed if (erroneousSequenceStep) return StatusReturn.Failed; - + // One or more checks generated a warning if (warningSequenceStep) return StatusReturn.Skipped; - + // Here everything went fine SuccessMsgDispatcher(feedbackMsg); @@ -674,11 +689,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr EolProgress.SpecialRequirementId = ProductionRequirements.SpecialId; EolProgress.SpecialRequirementVersion = ProductionRequirements.SpecialVersion; - feedbackMsg = isSpecialActive && - ProductionRequirements.SpecialId != null && - ProductionRequirements.SpecialVersion != null ? - Resources.StrWarningMsgSpecialRequirementActive + - $" Id.Ver: {ProductionRequirements.SpecialId}.{ProductionRequirements.SpecialVersion}" : + feedbackMsg = isSpecialActive && + ProductionRequirements.SpecialId != null && + ProductionRequirements.SpecialVersion != null ? + Resources.StrWarningMsgSpecialRequirementActive + + $" Id.Ver: {ProductionRequirements.SpecialId}.{ProductionRequirements.SpecialVersion}" : Resources.StrSuccessMsgRequirementActive + $" Id.Ver {ProductionRequirements.StandardId}.{ProductionRequirements.StandardVersion}"; @@ -915,7 +930,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// private String CheckFwAndApps(out String feedbackMsg) { - var fwCheckMsg = GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, + var fwCheckMsg = GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, out feedbackMsg); // Fill the EOL progress @@ -1322,7 +1337,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Allow overwriting of calibration successfully checked to okay if (EolProgress.ProductionStatusCalibrationChecked == null) EolProgress.ProductionStatusCalibrationChecked = EOLStatus.OK; - + // Stop logging CalibCheckRegisterRestorer.OnProcessUpdate -= ProcessUpdate_Handler; diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs index 45f4a449..37a1a667 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -3,11 +3,15 @@ using Logic.ProductionToProductMapper.Files.Fw; using System; using System.Collections.Generic; using System.Linq; +using Newtonsoft.Json; +using Xylem.Common.CommonCore.Configuration; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.Applications; using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; +using Xylem.Common.Logic.ProductionOrderCore.Vako; +using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Production.ProductionUiCordonel.Properties; namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericModules @@ -28,7 +32,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// /// - Import from CheckProductionState for common use. /// - public static StatusReturn CheckKitronRadioSignalLevels(IGenesisMeter meter, RegisterRestorer registerRestorer, + public static StatusReturn CheckKitronRadioSignalLevels(IGenesisMeter meter, RegisterRestorer registerRestorer, Boolean skipRadioCheck, out String feedbackMsg) { feedbackMsg = ""; @@ -38,26 +42,26 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener { return StatusReturn.Failed; } + // The NA region has no radio or radio check should be ignored if (meter.Region.Equals("NA") || skipRadioCheck) { return StatusReturn.Skipped; } - + var pressureSensorAssembled = + meter.PressureSensorAssembled ? $", {Resources.StrLblPressureSensorAssembledTxt}" : ""; + var meterInfo = $"{Resources.StrLblRadioFrequencyTxt}: {meter.RadioFrequencyMhz} MHz," + + $"{Resources.StrLblMeterSizeTxt}: {meter.MeterSize}, " + + $"{Resources.StrLblMeterLengthTxt}: {meter.MeterLength} mm" + + $"{pressureSensorAssembled}"; // On unknown radio signal level parameters from Kitron those are not in the list of the programming parameters if (!registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_PowerLevel"))) { - var pressureSensorAssembled = meter.PressureSensorAssembled ? - $", {Resources.StrLblPressureSensorAssembledTxt}": - ""; - feedbackMsg = $"{Resources.StrErrorMsgRadioSignalLevels} " + - $"{Resources.StrLblRadioFrequencyTxt}: {meter.RadioFrequencyMhz} MHz," + - $"{Resources.StrLblMeterSizeTxt}: {meter.MeterSize}, " + - $"{Resources.StrLblMeterLengthTxt}: {meter.MeterLength} mm" + - $"{pressureSensorAssembled}"; - return StatusReturn.Failed; + feedbackMsg = Resources.StrErrorMsgRadioSignalLevels + " " + meterInfo; + return StatusReturn.Failed; } - feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels; + + feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels + ". " + meterInfo; return StatusReturn.Okay; } @@ -82,7 +86,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// /// - Import from CheckProductionState for common use. /// - public static String CheckFwAndApps(IGenesisMeter meter, CordonelRequirements requirements, + public static String CheckFwAndApps(IGenesisMeter meter, CordonelRequirements requirements, List fwUpdatePackage, out String feedbackMsg) { feedbackMsg = ""; @@ -134,7 +138,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener // ABC (application binary container) fwUpdate.CompareAllMeterAndFileApps(); - if (// Validate package description file with required Apps (fileApps) and build the CORE REVISIONS MIN MAX + if ( // Validate package description file with required Apps (fileApps) and build the CORE REVISIONS MIN MAX !fwUpdate.ValidateFileAppsWithPackageFile() || // Check if any meter Apps is outdated or does contain an un-matching CRC meter.MeterAppListVersion.Any(app => app.Status != MeterAppState.MeterAppUpToDate && @@ -158,8 +162,44 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener feedbackMsg += $"{Resources.StrErrorMsgRequirementFw}\n"; return ""; } + feedbackMsg = $"{Resources.StrSuccessMsgRequirementFw} - Firmware: {meter.FwVersion}"; return meter.FwVersion; } + + /// + /// Get the meter length form database as single VAKO parameter + /// + /// + /// + /// + /// - Initial. + /// + public static Boolean GetMeterLengthFromDb(IGenesisMeter meter) + { + if (meter == null) + return false; + try + { + var a = LocalWebRequest.GetRequest( + $"{ServiceUrls.GenesisFinalCheckServiceUrl()}GetSingleVakoKey?ProductionOrderNumber=" + + $"{meter.OrderNumber}&KeyName=C_GEN_BAULAENGE"); + var response = JsonConvert.DeserializeObject(a); + + if (response == null || string.IsNullOrEmpty(response.Value)) + { + // Meter size unknown + return false; + } + + meter.MeterLength = response.Value; + return true; + } + catch (Exception) + { + // Meter size unknown + return false; + } + } } } diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs index 1373ced7..7e4efa18 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs @@ -21,7 +21,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// /// Maximum of expected processing steps for this process to feed the GUI progress bar. /// - private const Int32 MaxActualProgressSteps = 13; + private const Int32 MaxActualProgressSteps = 14; /// /// FW update package containing the ABC and the ADF. @@ -122,6 +122,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki ActualProcessProgress++; + // Get the meter length from VAKO needed for radio parameter message + if (!GenericChecks.GetMeterLengthFromDb(Meter)) + { + // Meter size unknown + ErrorMsgDispatcher(Resources.StrErrorMsgMeterLengthUnknown); + return StatusReturn.Failed; + } + ActualProcessProgress++; + return StatusReturn.Okay; } diff --git a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml index fe88c0f9..ddf06466 100644 --- a/Common/Production/ProductionUiCordonel/ProductionWindow.xaml +++ b/Common/Production/ProductionUiCordonel/ProductionWindow.xaml @@ -112,6 +112,7 @@