diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index a96975d6..4906d74a 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; @@ -693,23 +692,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; } @@ -727,38 +725,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; } @@ -774,23 +766,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; } @@ -809,25 +799,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; } @@ -843,26 +829,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; } @@ -946,90 +927,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; } /// @@ -1047,53 +965,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; } /// @@ -1114,56 +1006,23 @@ 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; 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.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; + EolProgress.MaxStorageMonthsChecked = EOLStatus.OK; + return EOLStatus.OK; } /// diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs index 08a69bbe..c0894307 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -1,16 +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 System.Threading; -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; @@ -19,15 +20,394 @@ 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! - /// - /// Software Requirement Specification: - /// [SRS_TBF_PICK_PP_CHECK_PROD_STATE_001]_Check_Requirements - /// /// /// /// @@ -48,7 +428,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener // requirement. var isSpecialActive = false; var isStandardActive = false; - if (productionRequirements.IsSpecialActive != null && (Boolean)productionRequirements.IsSpecialActive && + if (productionRequirements.IsSpecialActive != null && (Boolean)productionRequirements.IsSpecialActive && productionRequirements.IsSpecialApproved != null && (Boolean)productionRequirements.IsSpecialApproved) isSpecialActive = true; if (productionRequirements.IsStandardActive != null && (Boolean)productionRequirements.IsStandardActive && @@ -78,7 +458,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener return StatusReturn.Okay; } - /// + /// /// Check the measurements from Kitron for this specific Cordonel if it is an EMEA region. /// /// @@ -117,8 +497,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener // 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; + feedbackMsg = Resources.StrErrorMsgRadioSignalLevels + " " + meterInfo; + return StatusReturn.Failed; } feedbackMsg = Resources.StrSuccessMsgRadioSignalLevels + " - " + meterInfo; diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/PickingProcesses/CheckProductionState.cs index c53d57ff..1a0dd36d 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; @@ -175,7 +174,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 +187,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 +202,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 +214,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 +226,7 @@ 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; @@ -238,7 +238,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Kitron Radio Signal Levels ------------------------------ - statusReturn = CheckKitronRadioSignalLevels(out feedbackMsg); + statusReturn = GenericChecks.CheckKitronRadioSignalLevels(Meter, RegisterRestorer, + ProductionRequirements.SkipRadioCheck,out feedbackMsg); if (StatusReturn.Failed == statusReturn) { ErrorMsgDispatcher(feedbackMsg); @@ -254,7 +255,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #region ----------------------------------- Check Firmware and Apps --------------------------------------- - if (string.IsNullOrEmpty(CheckFwAndApps(out feedbackMsg))) + if (string.IsNullOrEmpty(GenericChecks.CheckFwAndApps(Meter, ProductionRequirements, FwUpdatePackage, + out feedbackMsg))) { ErrorMsgDispatcher(feedbackMsg); return StatusReturn.Failed; @@ -267,7 +269,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #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; @@ -281,7 +284,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #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; @@ -295,7 +299,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Picki #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; @@ -336,473 +341,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; - } } }