diff --git a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs index 1e8e30ff..5ac3a4b2 100644 --- a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs +++ b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockGenesis.cs @@ -426,12 +426,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.MockGenesis /// Mock reading all applications from a predefined package description file instead from the Meter. /// /// - /// - Initial + /// - Initial. + /// + /// + /// - Avoid overwriting of list combined with valid register dictionary. /// protected override void ReadMeterFirmwareAndAssignRegisters() { // Avoid overwriting of list if this already exits - if (MeterAppListVersion.Any() && MeterAppListVersion.All(f => f.Status != MeterAppState.Unknown)) + if (MeterAppListVersion.Any() && MeterAppListVersion.All(f => f.Status != MeterAppState.Unknown) && + ConfigRegister.MeterRegisterDic.Count != 0) { Logger.Warn($"Slot:{Slot} - Trying to overwride installed FW. Skipping generation of new " + "App list and meter register dictionary"); diff --git a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockRawParamsExamples/EMEA_DN50_RawParamsExample.json b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockRawParamsExamples/EMEA_DN50_RawParamsExample.json index 9a652317..7c5d0140 100644 --- a/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockRawParamsExamples/EMEA_DN50_RawParamsExample.json +++ b/Common/Hardware/WaterMeter/Genesis/MockGenesis/MockRawParamsExamples/EMEA_DN50_RawParamsExample.json @@ -1 +1,417 @@ -[{"RegisterName":"SENSUSRADIO_RadioAddress","RegisterValue":"GI6fMA==","Source":0},{"RegisterName":"SENSUSRADIO_EncryptionKey","RegisterValue":"Dp+sxqDh7xw7J6SbrCFlNQ==","Source":0},{"RegisterName":"GENESISFLOW_MeterSize","RegisterValue":"AAAAAQ==","Source":0},{"RegisterName":"GENESISFLOW_DisplayUnits","RegisterValue":"AAAAAA==","Source":0},{"RegisterName":"METROLOGYASST_FlowUnits","RegisterValue":"AAAABA==","Source":0},{"RegisterName":"SENSUSRADIO_FrequencyIndicator","RegisterValue":"AAABsQ==","Source":0},{"RegisterName":"METROLOGYASST_PulseMode","RegisterValue":"AAAABQ==","Source":0},{"RegisterName":"METROLOGYASST_PulseLength","RegisterValue":"AAAACA==","Source":0},{"RegisterName":"METROLOGYASST_PressurePresent","RegisterValue":"AAAAAA==","Source":0},{"RegisterName":"METROLOGYASST_TemperatureUnits","RegisterValue":"AAAAAA==","Source":0},{"RegisterName":"METROLOGYASST_PressureRate","RegisterValue":"AAAAAA==","Source":0},{"RegisterName":"METROLOGYASST_PressureUnits","RegisterValue":"AAAAAA==","Source":0},{"RegisterName":"METROLOGYASST_PulseWeight","RegisterValue":"ADDUAA==","Source":0},{"RegisterName":"SENSUSRADIO_MbusState","RegisterValue":"AAAABw==","Source":0},{"RegisterName":"SENSUSRADIO_OmTxInterval","RegisterValue":"AAAOEA==","Source":0},{"RegisterName":"SENSUSRADIO_TxInterval","RegisterValue":"AAAADw==","Source":0},{"RegisterName":"SENSUSRADIO_WakeupInterval","RegisterValue":"AAAAAw==","Source":0},{"RegisterName":"SENSUSRADIO_LatInterval","RegisterValue":"AAAAAw==","Source":0},{"RegisterName":"GENESISFLOW_DisplayPow10","RegisterValue":"/f///w==","Source":0},{"RegisterName":"METROLOGYASST_FlowPoint","RegisterValue":"AgAAAA==","Source":0},{"RegisterName":"CUSTOMER_AlarmEnableMask","RegisterValue":"AACAUw==","Source":1},{"RegisterName":"CUSTOMER_AlarmBroadcastMask","RegisterValue":"AAAf3A==","Source":1},{"RegisterName":"CUSTOMER_AlarmVisualMask","RegisterValue":"AAAf3A==","Source":1},{"RegisterName":"CUSTOMER_LeakTimeThreshold","RegisterValue":"AABOwA==","Source":1},{"RegisterName":"CUSTOMER_ExcessFlowTimeThreshold","RegisterValue":"AAAABQ==","Source":1},{"RegisterName":"CUSTOMER_ReverseFlowTimeThreshold","RegisterValue":"AAAHCA==","Source":1},{"RegisterName":"CUSTOMER_TemperatureHighThreshold","RegisterValue":"AAAB9A==","Source":1},{"RegisterName":"CUSTOMER_TemperatureHighDelay","RegisterValue":"AAABLA==","Source":1},{"RegisterName":"CUSTOMER_TemperatureLowThreshold","RegisterValue":"AAAAFA==","Source":1},{"RegisterName":"CUSTOMER_TemperatureLowDelay","RegisterValue":"AAABLA==","Source":1},{"RegisterName":"CUSTOMER_PressureHighThreshold","RegisterValue":"ABhqAA==","Source":1},{"RegisterName":"CUSTOMER_PressureHighDelay","RegisterValue":"AAABLA==","Source":1},{"RegisterName":"CUSTOMER_PressureLowThreshold","RegisterValue":"AAB1MA==","Source":1},{"RegisterName":"CUSTOMER_PressureLowDelay","RegisterValue":"AAABLA==","Source":1},{"RegisterName":"METROLOGYASST_TemperatureUnits","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"METROLOGYASST_PressureOffset","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"PERIODICLOG_DataLogContents","RegisterValue":"DAAkAw==","Source":1},{"RegisterName":"PERIODICLOG_DataLogPeriod","RegisterValue":"AAAAPA==","Source":1},{"RegisterName":"PERIODICLOG_AverageFlowPeriod","RegisterValue":"AAU=","Source":1},{"RegisterName":"SENSUSRADIO_AverageFlowPeriod","RegisterValue":"AAU=","Source":1},{"RegisterName":"PERIODICLOG_PeriodicLogLifeTimeCounter","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"SENSUSRADIO_MetroRadioLifeTimeCounter","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"PERIODICLOG_FixedDateReadingContents","RegisterValue":"DAAkAw==","Source":1},{"RegisterName":"PERIODICLOG_FixedDateDayOfMonth","RegisterValue":"AAAAAQ==","Source":1},{"RegisterName":"POWERMON_WarnFromClamp","RegisterValue":"JZgGAA==","Source":1},{"RegisterName":"SYSTEM_UpgradePermissions","RegisterValue":"AAAA/g==","Source":1},{"RegisterName":"POWERMON_BatteryQuantity","RegisterValue":"AAAAAg==","Source":1},{"RegisterName":"GENESISFLOW_SampleRate","RegisterValue":"AAI=","Source":1},{"RegisterName":"GENESISFLOW_LedMode","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"GENESISFLOW_HardErrorLimit","RegisterValue":"AAQ=","Source":1},{"RegisterName":"IRDA_PulseReportRate","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"IRDA_AdapterPresenceLimit","RegisterValue":"AAM=","Source":1},{"RegisterName":"SENSUSRADIO_OTAControlFlags","RegisterValue":"AAA=","Source":1},{"RegisterName":"CUSTOMER_RebootCount","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"GENESISFLOW_LowFlowMaxPeriod","RegisterValue":"ADwAAA==","Source":1},{"RegisterName":"GENESISFLOW_LowFlowThreshold","RegisterValue":"AAAAyA==","Source":1},{"RegisterName":"GENESISFLOW_MaxValidAmplitude","RegisterValue":"rwAAAA==","Source":1},{"RegisterName":"GENESISFLOW_MaxValidDeltaToF","RegisterValue":"AAPGXg==","Source":1},{"RegisterName":"GENESISFLOW_MaxValidToF","RegisterValue":"AXl8ww==","Source":1},{"RegisterName":"GENESISFLOW_MeterSize","RegisterValue":"AAAAAQ==","Source":1},{"RegisterName":"GENESISFLOW_MinValidAmplitude","RegisterValue":"JYAAAA==","Source":1},{"RegisterName":"GENESISFLOW_MinValidToF","RegisterValue":"ANG3Fw==","Source":1},{"RegisterName":"GENESISFLOW_Timeout","RegisterValue":"AAE=","Source":1},{"RegisterName":"CUSTOMER_LeakFlowThreshold","RegisterValue":"AAF3AA==","Source":1},{"RegisterName":"CUSTOMER_ExcessFlowVolumeThreshold","RegisterValue":"AMNQAA==","Source":1},{"RegisterName":"CUSTOMER_AppArrangement","RegisterValue":"AAE=","Source":1},{"RegisterName":"METROLOGYASST_PressureUnits","RegisterValue":"AAA=","Source":1},{"RegisterName":"CUSTOMER_Locale","RegisterValue":"AAAA0A==","Source":1},{"RegisterName":"GENESISFLOW_MaxValidAmplitude","RegisterValue":"rwAAAA==","Source":1},{"RegisterName":"SENSUSRADIO_HistoricalAlarmsDays","RegisterValue":"AAAAWg==","Source":1},{"RegisterName":"SENSUSRADIO_OmTxInterval","RegisterValue":"AAADhA==","Source":1},{"RegisterName":"GENESISFLOW_ForwardArrow","RegisterValue":"AAAAAQ==","Source":1},{"RegisterName":"SENSUSRADIO_EncryptionKey","RegisterValue":"8L/KE0jHXszHydwgWg0KHQ==","Source":1},{"RegisterName":"GENESISFLOW_ArrowThreshold","RegisterValue":"HoSA","Source":1},{"RegisterName":"GENESISFLOW_StartHit","RegisterValue":"AAAABg==","Source":1},{"RegisterName":"CUSTOMER_InstallationTime","RegisterValue":"AAAAAA==","Source":1},{"RegisterName":"METROLOGYASST_PressureRate","RegisterValue":"AADqYA==","Source":1},{"RegisterName":"GENESISFLOW_MaxDeltaToFDeviation","RegisterValue":"AAGtfw==","Source":1},{"RegisterName":"SENSUSRADIO_TemperatureMeasurePeriod","RegisterValue":"AAAAPA==","Source":1}] \ No newline at end of file +[ + { + "RegisterName": "SENSUSRADIO_RadioAddress", + "RegisterValue": "GI6fMA==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_EncryptionKey", + "RegisterValue": "Dp+sxqDh7xw7J6SbrCFlNQ==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_PowerLevel", + "RegisterValue": "AAAALQ==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_PowerLevelOption", + "RegisterValue": "AAAALw==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_ImpedanceCodeNew", + "RegisterValue": "AAALLQ==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_ImpedanceCodeOption", + "RegisterValue": "AAALLw==", + "Source": 0 + }, + { + "RegisterName": "GENESISFLOW_MeterSize", + "RegisterValue": "AAAAAQ==", + "Source": 0 + }, + { + "RegisterName": "GENESISFLOW_DisplayUnits", + "RegisterValue": "AAAAAA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_FlowUnits", + "RegisterValue": "AAAABA==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_FrequencyIndicator", + "RegisterValue": "AAABsQ==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PulseMode", + "RegisterValue": "AAAABQ==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PulseLength", + "RegisterValue": "AAAACA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PressurePresent", + "RegisterValue": "AAAAAA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_TemperatureUnits", + "RegisterValue": "AAAAAA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PressureRate", + "RegisterValue": "AAAAAA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PressureUnits", + "RegisterValue": "AAAAAA==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_PulseWeight", + "RegisterValue": "ADDUAA==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_MbusState", + "RegisterValue": "AAAABw==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_OmTxInterval", + "RegisterValue": "AAAOEA==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_TxInterval", + "RegisterValue": "AAAADw==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_WakeupInterval", + "RegisterValue": "AAAAAw==", + "Source": 0 + }, + { + "RegisterName": "SENSUSRADIO_LatInterval", + "RegisterValue": "AAAAAw==", + "Source": 0 + }, + { + "RegisterName": "GENESISFLOW_DisplayPow10", + "RegisterValue": "/f///w==", + "Source": 0 + }, + { + "RegisterName": "METROLOGYASST_FlowPoint", + "RegisterValue": "AgAAAA==", + "Source": 0 + }, + { + "RegisterName": "CUSTOMER_AlarmEnableMask", + "RegisterValue": "AACAUw==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_AlarmBroadcastMask", + "RegisterValue": "AAAf3A==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_AlarmVisualMask", + "RegisterValue": "AAAf3A==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_LeakTimeThreshold", + "RegisterValue": "AABOwA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_ExcessFlowTimeThreshold", + "RegisterValue": "AAAABQ==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_ReverseFlowTimeThreshold", + "RegisterValue": "AAAHCA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_TemperatureHighThreshold", + "RegisterValue": "AAAB9A==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_TemperatureHighDelay", + "RegisterValue": "AAABLA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_TemperatureLowThreshold", + "RegisterValue": "AAAAFA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_TemperatureLowDelay", + "RegisterValue": "AAABLA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_PressureHighThreshold", + "RegisterValue": "ABhqAA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_PressureHighDelay", + "RegisterValue": "AAABLA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_PressureLowThreshold", + "RegisterValue": "AAB1MA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_PressureLowDelay", + "RegisterValue": "AAABLA==", + "Source": 1 + }, + { + "RegisterName": "METROLOGYASST_TemperatureUnits", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "METROLOGYASST_PressureOffset", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_DataLogContents", + "RegisterValue": "DAAkAw==", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_DataLogPeriod", + "RegisterValue": "AAAAPA==", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_AverageFlowPeriod", + "RegisterValue": "AAU=", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_AverageFlowPeriod", + "RegisterValue": "AAU=", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_PeriodicLogLifeTimeCounter", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_MetroRadioLifeTimeCounter", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_FixedDateReadingContents", + "RegisterValue": "DAAkAw==", + "Source": 1 + }, + { + "RegisterName": "PERIODICLOG_FixedDateDayOfMonth", + "RegisterValue": "AAAAAQ==", + "Source": 1 + }, + { + "RegisterName": "POWERMON_WarnFromClamp", + "RegisterValue": "JZgGAA==", + "Source": 1 + }, + { + "RegisterName": "SYSTEM_UpgradePermissions", + "RegisterValue": "AAAA/g==", + "Source": 1 + }, + { + "RegisterName": "POWERMON_BatteryQuantity", + "RegisterValue": "AAAAAg==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_SampleRate", + "RegisterValue": "AAI=", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_LedMode", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_HardErrorLimit", + "RegisterValue": "AAQ=", + "Source": 1 + }, + { + "RegisterName": "IRDA_PulseReportRate", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "IRDA_AdapterPresenceLimit", + "RegisterValue": "AAM=", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_OTAControlFlags", + "RegisterValue": "AAA=", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_RebootCount", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_LowFlowMaxPeriod", + "RegisterValue": "ADwAAA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_LowFlowThreshold", + "RegisterValue": "AAAAyA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MaxValidAmplitude", + "RegisterValue": "rwAAAA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MaxValidDeltaToF", + "RegisterValue": "AAPGXg==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MaxValidToF", + "RegisterValue": "AXl8ww==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MeterSize", + "RegisterValue": "AAAAAQ==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MinValidAmplitude", + "RegisterValue": "JYAAAA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MinValidToF", + "RegisterValue": "ANG3Fw==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_Timeout", + "RegisterValue": "AAE=", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_LeakFlowThreshold", + "RegisterValue": "AAF3AA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_ExcessFlowVolumeThreshold", + "RegisterValue": "AMNQAA==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_AppArrangement", + "RegisterValue": "AAE=", + "Source": 1 + }, + { + "RegisterName": "METROLOGYASST_PressureUnits", + "RegisterValue": "AAA=", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_Locale", + "RegisterValue": "AAAA0A==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MaxValidAmplitude", + "RegisterValue": "rwAAAA==", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_HistoricalAlarmsDays", + "RegisterValue": "AAAAWg==", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_OmTxInterval", + "RegisterValue": "AAADhA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_ForwardArrow", + "RegisterValue": "AAAAAQ==", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_EncryptionKey", + "RegisterValue": "8L/KE0jHXszHydwgWg0KHQ==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_ArrowThreshold", + "RegisterValue": "HoSA", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_StartHit", + "RegisterValue": "AAAABg==", + "Source": 1 + }, + { + "RegisterName": "CUSTOMER_InstallationTime", + "RegisterValue": "AAAAAA==", + "Source": 1 + }, + { + "RegisterName": "METROLOGYASST_PressureRate", + "RegisterValue": "AADqYA==", + "Source": 1 + }, + { + "RegisterName": "GENESISFLOW_MaxDeltaToFDeviation", + "RegisterValue": "AAGtfw==", + "Source": 1 + }, + { + "RegisterName": "SENSUSRADIO_TemperatureMeasurePeriod", + "RegisterValue": "AAAAPA==", + "Source": 1 + } +] \ No newline at end of file diff --git a/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature b/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature index 0a7bcdf7..f1fdd772 100644 --- a/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature +++ b/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature @@ -466,7 +466,11 @@ OUTPUT: "StatusReturn" with results "Okay" or "Failed", # Activate the entire equality EOL progress check between requirement and result And Activate EOL progress check - # The input initializations don't have a "TestNo" nor a result (EOLStatus, StringReturn or StatusReturn) as those are commonly used for + # Name one production process to be checked in advance to the real test. This can be done more than once to fill a list with + # all required preceding production processes to check an entire sequence of processes. + And Define production process for sequencing before test 'ExecFinalParametrization' + +# The input initializations don't have a "TestNo" nor a result (EOLStatus, StringReturn or StatusReturn) as those are commonly used for # all tests specified in "Input matrix defining the test cases and results". All these inputs have a setup to pass the overall test with # positive feedback (all are good). And Input initializations for the test matrix and presets to pass the preceding tests @@ -530,20 +534,20 @@ OUTPUT: "StatusReturn" with results "Okay" or "Failed", # "Kill x" forces the test to fail to check if all tests are executed. REMIND: Set only ONE to "X" and leave all others as "-"! Otherwise the test will FAIL! | TestNo | Kill EOL | Kill Requ | Kill Order | Kill PcbId | Kill Region | Kill LUT | Kill Size | Kill FW | Kill Load | Kill LifeTime | Kill StoreTime | Kill PreAdj | Kill FlowTest | Kill Calib | StatusReturn | Comment | | 1 | - | - | - | - | - | - | - | - | - | - | - | - | - | - | Okay | Test sequence complete | - | 2 | X | - | - | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill EOL generation | - | 3 | - | X | - | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill requirement | - | 4 | - | - | X | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill production order check | - | 5 | - | - | - | X | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill PcbId check | - | 6 | - | - | - | - | X | - | - | - | - | - | - | - | - | - | Failed | Detected kill region check | - | 7 | - | - | - | - | - | X | - | - | - | - | - | - | - | - | Failed | Detected kill LUT check | - | 8 | - | - | - | - | - | - | X | - | - | - | - | - | - | - | Failed | Detected kill meter size check | - | 9 | - | - | - | - | - | - | - | X | - | - | - | - | - | - | Failed | Detected kill FW check | - | 10 | - | - | - | - | - | - | - | - | X | - | - | - | - | - | Failed | Detected kill battery load check | - | 11 | - | - | - | - | - | - | - | - | - | X | - | - | - | - | Failed | Detected kill life time check | - | 12 | - | - | - | - | - | - | - | - | - | - | X | - | - | - | Failed | Detected kill storage time check | - | 13 | - | - | - | - | - | - | - | - | - | - | - | X | - | - | Failed | Detected kill preadjustment check | - | 14 | - | - | - | - | - | - | - | - | - | - | - | - | X | - | Failed | Detected kill flow test check | - | 15 | - | - | - | - | - | - | - | - | - | - | - | - | - | X | Failed | Detected kill calibrations check | +# | 2 | X | - | - | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill EOL generation | +# | 3 | - | X | - | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill requirement | +# | 4 | - | - | X | - | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill production order check | +# | 5 | - | - | - | X | - | - | - | - | - | - | - | - | - | - | Failed | Detected kill PcbId check | +# | 6 | - | - | - | - | X | - | - | - | - | - | - | - | - | - | Failed | Detected kill region check | +# | 7 | - | - | - | - | - | X | - | - | - | - | - | - | - | - | Failed | Detected kill LUT check | +# | 8 | - | - | - | - | - | - | X | - | - | - | - | - | - | - | Failed | Detected kill meter size check | +# | 9 | - | - | - | - | - | - | - | X | - | - | - | - | - | - | Failed | Detected kill FW check | +# | 10 | - | - | - | - | - | - | - | - | X | - | - | - | - | - | Failed | Detected kill battery load check | +# | 11 | - | - | - | - | - | - | - | - | - | X | - | - | - | - | Failed | Detected kill life time check | +# | 12 | - | - | - | - | - | - | - | - | - | - | X | - | - | - | Failed | Detected kill storage time check | +# | 13 | - | - | - | - | - | - | - | - | - | - | - | X | - | - | Failed | Detected kill preadjustment check | +# | 14 | - | - | - | - | - | - | - | - | - | - | - | - | X | - | Failed | Detected kill flow test check | +# | 15 | - | - | - | - | - | - | - | - | - | - | - | - | - | X | Failed | Detected kill calibrations check | When Execute the generic tests Then Check the generic test results diff --git a/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature.cs b/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature.cs index 1c996a06..1120f140 100644 --- a/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature.cs +++ b/Common/Production/ProductionUiCordonel.UnitTests/Features/ProductionProcessCheckProductionState.feature.cs @@ -1877,6 +1877,9 @@ this.ScenarioInitialize(scenarioInfo); #line hidden #line 467 testRunner.And("Activate EOL progress check", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); +#line hidden +#line 471 + testRunner.And("Define production process for sequencing before test \'ExecFinalParametrization\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And "); #line hidden TechTalk.SpecFlow.Table table16 = new TechTalk.SpecFlow.Table(new string[] { "EOL Id", @@ -1890,7 +1893,7 @@ this.ScenarioInitialize(scenarioInfo); "182100041", "182100041", "EOL Progress successfully created"}); -#line 472 +#line 476 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table16, "And "); #line hidden @@ -1910,7 +1913,7 @@ this.ScenarioInitialize(scenarioInfo); "null", "null", "Standard Requirement is active and approved"}); -#line 476 +#line 480 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table17, "And "); #line hidden @@ -1922,7 +1925,7 @@ this.ScenarioInitialize(scenarioInfo); "3118323", "3118323", "Order number is identical"}); -#line 480 +#line 484 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table18, "And "); #line hidden @@ -1936,7 +1939,7 @@ this.ScenarioInitialize(scenarioInfo); "182100041", "182100041", "PcbId is identical"}); -#line 484 +#line 488 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table19, "And "); #line hidden @@ -1948,7 +1951,7 @@ this.ScenarioInitialize(scenarioInfo); "EMEA", "EMEA", "Region is identical"}); -#line 488 +#line 492 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table20, "And "); #line hidden @@ -1960,7 +1963,7 @@ this.ScenarioInitialize(scenarioInfo); "0xEB7C", "0xEB7C", "LUT CRC is identical"}); -#line 492 +#line 496 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table21, "And "); #line hidden @@ -1972,7 +1975,7 @@ this.ScenarioInitialize(scenarioInfo); "DN50", "DN50", "Meter size is identical"}); -#line 496 +#line 500 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table22, "And "); #line hidden @@ -1986,7 +1989,7 @@ this.ScenarioInitialize(scenarioInfo); "R1.3.0B", "R1.3.0B", "FW Version is identical"}); -#line 500 +#line 504 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table23, "And "); #line hidden @@ -1996,7 +1999,7 @@ this.ScenarioInitialize(scenarioInfo); table24.AddRow(new string[] { "2.0", "Normal threshold okay"}); -#line 504 +#line 508 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table24, "And "); #line hidden @@ -2010,7 +2013,7 @@ this.ScenarioInitialize(scenarioInfo); "20.0", "1.0", "Remaining lifetime as required"}); -#line 508 +#line 512 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table25, "And "); #line hidden @@ -2022,7 +2025,7 @@ this.ScenarioInitialize(scenarioInfo); "-3.0", "3.0", "Storage months in range"}); -#line 512 +#line 516 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table26, "And "); #line hidden @@ -2034,7 +2037,7 @@ this.ScenarioInitialize(scenarioInfo); "5", "21", "Test bench preadjustment succeeded"}); -#line 516 +#line 520 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table27, "And "); #line hidden @@ -2046,7 +2049,7 @@ this.ScenarioInitialize(scenarioInfo); "6", "30", "Test bench calibration succeeded"}); -#line 520 +#line 524 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table28, "And "); #line hidden @@ -2066,7 +2069,7 @@ this.ScenarioInitialize(scenarioInfo); "20000", "30000", "Valid calib factors"}); -#line 524 +#line 528 testRunner.And("Input initializations for the test matrix and presets to pass the preceding tests" + "", ((string)(null)), table29, "And "); #line hidden @@ -2106,265 +2109,13 @@ this.ScenarioInitialize(scenarioInfo); "-", "Okay", "Test sequence complete"}); - table30.AddRow(new string[] { - "2", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill EOL generation"}); - table30.AddRow(new string[] { - "3", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill requirement"}); - table30.AddRow(new string[] { - "4", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill production order check"}); - table30.AddRow(new string[] { - "5", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill PcbId check"}); - table30.AddRow(new string[] { - "6", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill region check"}); - table30.AddRow(new string[] { - "7", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill LUT check"}); - table30.AddRow(new string[] { - "8", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill meter size check"}); - table30.AddRow(new string[] { - "9", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill FW check"}); - table30.AddRow(new string[] { - "10", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill battery load check"}); - table30.AddRow(new string[] { - "11", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "-", - "Failed", - "Detected kill life time check"}); - table30.AddRow(new string[] { - "12", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "-", - "Failed", - "Detected kill storage time check"}); - table30.AddRow(new string[] { - "13", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "-", - "Failed", - "Detected kill preadjustment check"}); - table30.AddRow(new string[] { - "14", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "-", - "Failed", - "Detected kill flow test check"}); - table30.AddRow(new string[] { - "15", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "-", - "X", - "Failed", - "Detected kill calibrations check"}); -#line 529 +#line 533 testRunner.And("Input matrix defining the test cases and results", ((string)(null)), table30, "And "); #line hidden -#line 547 +#line 551 testRunner.When("Execute the generic tests", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); #line hidden -#line 548 +#line 552 testRunner.Then("Check the generic test results", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); #line hidden } diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index 3f203e66..b820c57c 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs @@ -10,7 +10,6 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; -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; @@ -140,7 +139,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr ActualProcessProgress++; - // Get the real content of the FW package including all binaries of each app and the application description file + // Get the real content of the FW package including all binaries of each app and the application + // description file FwUpdatePackage = new List(); if (!MeterFwUpdate.GetFwPackageFromDb((Int32)parentFileId, FwUpdatePackage, out error) || FwUpdatePackage == null) @@ -284,7 +284,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// - Region, /// - FW, /// - LUT CRC, - /// - Meter size + /// - Meter size, + /// - Kitron radio parameter, /// - Drained battery load versus required remaining battery load in percent, /// - Remaining run time in years, /// - Preadjustment is completed including correct values in registers, @@ -298,12 +299,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// - Adapted to new production process. /// /// - /// - Removed signals for and as - /// these will be automatically set based on return value in + /// - Removed signals for and + /// as these will be automatically set based on return value in /// . /// /// - /// - Take cordonel requirements from DB as base for checks of drained battery load and eventually special requirements. + /// - Take cordonel requirements from DB as base for checks of drained battery load and eventually special + /// requirements. /// /// /// - Get EOL progress model from DB, @@ -326,8 +328,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// - Changed from "StatusReturn" to "EOLStatus". /// /// - /// - Collect all requirement statuses before signalizing failed to summarize results starting with battery - /// load. + /// - Collect all requirement statuses before signalizing failed to summarize results starting with + /// battery load. /// /// /// - Check radio signal levels in parameter list. @@ -421,22 +423,6 @@ 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))) @@ -449,9 +435,34 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr ActualProcessProgress++; #endregion - #region ----------------------------------- Check Remaining Battery Load ---------------------------------- + #region ----------------------------------- Check Kitron Radio Signal Levels ------------------------------ var erroneousSequenceStep = false; + var warningSequenceStep = false; + var statusReturn = CheckKitronRadioSignalLevels(out feedbackMsg); + + if (StatusReturn.Failed == statusReturn) + { + ErrorMsgDispatcher(feedbackMsg); + //return StatusReturn.Failed; + // Do not return immediately to avoid multiple special-requirements on multiple errors + erroneousSequenceStep = true; + } + if (StatusReturn.Warning == statusReturn) + { + WarningMsgDispatcher(feedbackMsg); + warningSequenceStep = true; + } + if (StatusReturn.Okay == statusReturn) + { + SuccessMsgDispatcher(feedbackMsg); + } + + ActualProcessProgress++; + #endregion + + #region ----------------------------------- Check Remaining Battery Load ---------------------------------- + if (EOLStatus.FAIL == CheckRemainingBatteryLoad(out feedbackMsg)) { ErrorMsgDispatcher(feedbackMsg); @@ -459,7 +470,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion @@ -473,7 +487,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion @@ -487,14 +504,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion #region ----------------------------------- Check Preadjusment -------------------------------------------- - var warningSequenceStep = false; eolStatus = CheckPreadjustment(out feedbackMsg); if (EOLStatus.FAIL == eolStatus) { @@ -503,12 +522,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - if (EOLStatus.NA == eolStatus) + else if (EOLStatus.NA == eolStatus) { WarningMsgDispatcher(feedbackMsg); warningSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion @@ -523,12 +545,15 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - if (EOLStatus.NA == eolStatus) + else if (EOLStatus.NA == eolStatus) { WarningMsgDispatcher(feedbackMsg); warningSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion @@ -546,20 +571,24 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr warningSequenceStep = true; //return StatusReturn.Skipped; } - if (StatusReturn.Failed == statusReturn) + else if (StatusReturn.Failed == statusReturn) { ErrorMsgDispatcher(feedbackMsg); //return StatusReturn.Failed; // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - if (StatusReturn.Warning == statusReturn) + else if (StatusReturn.Warning == statusReturn) { WarningMsgDispatcher(feedbackMsg); //return StatusReturn.Failed;//TODO THW return warning? erroneousSequenceStep = true; } - #endregion -------------------------------- Check Calibration Values -------------------------------------- + else + { + SuccessMsgDispatcher(feedbackMsg); + } + #endregion #region ----------------------------------- Summarize Check Results --------------------------------------- @@ -647,6 +676,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - New IsSpecialApproved and IsStandardApproved. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckRequirements(out String feedbackMsg) { feedbackMsg = ""; @@ -658,26 +690,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr return EOLStatus.FAIL; } - // Check if requirement is active (free for production) and approved by a second person. Priority special - // requirement. - var isSpecialActive = false; - var isStandardActive = false; - if (ProductionRequirements.IsSpecialActive != null && (Boolean)ProductionRequirements.IsSpecialActive && - ProductionRequirements.IsSpecialApproved != null && (Boolean)ProductionRequirements.IsSpecialApproved) - isSpecialActive = true; - if (ProductionRequirements.IsStandardActive != null && (Boolean)ProductionRequirements.IsStandardActive && - ProductionRequirements.IsStandardApproved != null && (Boolean)ProductionRequirements.IsStandardApproved) - isStandardActive = true; - - // At least one requirement needs to be active and a requirement number and version has to be set - if ((!isStandardActive && !isSpecialActive) || - // The standard Id and version have always to be set even if the special is active - ProductionRequirements.StandardId == null || ProductionRequirements.StandardVersion == null || - // If the special is active the version and Id have to be defined - (isSpecialActive && (ProductionRequirements.SpecialId == null || - ProductionRequirements.SpecialVersion == null))) + var statusReturn = GenericChecks.CheckRequirements(ProductionRequirements, out feedbackMsg); + if (StatusReturn.Failed == statusReturn) { - feedbackMsg = Resources.StrErrorMsgRequirementInactive; EolProgress.RequirementRequestChecked = EOLStatus.FAIL; } else @@ -689,14 +704,6 @@ 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}" : - Resources.StrSuccessMsgRequirementActive + - $" Id.Ver {ProductionRequirements.StandardId}.{ProductionRequirements.StandardVersion}"; - EolProgress.RequirementRequestChecked = EOLStatus.OK; } @@ -715,23 +722,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Extracted from for better testability. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckProductionOrderNumber(out String feedbackMsg) { feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || - EolProgress == null || - ProductionRequirements.ProductionOrderNr != Meter.OrderNumber) + if (EolProgress == null || + StatusReturn.Failed == GenericChecks.CheckProductionOrderNumber(Meter, ProductionRequirements, + out feedbackMsg)) { if (EolProgress != null) EolProgress.RequirementOrderChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgRequirementProductionOrder; return EOLStatus.FAIL; } EolProgress.RequirementOrderChecked = EOLStatus.OK; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementProductionOrder} - " + - $"{Resources.StrLblOrderNumberTxt}: {Meter.OrderNumber}"; return EolProgress.RequirementOrderChecked; } @@ -749,38 +755,32 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Extracted from for better testability. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckPcbId(out String feedbackMsg) { feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || - EolProgress == null || - Meter.PcbId == null || - Meter.PcbId.Length < GenesisMeter.MinPcbIdLength) + if (EolProgress == null || + StatusReturn.Failed == GenericChecks.CheckPcbId(Meter, ProductionRequirements, out feedbackMsg)) { if (EolProgress != null) EolProgress.RequirementPcbIdChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgRequirementPcbId; return EOLStatus.FAIL; } if (ProductionRequirements.PcbId == null) { EolProgress.RequirementPcbIdChecked = EOLStatus.NA; - feedbackMsg = Resources.StrSuccessMsgOrderBasedRequirements; return EolProgress.RequirementPcbIdChecked; } - if (Meter.PcbId.Equals(EolProgress.PcbId.ToString()) && - Meter.PcbId.Equals(ProductionRequirements.PcbId.ToString())) + if (Meter.PcbId.Equals(EolProgress.PcbId.ToString())) { EolProgress.RequirementPcbIdChecked = EOLStatus.OK; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementPcbId} - PcbId: {Meter.PcbId}"; return EolProgress.RequirementPcbIdChecked; } EolProgress.RequirementPcbIdChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgRequirementPcbId; - return EolProgress.RequirementPcbIdChecked; } @@ -796,23 +796,21 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Extracted from for better testability. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckRegion(out String feedbackMsg) { feedbackMsg = ""; if (EolProgress == null || - ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.Region) || - string.IsNullOrEmpty(Meter.Region) || - !Meter.Region.Equals(ProductionRequirements.Region)) + StatusReturn.Failed == GenericChecks.CheckRegion(Meter, ProductionRequirements, out feedbackMsg)) { if (EolProgress != null) EolProgress.RequirementRegionChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgRequirementRegion; return EOLStatus.FAIL; } EolProgress.RequirementRegionChecked = EOLStatus.OK; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementRegion} - Region: {Meter.Region}"; return EolProgress.RequirementRegionChecked; } @@ -831,25 +829,21 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Set result to null on error. /// + /// + /// - Modified for generic checks. + /// private String CheckLutCrc(out String feedbackMsg) { feedbackMsg = ""; if (EolProgress == null || - Meter == null || - ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.LutCrc) || - string.IsNullOrEmpty(Meter.LutCrc) || - !Meter.LutCrc.Equals(ProductionRequirements.LutCrc)) + string.IsNullOrEmpty(GenericChecks.CheckLutCrc(Meter, ProductionRequirements, out feedbackMsg))) { - feedbackMsg = Resources.StrErrorMsgRequirementLut; if (EolProgress != null) EolProgress.ProductionStatusLutCrc = null; return ""; } EolProgress.ProductionStatusLutCrc = Meter.LutCrc; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementLut} - LUT CRC: {Meter.LutCrc}"; - return EolProgress.ProductionStatusLutCrc; } @@ -865,26 +859,21 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Extracted from for better testability. /// + /// + /// - Modified for generic checks. + /// private String CheckMeterSize(out String feedbackMsg) { feedbackMsg = ""; if (EolProgress == null || - Meter == null || - ProductionRequirements == null || string.IsNullOrEmpty(ProductionRequirements.MeterSize) || - string.IsNullOrEmpty(Meter.MeterSize) || - MeterSizeConverter.ConvertMeterSizeNameToEnum(Meter.MeterSize) != - MeterSizeConverter.ConvertMeterSizeNameToEnum(ProductionRequirements.MeterSize)) + string.IsNullOrEmpty(GenericChecks.CheckMeterSize(Meter, ProductionRequirements, out feedbackMsg))) { if (EolProgress != null) EolProgress.ProductionStatusMeterSize = null; - feedbackMsg = Resources.StrErrorMsgRequirementMeterSize; return ""; } EolProgress.ProductionStatusMeterSize = ProductionRequirements.MeterSize; - feedbackMsg = $"{Resources.StrSuccessMsgRequirementMeterSize} - " + - $"{Resources.StrLblMeterSizeTxt}: {Meter.MeterSize}"; - return EolProgress.ProductionStatusMeterSize; } @@ -968,90 +957,27 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Absolut maximal threshold even if alternative power consumption calculation. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckRemainingBatteryLoad(out String feedbackMsg) { + feedbackMsg = ""; if (EolProgress == null || - Meter == null || - ProductionRequirements?.MaxDrainedBatteryLoadPercentShipping == null || - ProductionStatus == null) + StatusReturn.Failed == GenericChecks.CheckRemainingBatteryLoad(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg)) { if (EolProgress != null) + { + EolProgress.ProductionStatusDrainedBatteryLoad = ProductionStatus.DrainedBatteryLoadPercent; EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; + } return EOLStatus.FAIL; } - // If the values for calculation of drained battery load and exceeded lifetime are not accessible - if (ProductionStatus.DrainedBatteryLoad_uAs == 0 || ProductionStatus.ExceededLifeTime_s == 0) - { - EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return EolProgress.ProductionStatusBatteryLoadChecked; - } - - // Set up the alternative calculation values needed for given current and supplement for production. - // These values will be set by the requirement and have a higher priority than the standard calculation - // based on the drained battery load and the estimated prediction based on this and the time of operation. - if (ProductionRequirements.QuiescentCurrent_uA > GenesisMeter.QuiescentCurrent_uA && - ProductionRequirements.EstimatedProductionBatteryLoadPercent > 0) - { - ProductionStatus.QuiescentCurrent_uA = ProductionRequirements.QuiescentCurrent_uA; - ProductionStatus.EstimatedProductionBatteryLoadPercent = - ProductionRequirements.EstimatedProductionBatteryLoadPercent; - } - - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus)) - { - EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return EolProgress.ProductionStatusBatteryLoadChecked; - } - - // Check battery load in percent and compare with requirements for limits for drained battery load - // For the alternative calculation based quiescent current and production supplement this will be used. - // Build message for required versus calculated lifetime - var threshold = ProductionStatus.AlternativeRequiredBatteryLoadPercent ?? - ProductionRequirements.MaxDrainedBatteryLoadPercentShipping; - - // Create an output message addon for alternative power consumption calculation - var strAlternativeCalc = ProductionStatus.AlternativeRequiredBatteryLoadPercent == null - ? "" - : $" - {Resources.StrMsgRequirementAbsolutLimitDrainedBattery}: " + - $"{ProductionRequirements.MaxDrainedBatteryLoadPercentShipping:F2} %" + - $" ({Resources.StrMsgAlternativeDrainedBatteryCalculation})"; - - var batteryLoad = $"{Resources.StrMsgDrainedBattery}: " + - // Actual calculated battery load based on readings from meter - $"{ProductionStatus.DrainedBatteryLoadPercent:F2} %" + - $" - {Resources.StrMsgRequirementLimitDrainedBattery}: " + - // Required battery load from standard or special requirement - $"{threshold:F2} % {strAlternativeCalc}"; - EolProgress.ProductionStatusDrainedBatteryLoad = ProductionStatus.DrainedBatteryLoadPercent; - - // This is the absolut limit even if the "AlternativeRequiredBatteryLoadPercent" will be used - if (ProductionStatus.DrainedBatteryLoadPercent > - ProductionRequirements.MaxDrainedBatteryLoadPercentShipping) - { - EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.FAIL; - feedbackMsg = $"{Resources.StrErrorMsg}: {batteryLoad}"; - return EolProgress.ProductionStatusBatteryLoadChecked; - } - - // This is the limit given by the "AlternativeRequiredBatteryLoadPercent" - if (ProductionStatus.AlternativeRequiredBatteryLoadPercent != null && - ProductionStatus.DrainedBatteryLoadPercent > ProductionStatus.AlternativeRequiredBatteryLoadPercent) - { - EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.FAIL; - feedbackMsg = $"{Resources.StrErrorMsg}: {batteryLoad}"; - return EolProgress.ProductionStatusBatteryLoadChecked; - } - EolProgress.ProductionStatusBatteryLoadChecked = EOLStatus.OK; - feedbackMsg = $"{Resources.StrSuccessMsg}: {batteryLoad}"; - - return EolProgress.ProductionStatusBatteryLoadChecked; + return EOLStatus.OK; } /// @@ -1069,53 +995,27 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Check required lifetime for unequal to 0. /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckRemainingLifetime(out String feedbackMsg) { + feedbackMsg = ""; if (EolProgress == null || - Meter == null || - ProductionRequirements?.RequiredLifeTimeYearsShipping == null || - ProductionRequirements.RequiredLifeTimeYearsShipping <= 0 || - ProductionStatus == null) + StatusReturn.Failed == GenericChecks.CheckRemainingLifetime(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg)) { if (EolProgress != null) + { + EolProgress.ProductionStatusRemainingLifeTime = ProductionStatus.RemainingLifeTimeYears; EolProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgLifeTimeCalculation; + } return EOLStatus.FAIL; } - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus)) - { - EolProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return EolProgress.ProductionStatusBatteryLoadChecked; - } - - // Build message for required versus calculated lifetime - var lifeTime = $"{Resources.StrMsgRemainingLifeTime}: " + - // Actual calculated lifetime based on readings from meter - $"{ProductionStatus.RemainingLifeTimeYears:F2} " + - $"{Resources.StrMsgYears}" + - $" - {Resources.StrMsgRequiredLifeTime}: " + - // Required lifetime from special or standard requirement - $"{ProductionRequirements.RequiredLifeTimeYearsShipping:F2} " + - $"{Resources.StrMsgYears}"; - EolProgress.ProductionStatusRemainingLifeTime = ProductionStatus.RemainingLifeTimeYears; - - // Check required years for shipping - if (ProductionRequirements.RequiredLifeTimeYearsShipping > ProductionStatus.RemainingLifeTimeYears) - { - EolProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.FAIL; - feedbackMsg = $"{Resources.StrErrorMsg}: {lifeTime}"; - } - else - { - feedbackMsg = $"{Resources.StrSuccessMsg}: {lifeTime}"; - EolProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.OK; - } - - return EolProgress.ProductionStatusRemainingLifeTimeChecked; + EolProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.OK; + return EOLStatus.OK; } /// @@ -1136,56 +1036,28 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Changed from "StatusReturn" to "EOLStatus". /// + /// + /// - Modified for generic checks. + /// private EOLStatus CheckStorageMonths(out String feedbackMsg) { - // Based on first attached battery and the POWEMON_TotalUsedSeconds (Kitron production date) and actual date + feedbackMsg = ""; if (EolProgress == null || - Meter == null || - ProductionRequirements?.MaxStorageMonths == null || - ProductionRequirements.MaxStorageMonths < 0.0 || - ProductionStatus == null || - ProductionStatus.DrainedBatteryLoad_uAs == 0 || - ProductionStatus.ExceededLifeTime_s == 0) + StatusReturn.Failed == GenericChecks.CheckStorageMonths(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg)) { if (EolProgress != null) + { EolProgress.MaxStorageMonthsChecked = EOLStatus.FAIL; - // Storage months requirement or Kitron production date unknown - feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; + EolProgress.MaxStorageMonths = ProductionRequirements.MaxStorageMonths; + } + return EOLStatus.FAIL; } - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus) || ProductionStatus.BatteryAssemblyDateTimeUtc == null) - { - EolProgress.MaxStorageMonthsChecked = EOLStatus.FAIL; - feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; - return EOLStatus.FAIL; - } - - var actualDate = DateTime.UtcNow.Date; - var batteryAssemblyDate = ProductionStatus.BatteryAssemblyDateTimeUtc.Value.Date; - // Give one day more as rounding issue - var expirationDate = batteryAssemblyDate.AddDays((Double)ProductionRequirements.MaxStorageMonths * GenesisStatusHandler.DAYS_PER_MONTH + 1.0); - var strStorageProduction = $"{Resources.StrLblKitronProductionDate}: " + - $"{ProductionStatus.BatteryAssemblyDateTimeUtc.Value:dd-MMM-yyyy} - " + - $"{Resources.StrLblExpirationDate}: {expirationDate:dd-MMM-yyyy} - " + - $"{Resources.StrLblMaxStorageMonths}: " + - $"{(Int32)ProductionRequirements.MaxStorageMonths} {Resources.StrLblMonths}"; - + EolProgress.MaxStorageMonthsChecked = EOLStatus.OK; EolProgress.MaxStorageMonths = ProductionRequirements.MaxStorageMonths; - if (actualDate >= expirationDate) - { - // Storage months exceeded - feedbackMsg = $"{Resources.StrErrorMsgRequirementMaximumStorageMonth} - " + strStorageProduction; - EolProgress.MaxStorageMonthsChecked = EOLStatus.FAIL; - } - else - { - feedbackMsg = $"{Resources.StrSuccessMsgRequirementMaximumStorageMonth} - " + strStorageProduction; - EolProgress.MaxStorageMonthsChecked = EOLStatus.OK; - } - - return EolProgress.MaxStorageMonthsChecked; + return EOLStatus.OK; } /// diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs index 37a1a667..69eb76c5 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -1,15 +1,17 @@ using LaaPackages.Features.Cordonel.Models; using Logic.ProductionToProductMapper.Files.Fw; +using Newtonsoft.Json; 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.Hardware.WaterMeter.Genesis.GenesisStatus; +using Xylem.Common.Logic.ProductionOrderCore.OrderData; using Xylem.Common.Logic.ProductionOrderCore.Vako; using Xylem.Common.Logic.SoftwareAccessHelper; using Xylem.Common.Production.ProductionUiCordonel.Properties; @@ -18,6 +20,444 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener { internal static class GenericChecks { + /// + /// Check the remaining lifetime + /// + /// + /// + /// + /// + /// true == assemblyLine, false == EOL + /// + /// + /// - Initial. + /// + public static StatusReturn CheckRemainingLifetime(IGenesisMeter meter, CordonelRequirements productionRequirements, + GenesisStatus productionStatus, out String feedbackMsg, Boolean assemblyLine = false) + { + if (meter == null || + productionRequirements == null || + (assemblyLine && productionRequirements.RequiredLifeTimeYearsAssembly == null) || + (assemblyLine && productionRequirements.RequiredLifeTimeYearsAssembly <= 0) || + (!assemblyLine && productionRequirements.RequiredLifeTimeYearsShipping == null) || + (!assemblyLine && productionRequirements.RequiredLifeTimeYearsShipping <= 0) || + productionStatus == null) + { + feedbackMsg = Resources.StrErrorMsgLifeTimeCalculation; + return StatusReturn.Failed; + } + + // Calculate the power consumption + if (!GenesisStatusHandler.CalculateLifeTime(productionStatus)) + { + feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; + return StatusReturn.Failed; + } + + // Decide which station Assembly-Line or Shipping-Line (EOL) + var strStation = assemblyLine + ? $"{productionRequirements.RequiredLifeTimeYearsAssembly:F2} %" + : $"{productionRequirements.RequiredLifeTimeYearsShipping:F2} %"; + // Build message for required versus calculated lifetime + var lifeTime = $"{Resources.StrMsgRemainingLifeTime}: " + + // Actual calculated lifetime based on readings from meter + $"{productionStatus.RemainingLifeTimeYears:F2} " + + $"{Resources.StrMsgYears}" + + $" - {Resources.StrMsgRequiredLifeTime}: " + + // Required lifetime from special or standard requirement + strStation + + $"{Resources.StrMsgYears}"; + + // Check required years for assembly + if ((assemblyLine && + productionRequirements.RequiredLifeTimeYearsAssembly > productionStatus.RemainingLifeTimeYears) || + (!assemblyLine && + productionRequirements.RequiredLifeTimeYearsShipping > productionStatus.RemainingLifeTimeYears)) + { + feedbackMsg = $"{Resources.StrErrorMsg}: {lifeTime}"; + return StatusReturn.Failed; + } + + feedbackMsg = $"{Resources.StrSuccessMsg}: {lifeTime}"; + return StatusReturn.Okay; + } + + /// + /// Check the months between first battery activation and now + /// + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static StatusReturn CheckStorageMonths(IGenesisMeter meter, CordonelRequirements productionRequirements, + GenesisStatus productionStatus, out String feedbackMsg) + { + // Based on first attached battery and the POWEMON_TotalUsedSeconds (Kitron production date) and actual date + if (meter == null || + productionRequirements?.MaxStorageMonths == null || + productionRequirements.MaxStorageMonths < 0.0 || + productionStatus == null || + productionStatus.DrainedBatteryLoad_uAs == 0 || + productionStatus.ExceededLifeTime_s == 0) + { + // Storage months requirement or Kitron production date unknown + feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; + return StatusReturn.Failed; + } + + // Calculate the power consumption + if (!GenesisStatusHandler.CalculateLifeTime(productionStatus) || productionStatus.BatteryAssemblyDateTimeUtc == null) + { + feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; + return StatusReturn.Failed; + } + + var actualDate = DateTime.UtcNow.Date; + var batteryAssemblyDate = productionStatus.BatteryAssemblyDateTimeUtc.Value.Date; + // Give one day more as rounding issue + var expirationDate = batteryAssemblyDate.AddDays((Double)productionRequirements.MaxStorageMonths * + GenesisStatusHandler.DAYS_PER_MONTH + 1.0); + var strStorageProduction = $"{Resources.StrLblKitronProductionDate}: " + + $"{productionStatus.BatteryAssemblyDateTimeUtc.Value:dd-MMM-yyyy} - " + + $"{Resources.StrLblExpirationDate}: {expirationDate:dd-MMM-yyyy} - " + + $"{Resources.StrLblMaxStorageMonths}: " + + $"{(Int32)productionRequirements.MaxStorageMonths} {Resources.StrLblMonths}"; + + if (actualDate >= expirationDate) + { + // Storage months exceeded + feedbackMsg = $"{Resources.StrErrorMsgRequirementMaximumStorageMonth} - " + strStorageProduction; + return StatusReturn.Failed; + } + + feedbackMsg = $"{Resources.StrSuccessMsgRequirementMaximumStorageMonth} - " + strStorageProduction; + return StatusReturn.Okay; + } + /// + /// Check the remaining battery load based on the thresholds which can be either: + /// - The AlternativeRequiredBatteryLoadPercent if the QuiescentCurrent_uA is set to a value greater than 50 uA + /// and the EstimatedProductionBatteryLoadPercent is greater than 0.0 % + /// and + /// - the MaxDrainedBatteryLoadPercentAssembly limits the threshold, + /// or only + /// - the MaxDrainedBatteryLoadPercentAssembly/Shipping limits the threshold as absolut limit. + /// + /// ATTENTION: The MaxDrainedBatteryLoadPercentAssembly/Shipping forces the absolut limit even if the alternative + /// calculation is being used. + /// + /// + /// + /// + /// + /// true == assemblyLine, false == EOL + /// + /// + /// - Initial. + /// + public static StatusReturn CheckRemainingBatteryLoad(IGenesisMeter meter, CordonelRequirements productionRequirements, + GenesisStatus productionStatus, out String feedbackMsg, Boolean assemblyLine = false) + { + if (meter == null || + productionRequirements == null || + (assemblyLine && productionRequirements.MaxDrainedBatteryLoadPercentAssembly == null) || + (!assemblyLine && productionRequirements.MaxDrainedBatteryLoadPercentShipping == null) || + productionStatus == null) + { + feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; + return StatusReturn.Failed; + } + + // If the values for calculation of drained battery load and exceeded lifetime are not accessible + if (productionStatus.DrainedBatteryLoad_uAs == 0 || productionStatus.ExceededLifeTime_s == 0) + { + feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; + return StatusReturn.Failed; + } + + // Set up the alternative calculation values needed for given current and supplement for production. + // These values will be set by the requirement and have a higher priority than the standard calculation + // based on the drained battery load and the estimated prediction based on this and the time of operation. + if (productionRequirements.QuiescentCurrent_uA > GenesisMeter.QuiescentCurrent_uA && + productionRequirements.EstimatedProductionBatteryLoadPercent > 0) + { + productionStatus.QuiescentCurrent_uA = productionRequirements.QuiescentCurrent_uA; + productionStatus.EstimatedProductionBatteryLoadPercent = + productionRequirements.EstimatedProductionBatteryLoadPercent; + } + + // Calculate the power consumption + if (!GenesisStatusHandler.CalculateLifeTime(productionStatus)) + { + feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; + return StatusReturn.Failed; + } + + // Check battery load in percent and compare with requirements for limits for drained battery load + // For the alternative calculation based quiescent current and production supplement this will be used. + // Build message for required versus calculated lifetime + Double? threshold; + if (assemblyLine) + { + threshold = productionStatus.AlternativeRequiredBatteryLoadPercent ?? + productionRequirements.MaxDrainedBatteryLoadPercentAssembly; + } + else + { + threshold = productionStatus.AlternativeRequiredBatteryLoadPercent ?? + productionRequirements.MaxDrainedBatteryLoadPercentShipping; + } + + // Decide which station Assembly-Line or Shipping-Line (EOL) + var strStation = assemblyLine + ? $"{productionRequirements.MaxDrainedBatteryLoadPercentAssembly:F2} %" + : $"{productionRequirements.MaxDrainedBatteryLoadPercentShipping:F2} %"; + + // Create an output message addon for alternative power consumption calculation + var strAlternativeCalc = productionStatus.AlternativeRequiredBatteryLoadPercent == null + ? "" + : $" - {Resources.StrMsgRequirementAbsolutLimitDrainedBattery}: " + strStation + + $" ({Resources.StrMsgAlternativeDrainedBatteryCalculation})"; + + var strBatLoad = $"{Resources.StrMsgDrainedBattery}: " + + // Actual calculated battery load based on readings from meter + $"{productionStatus.DrainedBatteryLoadPercent:F2} %" + + $" - {Resources.StrMsgRequirementLimitDrainedBattery}: " + + // Required battery load from standard or special requirement + $"{threshold:F2} % {strAlternativeCalc}"; + + + // This is the absolut limit even if the "AlternativeRequiredBatteryLoadPercent" will be used + if ((assemblyLine && productionStatus.DrainedBatteryLoadPercent > + productionRequirements.MaxDrainedBatteryLoadPercentAssembly) || + (!assemblyLine && productionStatus.DrainedBatteryLoadPercent > + productionRequirements.MaxDrainedBatteryLoadPercentShipping)) + { + feedbackMsg = $"{Resources.StrErrorMsg}: {strBatLoad}"; + return StatusReturn.Failed; + } + + // This is the limit given by the "AlternativeRequiredBatteryLoadPercent" + if (productionStatus.AlternativeRequiredBatteryLoadPercent != null && + productionStatus.DrainedBatteryLoadPercent > productionStatus.AlternativeRequiredBatteryLoadPercent) + { + feedbackMsg = $"{Resources.StrErrorMsg}: {strBatLoad}"; + return StatusReturn.Failed; + } + + feedbackMsg = $"{Resources.StrSuccessMsg}: {strBatLoad}"; + + return StatusReturn.Okay; + } + + /// + /// Check meter size + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static String CheckMeterSize(IGenesisMeter meter, CordonelRequirements productionRequirements, + out String feedbackMsg) + { + feedbackMsg = ""; + if (meter == null || + productionRequirements == null || string.IsNullOrEmpty(productionRequirements.MeterSize) || + string.IsNullOrEmpty(meter.MeterSize) || + MeterSizeConverter.ConvertMeterSizeNameToEnum(meter.MeterSize) != + MeterSizeConverter.ConvertMeterSizeNameToEnum(productionRequirements.MeterSize)) + { + feedbackMsg = Resources.StrErrorMsgRequirementMeterSize; + return ""; + } + + feedbackMsg = $"{Resources.StrSuccessMsgRequirementMeterSize} - " + + $"{Resources.StrLblMeterSizeTxt}: {meter.MeterSize}"; + + return productionRequirements.MeterSize; + } + + /// + /// Check PcbId of meter and requirements. Mark PcbId as skipped if + /// production requirements PcbId is null as this is the indication that all Cordonels + /// assigned to this production order are produced according to this requirement. + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static StatusReturn CheckPcbId(IGenesisMeter meter, CordonelRequirements productionRequirements, + out String feedbackMsg) + { + feedbackMsg = ""; + if (meter == null || + productionRequirements == null || + meter.PcbId == null || + meter.PcbId.Length < GenesisMeter.MinPcbIdLength) + { + feedbackMsg = Resources.StrErrorMsgRequirementPcbId; + return StatusReturn.Failed; + } + + if (productionRequirements.PcbId == null) + { + feedbackMsg = Resources.StrSuccessMsgOrderBasedRequirements; + return StatusReturn.Okay; + } + if (meter.PcbId.Equals(productionRequirements.PcbId.ToString())) + { + feedbackMsg = $"{Resources.StrSuccessMsgRequirementPcbId} - PcbId: {meter.PcbId}"; + return StatusReturn.Okay; + } + + feedbackMsg = Resources.StrErrorMsgRequirementPcbId; + return StatusReturn.Failed; + } + + /// + /// Check production order number between meter and requirements. + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static StatusReturn CheckProductionOrderNumber(IGenesisMeter meter, CordonelRequirements productionRequirements, + out String feedbackMsg) + { + feedbackMsg = ""; + if (meter == null || + productionRequirements == null || + productionRequirements.ProductionOrderNr != meter.OrderNumber) + { + feedbackMsg = Resources.StrErrorMsgRequirementProductionOrder; + return StatusReturn.Failed; + } + + feedbackMsg = $"{Resources.StrSuccessMsgRequirementProductionOrder} - " + + $"{Resources.StrLblOrderNumberTxt}: {meter.OrderNumber}"; + return StatusReturn.Okay; + } + + /// + /// Check region between meter and requirements + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static StatusReturn CheckRegion(IGenesisMeter meter, CordonelRequirements productionRequirements, out String feedbackMsg) + { + feedbackMsg = ""; + if (productionRequirements == null || + string.IsNullOrEmpty(productionRequirements.Region) || + string.IsNullOrEmpty(meter.Region) || + !meter.Region.Equals(productionRequirements.Region)) + { + feedbackMsg = Resources.StrErrorMsgRequirementRegion; + return StatusReturn.Failed; + } + + feedbackMsg = $"{Resources.StrSuccessMsgRequirementRegion} - Region: {meter.Region}"; + return StatusReturn.Okay; + } + /// + /// Check Look-Up-Table (LUT) for metrology calibration values for the checksum (CRC) of this table + /// + /// + /// + /// + /// + /// + /// - Initial. + /// + public static String CheckLutCrc(IGenesisMeter meter, CordonelRequirements productionRequirements, out String feedbackMsg) + { + feedbackMsg = ""; + if (meter == null || + productionRequirements == null || + string.IsNullOrEmpty(productionRequirements.LutCrc) || + string.IsNullOrEmpty(meter.LutCrc) || + !meter.LutCrc.Equals(productionRequirements.LutCrc)) + { + feedbackMsg = Resources.StrErrorMsgRequirementLut; + return ""; + } + + feedbackMsg = $"{Resources.StrSuccessMsgRequirementLut} - LUT CRC: {meter.LutCrc}"; + + return meter.LutCrc; + } + + /// + /// Check for requirement permission special or standard or none: + /// - If the special requirement is active all fields a filled with the according values from this "special" + /// requirement, + /// - Else those fields contain the "standard" requirements! + /// + /// + /// + /// + /// + /// - Initial. + /// + public static StatusReturn CheckRequirements(CordonelRequirements productionRequirements, out String feedbackMsg) + { + feedbackMsg = ""; + if (productionRequirements == null) + { + feedbackMsg = Resources.StrErrorMsgProductionRequirements; + return StatusReturn.Failed; + } + + // Check if requirement is active (free for production) and approved by a second person. Priority special + // requirement. + var isSpecialActive = false; + var isStandardActive = false; + if (productionRequirements.IsSpecialActive != null && (Boolean)productionRequirements.IsSpecialActive && + productionRequirements.IsSpecialApproved != null && (Boolean)productionRequirements.IsSpecialApproved) + isSpecialActive = true; + if (productionRequirements.IsStandardActive != null && (Boolean)productionRequirements.IsStandardActive && + productionRequirements.IsStandardApproved != null && (Boolean)productionRequirements.IsStandardApproved) + isStandardActive = true; + + // At least one requirement needs to be active and a requirement number and version has to be set + if ((!isStandardActive && !isSpecialActive) || + // The standard Id and version have always to be set even if the special is active + productionRequirements.StandardId == null || productionRequirements.StandardVersion == null || + // If the special is active the version and Id have to be defined + (isSpecialActive && (productionRequirements.SpecialId == null || + productionRequirements.SpecialVersion == null))) + { + feedbackMsg = Resources.StrErrorMsgRequirementInactive; + return StatusReturn.Failed; + } + + feedbackMsg = isSpecialActive && + productionRequirements.SpecialId != null && + productionRequirements.SpecialVersion != null ? + Resources.StrWarningMsgSpecialRequirementActive + + $" Id.Ver: {productionRequirements.SpecialId}.{productionRequirements.SpecialVersion}" : + Resources.StrSuccessMsgRequirementActive + + $" Id.Ver {productionRequirements.StandardId}.{productionRequirements.StandardVersion}"; + + + return StatusReturn.Okay; + } /// /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. /// @@ -32,6 +472,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// /// - Import from CheckProductionState for common use. /// + /// + /// - Extended radio parameter. + /// public static StatusReturn CheckKitronRadioSignalLevels(IGenesisMeter meter, RegisterRestorer registerRestorer, Boolean skipRadioCheck, out String feedbackMsg) { @@ -43,11 +486,17 @@ 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) + // The NA region has no radio + if (meter.Region.Equals("NA")) { return StatusReturn.Skipped; } + // The radio check should be ignored + if (skipRadioCheck) + { + feedbackMsg = Resources.StrSkippedMsgRadioCheckSpecialPermission; + return StatusReturn.Warning; + } var pressureSensorAssembled = meter.PressureSensorAssembled ? $", {Resources.StrLblPressureSensorAssembledTxt}" : ""; var meterInfo = $"{Resources.StrLblRadioFrequencyTxt}: {meter.RadioFrequencyMhz} MHz," + @@ -55,13 +504,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener $"{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"))) - { - feedbackMsg = Resources.StrErrorMsgRadioSignalLevels + " " + meterInfo; - return StatusReturn.Failed; + if (!registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_PowerLevel")) || + !registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_PowerLevelOption")) || + !registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_ImpedanceCodeNew")) || + !registerRestorer.RecoveryRegisters.Any(x => x.RegisterIdent.Equals("SENSUSRADIO_ImpedanceCodeOption")) ) + { + feedbackMsg = Resources.StrErrorMsgRadioSignalLevels + " " + meterInfo; + return StatusReturn.Failed; } - feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels + ". " + meterInfo; + feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels + " - " + meterInfo; return StatusReturn.Okay; } diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs index 7e4efa18..36b539c8 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs @@ -6,7 +6,6 @@ using Xylem.Common.CommonCore.Consts; 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; @@ -149,19 +148,20 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki /// - Region, /// - FW, /// - LUT CRC, - /// - Meter size + /// - Meter size, + /// - Kitron radio parameter, /// - Drained battery load versus required remaining battery load in percent, /// - Remaining run time in years, /// /// - /// + /// /// - Initial. /// public override StatusReturn ExecuteProcess() { #region ----------------------------------- Check Requirements -------------------------------------------- - var statusReturn = CheckRequirements(out var feedbackMsg); + var statusReturn = GenericChecks.CheckRequirements(ProductionRequirements, out var feedbackMsg); if (StatusReturn.Failed == statusReturn) { ErrorMsgDispatcher(feedbackMsg); @@ -175,7 +175,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Production Order ---------------------------------------- // Production order - if (StatusReturn.Failed == CheckProductionOrderNumber(out feedbackMsg)) + if (StatusReturn.Failed == GenericChecks.CheckProductionOrderNumber(Meter, ProductionRequirements, + out feedbackMsg)) { ErrorMsgDispatcher(feedbackMsg); return StatusReturn.Failed; @@ -187,7 +188,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check PCBID --------------------------------------------------- // PCBID read from meter compared with requirement PcbIds - statusReturn = CheckPcbId(out feedbackMsg); + statusReturn = GenericChecks.CheckPcbId(Meter, ProductionRequirements, out feedbackMsg); // Exit here with error if (StatusReturn.Failed == statusReturn) @@ -202,7 +203,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Region -------------------------------------------------- - if (StatusReturn.Failed == CheckRegion(out feedbackMsg)) + if (StatusReturn.Failed == GenericChecks.CheckRegion(Meter, ProductionRequirements, out feedbackMsg)) { ErrorMsgDispatcher(feedbackMsg); return StatusReturn.Failed; @@ -214,7 +215,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check LUT CRC ------------------------------------------------- - if (string.IsNullOrEmpty(CheckLutCrc(out feedbackMsg))) + if (string.IsNullOrEmpty(GenericChecks.CheckLutCrc(Meter, ProductionRequirements, out feedbackMsg))) { ErrorMsgDispatcher(feedbackMsg); return StatusReturn.Failed; @@ -226,7 +227,20 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Meter Size ---------------------------------------------- - if (string.IsNullOrEmpty(CheckMeterSize(out feedbackMsg))) + if (string.IsNullOrEmpty(GenericChecks.CheckMeterSize(Meter, ProductionRequirements, out feedbackMsg))) + { + ErrorMsgDispatcher(feedbackMsg); + return StatusReturn.Failed; + } + + SuccessMsgDispatcher(feedbackMsg); + ActualProcessProgress++; + #endregion + + #region ----------------------------------- Check Firmware and Apps --------------------------------------- + + if (string.IsNullOrEmpty(GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, + out feedbackMsg))) { ErrorMsgDispatcher(feedbackMsg); return StatusReturn.Failed; @@ -238,13 +252,24 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Kitron Radio Signal Levels ------------------------------ - statusReturn = CheckKitronRadioSignalLevels(out feedbackMsg); + var erroneousSequenceStep = false; + var warningSequenceStep = false; + statusReturn = GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, ProductionRequirements.SkipRadioCheck, + out feedbackMsg); + if (StatusReturn.Failed == statusReturn) { ErrorMsgDispatcher(feedbackMsg); - return StatusReturn.Failed; + //return StatusReturn.Failed; + // Do not return immediately to avoid multiple special-requirements on multiple errors + erroneousSequenceStep = true; } - if (StatusReturn.Okay == statusReturn) + else if (StatusReturn.Warning == statusReturn) + { + WarningMsgDispatcher(feedbackMsg); + warningSequenceStep = true; + } + else { SuccessMsgDispatcher(feedbackMsg); } @@ -252,57 +277,56 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki ActualProcessProgress++; #endregion - #region ----------------------------------- Check Firmware and Apps --------------------------------------- - - if (string.IsNullOrEmpty(CheckFwAndApps(out feedbackMsg))) - { - ErrorMsgDispatcher(feedbackMsg); - return StatusReturn.Failed; - } - - SuccessMsgDispatcher(feedbackMsg); - ActualProcessProgress++; - #endregion - #region ----------------------------------- Check Remaining Battery Load ---------------------------------- - var erroneousSequenceStep = false; - if (StatusReturn.Failed == CheckRemainingBatteryLoad(out feedbackMsg)) + if (StatusReturn.Failed == GenericChecks.CheckRemainingBatteryLoad(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg, true)) { ErrorMsgDispatcher(feedbackMsg); //return StatusReturn.Failed; // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion #region ----------------------------------- Check Remaining Life Time ------------------------------------- - if (StatusReturn.Failed == CheckRemainingLifetime(out feedbackMsg)) + if (StatusReturn.Failed == GenericChecks.CheckRemainingLifetime(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg, true)) { ErrorMsgDispatcher(feedbackMsg); //return StatusReturn.Failed; // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion #region ----------------------------------- Check Storage Months ------------------------------------------ - if (StatusReturn.Failed == CheckStorageMonths(out feedbackMsg)) + if (StatusReturn.Failed == GenericChecks.CheckStorageMonths(Meter, ProductionRequirements, + ProductionStatus, out feedbackMsg)) { ErrorMsgDispatcher(feedbackMsg); //return StatusReturn.Failed; // Do not return immediately to avoid multiple special-requirements on multiple errors erroneousSequenceStep = true; } - SuccessMsgDispatcher(feedbackMsg); + else + { + SuccessMsgDispatcher(feedbackMsg); + } ActualProcessProgress++; #endregion @@ -313,6 +337,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki if (erroneousSequenceStep) return StatusReturn.Failed; + // One or more checks generated a warning + if (warningSequenceStep) + return StatusReturn.Skipped; + // Here everything went fine SuccessMsgDispatcher(feedbackMsg); @@ -336,473 +364,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki MessageBox.Show(errorMsg, Resources.StrProcessStateError, MessageBoxButton.OK, MessageBoxImage.Error); return StatusReturn.Failed; } - - /// - /// Check for requirement permission special or standard or none: - /// - If the special requirement is active all fields a filled with the according values from this "special" - /// requirement, - /// - Else those fields contain the "standard" requirements! - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_001]_Check_Requirements - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckRequirements(out String feedbackMsg) - { - feedbackMsg = ""; - if (ProductionRequirements == null) - { - feedbackMsg = Resources.StrErrorMsgProductionRequirements; - return StatusReturn.Failed; - } - - // Check if requirement is active (free for production) and approved by a second person. Priority special - // requirement. - var isSpecialActive = false; - var isStandardActive = false; - if (ProductionRequirements.IsSpecialActive != null && (Boolean)ProductionRequirements.IsSpecialActive && - ProductionRequirements.IsSpecialApproved != null && (Boolean)ProductionRequirements.IsSpecialApproved) - isSpecialActive = true; - if (ProductionRequirements.IsStandardActive != null && (Boolean)ProductionRequirements.IsStandardActive && - ProductionRequirements.IsStandardApproved != null && (Boolean)ProductionRequirements.IsStandardApproved) - isStandardActive = true; - - // At least one requirement needs to be active and a requirement number and version has to be set - if ((!isStandardActive && !isSpecialActive) || - // The standard Id and version have always to be set even if the special is active - ProductionRequirements.StandardId == null || ProductionRequirements.StandardVersion == null || - // If the special is active the version and Id have to be defined - (isSpecialActive && (ProductionRequirements.SpecialId == null || - ProductionRequirements.SpecialVersion == null))) - { - feedbackMsg = Resources.StrErrorMsgRequirementInactive; - return StatusReturn.Failed; - } - - feedbackMsg = isSpecialActive && - ProductionRequirements.SpecialId != null && - ProductionRequirements.SpecialVersion != null ? - Resources.StrWarningMsgSpecialRequirementActive + - $" Id.Ver: {ProductionRequirements.SpecialId}.{ProductionRequirements.SpecialVersion}" : - Resources.StrSuccessMsgRequirementActive + - $" Id.Ver {ProductionRequirements.StandardId}.{ProductionRequirements.StandardVersion}"; - - - return StatusReturn.Okay; - } - - /// - /// Check production order number between meter and requirements. - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_002]_Check_ProductionOrderNo - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckProductionOrderNumber(out String feedbackMsg) - { - feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || - ProductionRequirements.ProductionOrderNr != Meter.OrderNumber) - { - feedbackMsg = Resources.StrErrorMsgRequirementProductionOrder; - return StatusReturn.Failed; - } - - feedbackMsg = $"{Resources.StrSuccessMsgRequirementProductionOrder} - " + - $"{Resources.StrLblOrderNumberTxt}: {Meter.OrderNumber}"; - return StatusReturn.Okay; - } - - /// - /// Check PcbId of meter and requirements. Mark PcbId as skipped if - /// production requirements PcbId is null as this is the indication that all Cordonels - /// assigned to this production order are produced according to this requirement. - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_003]_Check_PcbId - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckPcbId(out String feedbackMsg) - { - feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || - Meter.PcbId == null || - Meter.PcbId.Length < GenesisMeter.MinPcbIdLength) - { - feedbackMsg = Resources.StrErrorMsgRequirementPcbId; - return StatusReturn.Failed; - } - - if (ProductionRequirements.PcbId == null) - { - feedbackMsg = Resources.StrSuccessMsgOrderBasedRequirements; - return StatusReturn.Okay; - } - if (Meter.PcbId.Equals(ProductionRequirements.PcbId.ToString())) - { - feedbackMsg = $"{Resources.StrSuccessMsgRequirementPcbId} - PcbId: {Meter.PcbId}"; - return StatusReturn.Okay; - } - - feedbackMsg = Resources.StrErrorMsgRequirementPcbId; - return StatusReturn.Failed; - } - - /// - /// Check region between meter and requirements - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_004]_Check_Region - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckRegion(out String feedbackMsg) - { - feedbackMsg = ""; - if (ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.Region) || - string.IsNullOrEmpty(Meter.Region) || - !Meter.Region.Equals(ProductionRequirements.Region)) - { - feedbackMsg = Resources.StrErrorMsgRequirementRegion; - return StatusReturn.Failed; - } - - feedbackMsg = $"{Resources.StrSuccessMsgRequirementRegion} - Region: {Meter.Region}"; - return StatusReturn.Okay; - } - - /// - /// Check Look-Up-Table (LUT) for metrology calibration values for the checksum (CRC) of this table - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_005]_Check_LUT_CRC - /// - /// - /// - /// - /// - /// - Initial. - /// - private String CheckLutCrc(out String feedbackMsg) - { - feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || - string.IsNullOrEmpty(ProductionRequirements.LutCrc) || - string.IsNullOrEmpty(Meter.LutCrc) || - !Meter.LutCrc.Equals(ProductionRequirements.LutCrc)) - { - feedbackMsg = Resources.StrErrorMsgRequirementLut; - return ""; - } - - feedbackMsg = $"{Resources.StrSuccessMsgRequirementLut} - LUT CRC: {Meter.LutCrc}"; - - return Meter.LutCrc; - } - - /// - /// Check meter size - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_006]_Check_Meter_Size - /// - /// - /// - /// - /// - /// - Initial. - /// - private String CheckMeterSize(out String feedbackMsg) - { - feedbackMsg = ""; - if (Meter == null || - ProductionRequirements == null || string.IsNullOrEmpty(ProductionRequirements.MeterSize) || - string.IsNullOrEmpty(Meter.MeterSize) || - MeterSizeConverter.ConvertMeterSizeNameToEnum(Meter.MeterSize) != - MeterSizeConverter.ConvertMeterSizeNameToEnum(ProductionRequirements.MeterSize)) - { - feedbackMsg = Resources.StrErrorMsgRequirementMeterSize; - return ""; - } - - feedbackMsg = $"{Resources.StrSuccessMsgRequirementMeterSize} - " + - $"{Resources.StrLblMeterSizeTxt}: {Meter.MeterSize}"; - - 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, ProductionRequirements.SkipRadioCheck, - 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 - /// 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). - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_008]_Check_FW_and_Apps - /// - /// - /// - /// - /// - /// - Initial. - /// - /// - /// - Exported to generic tests. - /// - private String CheckFwAndApps(out String feedbackMsg) - { - return GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, out feedbackMsg); - } - - /// - /// Check the remaining battery load based on the thresholds which can be either: - /// - The AlternativeRequiredBatteryLoadPercent if the QuiescentCurrent_uA is set to a value greater than 50 uA - /// and the EstimatedProductionBatteryLoadPercent is greater than 0.0 % - /// and - /// - the MaxDrainedBatteryLoadPercentAssembly limits the threshold, - /// or only - /// - the MaxDrainedBatteryLoadPercentAssembly limits the threshold as absolut limit. - /// - /// ATTENTION: The MaxDrainedBatteryLoadPercentAssembly forces the absolut limit even if the alternative - /// calculation is being used. - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_009]_Check_Remaining_Battery_Load - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckRemainingBatteryLoad(out String feedbackMsg) - { - if (Meter == null || - ProductionRequirements?.MaxDrainedBatteryLoadPercentAssembly == null || - ProductionStatus == null) - { - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return StatusReturn.Failed; - } - - // If the values for calculation of drained battery load and exceeded lifetime are not accessible - if (ProductionStatus.DrainedBatteryLoad_uAs == 0 || ProductionStatus.ExceededLifeTime_s == 0) - { - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return StatusReturn.Failed; - } - - // Set up the alternative calculation values needed for given current and supplement for production. - // These values will be set by the requirement and have a higher priority than the standard calculation - // based on the drained battery load and the estimated prediction based on this and the time of operation. - if (ProductionRequirements.QuiescentCurrent_uA > GenesisMeter.QuiescentCurrent_uA && - ProductionRequirements.EstimatedProductionBatteryLoadPercent > 0) - { - ProductionStatus.QuiescentCurrent_uA = ProductionRequirements.QuiescentCurrent_uA; - ProductionStatus.EstimatedProductionBatteryLoadPercent = - ProductionRequirements.EstimatedProductionBatteryLoadPercent; - } - - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus)) - { - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return StatusReturn.Failed; - } - - // Check battery load in percent and compare with requirements for limits for drained battery load - // For the alternative calculation based quiescent current and production supplement this will be used. - // Build message for required versus calculated lifetime - var threshold = ProductionStatus.AlternativeRequiredBatteryLoadPercent ?? - ProductionRequirements.MaxDrainedBatteryLoadPercentAssembly; - - // Create an output message addon for alternative power consumption calculation - var strAlternativeCalc = ProductionStatus.AlternativeRequiredBatteryLoadPercent == null - ? "" - : $" - {Resources.StrMsgRequirementAbsolutLimitDrainedBattery}: " + - $"{ProductionRequirements.MaxDrainedBatteryLoadPercentAssembly:F2} %" + - $" ({Resources.StrMsgAlternativeDrainedBatteryCalculation})"; - - var batteryLoad = $"{Resources.StrMsgDrainedBattery}: " + - // Actual calculated battery load based on readings from meter - $"{ProductionStatus.DrainedBatteryLoadPercent:F2} %" + - $" - {Resources.StrMsgRequirementLimitDrainedBattery}: " + - // Required battery load from standard or special requirement - $"{threshold:F2} % {strAlternativeCalc}"; - - - // This is the absolut limit even if the "AlternativeRequiredBatteryLoadPercent" will be used - if (ProductionStatus.DrainedBatteryLoadPercent > - ProductionRequirements.MaxDrainedBatteryLoadPercentAssembly) - { - feedbackMsg = $"{Resources.StrErrorMsg}: {batteryLoad}"; - return StatusReturn.Failed; - } - - // This is the limit given by the "AlternativeRequiredBatteryLoadPercent" - if (ProductionStatus.AlternativeRequiredBatteryLoadPercent != null && - ProductionStatus.DrainedBatteryLoadPercent > ProductionStatus.AlternativeRequiredBatteryLoadPercent) - { - feedbackMsg = $"{Resources.StrErrorMsg}: {batteryLoad}"; - return StatusReturn.Failed; - } - - feedbackMsg = $"{Resources.StrSuccessMsg}: {batteryLoad}"; - - return StatusReturn.Okay; - } - - /// - /// Check the remaining lifetime - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_010]_Check_Remaining_Lifetime - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckRemainingLifetime(out String feedbackMsg) - { - if (Meter == null || - ProductionRequirements?.RequiredLifeTimeYearsAssembly == null || - ProductionRequirements.RequiredLifeTimeYearsAssembly <= 0 || - ProductionStatus == null) - { - feedbackMsg = Resources.StrErrorMsgLifeTimeCalculation; - return StatusReturn.Failed; - } - - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus)) - { - feedbackMsg = Resources.StrErrorMsgBatteryLoadCalculation; - return StatusReturn.Failed; - } - - // Build message for required versus calculated lifetime - var lifeTime = $"{Resources.StrMsgRemainingLifeTime}: " + - // Actual calculated lifetime based on readings from meter - $"{ProductionStatus.RemainingLifeTimeYears:F2} " + - $"{Resources.StrMsgYears}" + - $" - {Resources.StrMsgRequiredLifeTime}: " + - // Required lifetime from special or standard requirement - $"{ProductionRequirements.RequiredLifeTimeYearsAssembly:F2} " + - $"{Resources.StrMsgYears}"; - - // Check required years for assembly - if (ProductionRequirements.RequiredLifeTimeYearsAssembly > ProductionStatus.RemainingLifeTimeYears) - { - feedbackMsg = $"{Resources.StrErrorMsg}: {lifeTime}"; - return StatusReturn.Failed; - } - - feedbackMsg = $"{Resources.StrSuccessMsg}: {lifeTime}"; - return StatusReturn.Okay; - } - - /// - /// Check the months between first battery activation and now - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_011]_Check_Storage_Months - /// - /// - /// - /// - /// - /// - Initial. - /// - private StatusReturn CheckStorageMonths(out String feedbackMsg) - { - // Based on first attached battery and the POWEMON_TotalUsedSeconds (Kitron production date) and actual date - if (Meter == null || - ProductionRequirements?.MaxStorageMonths == null || - ProductionRequirements.MaxStorageMonths < 0.0 || - ProductionStatus == null || - ProductionStatus.DrainedBatteryLoad_uAs == 0 || - ProductionStatus.ExceededLifeTime_s == 0) - { - // Storage months requirement or Kitron production date unknown - feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; - return StatusReturn.Failed; - } - - // Calculate the power consumption - if (!GenesisStatusHandler.CalculateLifeTime(ProductionStatus) || ProductionStatus.BatteryAssemblyDateTimeUtc == null) - { - feedbackMsg = Resources.StrErrorMsgRequirementMaximumStorageMonthUnknown; - return StatusReturn.Failed; - } - - var actualDate = DateTime.UtcNow.Date; - var batteryAssemblyDate = ProductionStatus.BatteryAssemblyDateTimeUtc.Value.Date; - // Give one day more as rounding issue - var expirationDate = batteryAssemblyDate.AddDays((Double)ProductionRequirements.MaxStorageMonths * GenesisStatusHandler.DAYS_PER_MONTH + 1.0); - var strStorageProduction = $"{Resources.StrLblKitronProductionDate}: " + - $"{ProductionStatus.BatteryAssemblyDateTimeUtc.Value:dd-MMM-yyyy} - " + - $"{Resources.StrLblExpirationDate}: {expirationDate:dd-MMM-yyyy} - " + - $"{Resources.StrLblMaxStorageMonths}: " + - $"{(Int32)ProductionRequirements.MaxStorageMonths} {Resources.StrLblMonths}"; - - if (actualDate >= expirationDate) - { - // Storage months exceeded - feedbackMsg = $"{Resources.StrErrorMsgRequirementMaximumStorageMonth} - " + strStorageProduction; - return StatusReturn.Failed; - } - - feedbackMsg = $"{Resources.StrSuccessMsgRequirementMaximumStorageMonth} - " + strStorageProduction; - return StatusReturn.Okay; - } } }