diff --git a/Common/.shared/SharedAssemblyInfo.cs b/Common/.shared/SharedAssemblyInfo.cs index 5d4e6217..625b4677 100644 --- a/Common/.shared/SharedAssemblyInfo.cs +++ b/Common/.shared/SharedAssemblyInfo.cs @@ -13,4 +13,4 @@ using System.Reflection; // //[assembly: AssemblyVersion("1.2.*.0")] -[assembly: AssemblyVersion("2.7.4.*")] +[assembly: AssemblyVersion("2.7.5.*")] diff --git a/Common/Common.sln.DotSettings b/Common/Common.sln.DotSettings index fba34e5b..d76a8661 100644 --- a/Common/Common.sln.DotSettings +++ b/Common/Common.sln.DotSettings @@ -33,6 +33,7 @@ True True True + True True True True diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json index f81206a2..fe1e8e62 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/configuration.json @@ -18469,7 +18469,7 @@ }, "description": "", "version": { - "first": 69, + "first": 72, "last": 72 }, "statictype": "dynamic", diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs index 75b3a16e..16fecc89 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs @@ -7,6 +7,16 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus /// public class GenesisStatus { + /// + /// Remaining lifetime for Cordonel in years based on FW calculation. + /// + public Double? FwCalculatedRemainingLifeTimeYears { get; set; } + + /// + /// Remaining lifetime for Cordonel in seconds based on FW calculation. + /// + public UInt64? FwCalculatedRemainingLifeTime_s { get; set; } + /// /// Remaining lifetime for Cordonel in years based on battery drainage. /// diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs index 17648d2a..a6a2b075 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs @@ -280,6 +280,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus /// /// - errorMsg. /// + /// + /// - Readout FW based calculation of remaining lifetime in seconds. + /// public static Boolean BuildLifeTimeInformation(IGenesisMeter currentGenesis, GenesisStatus status, out String errorMsg) { Boolean retVal; @@ -302,6 +305,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus status.InitialBatteryLoad_mAh = RegisterConverter.ByteArrayToValue( currentGenesis.ReadRegister(Register.Powermon.BatteryInitialLoad)); + var nullCheck = currentGenesis.ReadRegister(Register.Powermon.RemainingSeconds); + if (nullCheck == null) + status.FwCalculatedRemainingLifeTime_s = null; + else + status.FwCalculatedRemainingLifeTime_s = + RegisterConverter.ByteArrayToValue(nullCheck); + currentGenesis.Logout(); retVal = CalculateLifeTime(status); @@ -337,6 +347,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus /// /// - Calculate storage months. /// + /// + /// - Calculate FW based calculation of remaining lifetime in years. + /// public static Boolean CalculateLifeTime(GenesisStatus status) { // Mark as false if the basic inputs are missed @@ -361,6 +374,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus var estimatedLifeTime_s = status.ExceededLifeTime_s / drainedBatteryLoad_rel; var remainingLifetime_s = estimatedLifeTime_s - status.ExceededLifeTime_s; status.RemainingLifeTimeYears = remainingLifetime_s * YEARS_PER_SECONDS; + status.FwCalculatedRemainingLifeTimeYears = status.FwCalculatedRemainingLifeTime_s * YEARS_PER_SECONDS; // Calculate an alternative threshold for remaining battery load based on the quiescent current and a supplement // for production purpose. Those values can be assigned in the Cordonel requirements. diff --git a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs index 41799755..a6ba9035 100644 --- a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs +++ b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs @@ -94,6 +94,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers public static readonly String BatteryInitialLoad = "POWERMON_BatteryMilliAHrRating"; public static readonly String BatteryExceededSeconds = "POWERMON_TotalUsedSeconds"; public static readonly String StoreConfiguration = "POWERMON_StoreConfiguration"; + public static readonly String RemainingSeconds = "POWERMON_RemainingSeconds"; } diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs index be95b8f7..247366b9 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/CheckProductionState.cs @@ -11,7 +11,6 @@ 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.TestResults; -using Xylem.Common.Production.ProductionUiCordonel.Model; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericModules; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.GenericProcesses; @@ -78,6 +77,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - CancellationToken. /// + /// + /// - Moved EOL creation to ExecPasswordFile. + /// public override StatusReturn PreExecuteProcess() { if (Meter == null || string.IsNullOrEmpty(Meter.PcbId) || Meter.PcbId.Length < GenesisMeter.MinPcbIdLength) @@ -89,13 +91,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Some statistics for GUI and internal processing SignalRunningState(MaxActualProgressSteps); - // Get new EOL progress from DB. All fields except the Id, StartDate of EOL and the PcbId are null! - if (!EOLHandler.GetNewEolProgress(Meter.PcbId, EolProgress, out var error)) - { - Meter.WriteLog(error); - ErrorMsgDispatcher(Resources.StrErrorMsgCreateEolProgress); - return StatusReturn.Failed; - } + //// Get new EOL progress from DB. All fields except the Id, StartDate of EOL and the PcbId are null! + //if (!EOLHandler.GetNewEolProgress(Meter.PcbId, EolProgress, out var error)) + //{ + // Meter.WriteLog(error); + // ErrorMsgDispatcher(Resources.StrErrorMsgCreateEolProgress); + // return StatusReturn.Failed; + //} // Exit if meanwhile cancellation is required if (CancellationToken.IsCancellationRequested) @@ -105,7 +107,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Get the requirement (Standard or special) if (!GenesisStatusHandler.GetCordonelRequirementInfoFromDb(Meter.PcbId, ProductionRequirements, - out error) || ProductionRequirements == null) + out var error) || ProductionRequirements == null) { Meter.WriteLog(error); ErrorMsgDispatcher(Resources.StrErrorMsgProductionRequirements); diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs index 1e5d3928..e164f9d3 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/EolProcessStatesDef.cs @@ -104,16 +104,14 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr var stateContainer = new List { #region ----------------------------------- GENERIC-STATES--------------------------------------------- - // Detection of Cordonel has to be completed before assigning next state, so leave to automatic - // to change the state after successfully execution. The detection is the base for all others. new ProcessStateStruct( productionProcess: new DetectCordonel(Resources.StrStateDetectCordonel), processState: ProcessState.DetectCordonel, processInfo: Resources.StrStateDetectCordonel, productionProcessNo: 0, + // CheckNewMeter will exit with repeated detect or connect nextStateOnSuccess: ProcessState.CheckNewMeter), - // Precondition: - The detection process has to be completed as the PcbId is needed. new ProcessStateStruct( productionProcess: new ConnectCordonel(Resources.StrStateConnectCordonel), processState: ProcessState.ConnectCordonel, @@ -121,8 +119,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr productionProcessNo: 1, nextStateOnSuccess: ProcessState.GetSerialNumberAndRadioAddress), - // Precondition: - The detection process has to be completed as the PcbId is needed. - // AVOID to change the process state on completion as parallel process is active! new ProcessStateStruct( productionProcess: new GetSerialNumberAndRadioAddress(Resources.StrStateGetSerialAndRadioAddress), processState: ProcessState.GetSerialNumberAndRadioAddress, @@ -133,10 +129,6 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Kick off parallel process execution kickOffParallelState: ProcessState.GetProgrammingParameters), - // Precondition: - The connection process has to be completed as a readout of some register - // values from the Cordonel are needed to check the update capability: - // - Wait on completed connection process before starting this process. - // AVOID to change the process state on completion as parallel process is active! new ProcessStateStruct( productionProcess: new GetFinalParametrization(Resources.StrStateGetProgrammingParameters), processState: ProcessState.GetProgrammingParameters, @@ -145,29 +137,11 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr // Avoid automatic change after completion as parallel process is active nextStateOnSuccess: BaseProductionProcess.DoNotChangeStateAfterCompletion, // Kick off parallel process execution - kickOffParallelState: ProcessState.CheckProductionState, - // Wait until this process has been successfully completed - waitForSingleProcess: ProcessState.ConnectCordonel), + kickOffParallelState: ProcessState.ProcessPasswordFile), #endregion -------------------------------- GENERIC-STATES -------------------------------------------- #region ----------------------------------- EOL-STATES ------------------------------------------------ - // Precondition: - The connection process has to be completed as a readout of some register - // values from the Cordonel are needed to check the update capability: - // - Wait on completed connection process before starting this process. - // AVOID to change the process state on completion as parallel process is active! - new ProcessStateStruct( - productionProcess: new CheckProductionState(Resources.StrStateCheckProductionState), - processState: ProcessState.CheckProductionState, - processInfo: Resources.StrStateCheckProductionState, - productionProcessNo: 4, - // Avoid automatic change after completion as parallel process is active - nextStateOnSuccess: BaseProductionProcess.DoNotChangeStateAfterCompletion, - // Kick off parallel process execution - kickOffParallelState: ProcessState.ProcessPasswordFile, - // Wait until this process has been successfully completed - waitForSingleProcess: ProcessState.ConnectCordonel), - // Precondition: - The connection process has to be completed as a password change in the DB // will take place: Skeleton to Password Level 8. Not waiting for completion may cause side // effects on login. Wait for all processes to complete. @@ -177,27 +151,32 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr productionProcess: new ExecPasswordFile(Resources.StrStatePasswordFile), processState: ProcessState.ProcessPasswordFile, processInfo: Resources.StrStatePasswordFile, - productionProcessNo: 5, + productionProcessNo: 4, nextStateOnSuccess: ProcessState.ExecFinalParametrization, + // Wait for completion of all processes to avoid side effects waitForAllProcesses: true), - // This writes all setups to the device, it has to be executed exclusively with automatic - new ProcessStateStruct( + new ProcessStateStruct( productionProcess: new ExecFinalParametrization(Resources.StrStateFinalParametrization), processState: ProcessState.ExecFinalParametrization, processInfo: Resources.StrStateFinalParametrization, - productionProcessNo: 6, + productionProcessNo: 5, nextStateOnSuccess: ProcessState.ExecStoreConfiguration), - // Precondition: - The final parametrization has to be finished as this shall be stored - // to non-volatile memory and checked if remaining valid after the reboot. - // Store configuration has to be executed exclusively with automatic new ProcessStateStruct( productionProcess: new ExecStoreConfiguration(Resources.StrStateStoreConfiguration), processState: ProcessState.ExecStoreConfiguration, processInfo: Resources.StrStateStoreConfiguration, - productionProcessNo: 7, - nextStateOnSuccess: ProcessState.RebootCordonel), + productionProcessNo: 6, + nextStateOnSuccess: ProcessState.CheckProductionState), + + // Parametrization has to be completed as those needed to check e.g. the remaining FW based lifetime. + new ProcessStateStruct( + productionProcess: new CheckProductionState(Resources.StrStateCheckProductionState), + processState: ProcessState.CheckProductionState, + processInfo: Resources.StrStateCheckProductionState, + productionProcessNo: 7, + nextStateOnSuccess: ProcessState.RebootCordonel), // Precondition: - The store configuration has to be executed to safe all settings // to non-volatile memory and checked if remaining valid after the reboot. diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs index 214570a5..13180fbd 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/EolProcesses/ExecPasswordFile.cs @@ -8,6 +8,7 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Logic.ProductionOrderCore; +using Xylem.Common.Production.ProductionUiCordonel.Model; using Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Enum; using Xylem.Common.Production.ProductionUiCordonel.Properties; using Xylem.Common.Production.ProductionUiCordonel.UserControls; @@ -89,8 +90,19 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.EolPr /// /// - Retries for installation of password file. /// + /// + /// - Moved EOL creation from CHeckProductionState as this is the first entry for the configuration. + /// public override StatusReturn ExecuteProcess() { + // Get new EOL progress from DB. All fields except the Id, StartDate of EOL and the PcbId are null! + if (!EOLHandler.GetNewEolProgress(Meter.PcbId, EolProgress, out var error)) + { + Meter.WriteLog(error); + ErrorMsgDispatcher(Resources.StrErrorMsgCreateEolProgress); + return StatusReturn.Failed; + } + // Uncheck executed process to leave the result open needed for retries EolProgress.PasswordFileInstalledCheck = null; diff --git a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs index aeaf1622..74ba04a6 100644 --- a/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs +++ b/Common/Production/ProductionUiCordonel/ProductionProcesses/GenericModules/GenericChecks.cs @@ -32,6 +32,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener /// /// - Initial. /// + /// + /// - FW based calculation of remaining lifetime in years. + /// public static StatusReturn CheckRemainingLifetime(IGenesisMeter meter, CordonelRequirements productionRequirements, GenesisStatus productionStatus, out String feedbackMsg, Boolean assemblyLine = false) { @@ -58,11 +61,22 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener var strStation = assemblyLine ? $"{productionRequirements.RequiredLifeTimeYearsAssembly:F2} " : $"{productionRequirements.RequiredLifeTimeYearsShipping:F2} "; + // Take the FW based calculation into account + var strFwCalculatedLifeTimeYears = ""; + if (productionStatus.FwCalculatedRemainingLifeTimeYears != null) + { + strFwCalculatedLifeTimeYears = + $@" - {Resources.StrMsgRemainingLifeTime}: " + + $"{productionStatus.FwCalculatedRemainingLifeTimeYears:F2} " + + $"{Resources.StrMsgYears} (Firmware)"; + } // Build message for required versus calculated lifetime var lifeTime = $"{Resources.StrMsgRemainingLifeTime}: " + - // Actual calculated lifetime based on readings from meter + // Actual SW calculated lifetime based on readings from meter $"{productionStatus.RemainingLifeTimeYears:F2} " + - $"{Resources.StrMsgYears}" + + $"{Resources.StrMsgYears} (Software)" + + // Optional FW calculation + strFwCalculatedLifeTimeYears + $" - {Resources.StrMsgRequiredLifeTime}: " + // Required lifetime from special or standard requirement strStation + @@ -72,7 +86,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener if ((assemblyLine && productionRequirements.RequiredLifeTimeYearsAssembly > productionStatus.RemainingLifeTimeYears) || (!assemblyLine && - productionRequirements.RequiredLifeTimeYearsShipping > productionStatus.RemainingLifeTimeYears)) + (productionRequirements.RequiredLifeTimeYearsShipping > productionStatus.RemainingLifeTimeYears || + // internally in FW calculated remaining lifetime visual for customer in DIAVASO + productionRequirements.RequiredLifeTimeYearsShipping > productionStatus.FwCalculatedRemainingLifeTimeYears))) { feedbackMsg = $"{Resources.StrErrorMsg}: {lifeTime}"; return StatusReturn.Failed; @@ -218,9 +234,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.ProductionProcesses.Gener // Create an output message addon for alternative power consumption calculation var strAlternativeCalc = productionStatus.AlternativeRequiredBatteryLoadPercent == null - ? "" - : $" - {Resources.StrMsgRequirementAbsolutLimitDrainedBattery}: " + strStation + - $" ({Resources.StrMsgAlternativeDrainedBatteryCalculation})"; + ? "" : $" - {Resources.StrMsgRequirementAbsolutLimitDrainedBattery}: " + strStation ; var strBatLoad = $"{Resources.StrMsgDrainedBattery}: " + // Actual calculated battery load based on readings from meter diff --git a/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs b/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs index 85d04021..5a6c5005 100644 --- a/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs +++ b/Common/Ui/GenesisToolBox/FrmLowLevelTools.cs @@ -991,6 +991,9 @@ namespace Xylem.Common.Ui.GenesisToolBox /// /// - Initial /// + /// + /// - Added FW based calculation of lifetime in years. + /// private Boolean BuildGenesisStatus(out String msg) { msg = ""; @@ -1017,6 +1020,8 @@ namespace Xylem.Common.Ui.GenesisToolBox sbMSG.AppendLine(""); sbMSG.AppendLine($"Actual storage months: {genesisStatus.StorageMonths:F1}"); sbMSG.AppendLine($"Remaining life time in years: {genesisStatus.RemainingLifeTimeYears:F2}"); + if (genesisStatus.FwCalculatedRemainingLifeTimeYears != null) + sbMSG.AppendLine($"Remaining life time in years (FW): {genesisStatus.FwCalculatedRemainingLifeTimeYears:F2}"); sbMSG.AppendLine($"Totally drained battery load in %: {genesisStatus.DrainedBatteryLoadPercent:F2}"); msg = sbMSG.ToString();