diff --git a/Common/Common.sln b/Common/Common.sln index 03e76c5a..05f7ea5b 100644 --- a/Common/Common.sln +++ b/Common/Common.sln @@ -149,6 +149,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TempFlansh", "TempFlansh\Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicStremingLogAnalyzer", "Ui\DynamicStremingLogAnalyzer\DynamicStremingLogAnalyzer.csproj", "{652ECA13-A411-4789-8814-6823965947CB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenesisStatus", "Hardware\WaterMeter\Genesis\GenesisStatus\GenesisStatus.csproj", "{0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution Utils\DateTimeServerShared\DateTimeServerShared.projitems*{4806d89a-fbfb-41bc-aaa7-2242444bf55a}*SharedItemsImports = 4 @@ -3383,6 +3385,70 @@ Global {652ECA13-A411-4789-8814-6823965947CB}.XP32bit|x64.Build.0 = Release|Any CPU {652ECA13-A411-4789-8814-6823965947CB}.XP32bit|x86.ActiveCfg = Release|Any CPU {652ECA13-A411-4789-8814-6823965947CB}.XP32bit|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}._MANUAL_CONTROL|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.COM|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|x64.ActiveCfg = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|x64.Build.0 = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|x86.ActiveCfg = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Debug|x86.Build.0 = Debug|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.GenesisDisplayTool_V01|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.PerformTest|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.Release|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.ReleaseTest|x86.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|Any CPU.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|Any CPU.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|Mixed Platforms.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|Mixed Platforms.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|x64.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|x64.Build.0 = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|x86.ActiveCfg = Release|Any CPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F}.XP32bit|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3441,6 +3507,7 @@ Global {E9FAAF12-8721-46AC-8181-744001E3314E} = {57AA2731-BFD9-40A5-820F-E943FBC75D91} {2FD60CF1-45CD-4060-B8E5-4F39FBA7F1CB} = {7A0EE7B8-6B7E-41E9-B679-319C8CA48CF1} {A25A96FD-604B-43BE-80CD-A953152C2175} = {0C89F3A2-BBB9-4E09-B424-D2D4395F046F} + {AC434B18-4D7B-49BA-9AD5-0527C79E8297} = {B5F43F61-4448-4992-85B5-7EDFB82FD643} {4806D89A-FBFB-41BC-AAA7-2242444BF55A} = {57AA2731-BFD9-40A5-820F-E943FBC75D91} {0FFBCA6C-E828-4196-B0A8-988DEA3E077F} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {70BF5094-0F03-41FC-B0BD-BEFCF51686C9} = {03D4F23E-7E4A-4091-BC96-036C996D351A} @@ -3448,6 +3515,7 @@ Global {108FE49B-75E1-43F5-82DD-DA33FE99CBEC} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {62E5BA37-36AB-4F0A-BC12-554E7A1F1A39} = {03D4F23E-7E4A-4091-BC96-036C996D351A} {652ECA13-A411-4789-8814-6823965947CB} = {03D4F23E-7E4A-4091-BC96-036C996D351A} + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} = {B5F43F61-4448-4992-85B5-7EDFB82FD643} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4BCB7B69-696C-436A-86F7-C91EA5588164} diff --git a/Common/Common.sln.DotSettings b/Common/Common.sln.DotSettings index 4d2ea367..cee2e4d3 100644 --- a/Common/Common.sln.DotSettings +++ b/Common/Common.sln.DotSettings @@ -48,7 +48,9 @@ True True True + True True + True True True True diff --git a/Common/Common.sln.DotSettings.user b/Common/Common.sln.DotSettings.user index dd1608cc..772152a3 100644 --- a/Common/Common.sln.DotSettings.user +++ b/Common/Common.sln.DotSettings.user @@ -23,6 +23,7 @@ <Policy Inspect="False" Prefix="" Suffix="" Style="Aa_bb" /> <AssemblyExplorer> <Assembly Path="D:\Projekte\SENSUS_tfs_workspaces\WorkBenchV2\Main\Common\Ui\IrdaFunctionalTestApp\bin\Debug\Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.dll" /> + <Assembly Path="D:\Projekte\SENSUS_GitLab\laa_production\Common\Hardware\WaterMeter\Genesis\GenesisPwd\bin\Debug\Newtonsoft.Json.dll" /> </AssemblyExplorer> True NewVersion diff --git a/Common/CommonCore.Configuration/ServiceUrls.cs b/Common/CommonCore.Configuration/ServiceUrls.cs index 4ed1451e..469eb12c 100644 --- a/Common/CommonCore.Configuration/ServiceUrls.cs +++ b/Common/CommonCore.Configuration/ServiceUrls.cs @@ -33,6 +33,9 @@ namespace Xylem.Common.CommonCore.Configuration private const String DefaultSetCordonelAppVersionServiceUrl = "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/SetCordonelProgress?PcbId="; + private const String DefaultGetProductionSkipAndLifeTimeInfoUrl = + "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/GetProductionSkipAndLifeTimeInfo?PcbId="; + private const String DefaultGetCordonelAppVersionServiceUrl = "http://sla12iis01.emea.sensus.net/MeterProcessState/api/ProccesState/GetCordonelAppVersion?PcbId="; @@ -305,6 +308,20 @@ namespace Xylem.Common.CommonCore.Configuration DefaultSetCordonelAppVersionServiceUrl; } + /// + /// Get all production infos for skip process checks or limits for production like: + /// - Battery drained percentage upper limit, + /// - Production due date for a special register, + /// - Required life time for assembly line, + /// - Required life time for shipping line. + /// + /// + public static String GetProductionSkipAndLifeTimeInfoServiceUrl() + { + return ConfigurationManager.AppSettings["GetProductionSkipAndLifeTimeInfoUrl"] ?? + DefaultGetProductionSkipAndLifeTimeInfoUrl; + } + /// /// Get all applications versions installed to a specific Cordonel. /// diff --git a/Common/CordonelAssemblyLine/CordonelAssemblyLine.csproj b/Common/CordonelAssemblyLine/CordonelAssemblyLine.csproj index 74e66da7..ca9e7a83 100644 --- a/Common/CordonelAssemblyLine/CordonelAssemblyLine.csproj +++ b/Common/CordonelAssemblyLine/CordonelAssemblyLine.csproj @@ -180,6 +180,10 @@ {2C6378C6-6BA1-4CEE-8992-8404D8369A90} GenesisFile + + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} + GenesisStatus + {F4AAF7E6-7333-4284-B735-E32DEB076C64} Registers diff --git a/Common/CordonelAssemblyLine/Model/PickingModel.cs b/Common/CordonelAssemblyLine/Model/PickingModel.cs index 154d5d89..bf7aaa6b 100644 --- a/Common/CordonelAssemblyLine/Model/PickingModel.cs +++ b/Common/CordonelAssemblyLine/Model/PickingModel.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using Xylem.Common.CommonCore.Configuration; 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.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Logic.SoftwareAccessHelper; @@ -577,15 +578,10 @@ namespace CordonelAssemblyLine.Model ret = false; } + var genesisStatus = new GenesisStatus(); - var nowSeconds = meter.ReadRegister("POWERMON_TotalUsedSeconds"); - var nowCharge = meter.ReadRegister("POWERMON_TotalUsedCharge", 8); - var mfgCharge = meter.ReadRegister("CUSTOMER_MfgCharge"); - var BatteryMilliAHrRating = meter.ReadRegister("POWERMON_BatteryMilliAHrRating"); - - - - if (nowCharge == null || nowSeconds == null) + // this calculates all life time values + if (!GenesisStatusHandler.BuildLifeTimeInformation(meter, genesisStatus)) { meter.WriteLog("Batterie nicht lesbar"); lblS08Text = "Batterie nicht lesbar"; @@ -594,84 +590,25 @@ namespace CordonelAssemblyLine.Model } else { - //var nowChargeV = BitConverter.ToUInt64(nowCharge.ToArray(), 0); - //var nowSecondsV = BitConverter.ToUInt32(nowSeconds.ToArray(), 0); - //var mfgChargeV = BitConverter.ToUInt32(mfgCharge.ToArray(), 0); - //var BatteryMilliAHrRatingV = BitConverter.ToUInt32(BatteryMilliAHrRating.ToArray(), 0); - - ////// Time Span in h in mAhr In % with one battery is 100% - //////(((total used change difference / (Time span / 3600) ) / 3600000) / 19000)*100 - //// ReSharper disable once UnusedVariable - //var loadAtH = nowChargeV / ((Double)nowSecondsV / 3600) / 3600000 / (19000 * 2) * 100; - //var totalUsed = (Double)nowChargeV / 1000000 / 3.6 / (19000 * 2) * 100; - //SetState($"Battery Total Used {totalUsed}%"); - //SetState($"Battery Total Charge {nowChargeV}uAs"); - //SetState($"Battery MFG Charge {mfgChargeV}uAs"); - - - // (nowSecondsV / nowChargeV) * (2*BatteryMilliAHrRatingV * 1000 * 3600) - - //(POWERMON_TotalUsedSeconds / POWERMON_TotalUsedCharge) * (POWERMON_BatteryQuantity * POWERMON_BatteryMilliAHrRating * 1000 * 3600) = lifetime in seconds - //Lifetime in seconds - POWERMON_TotalUsedSeconds = remaining lifetime. - - - - var POWERMON_TotalUsedSeconds = (double)(RegisterConverter.ConvertTo(meter.ReadRegister("POWERMON_TotalUsedSeconds"))); - - var tmp_POWERMON_TotalUsedCharge = meter.ReadRegister("POWERMON_TotalUsedCharge", 8); - - var POWERMON_TotalUsedCharge = BitConverter.ToUInt64(tmp_POWERMON_TotalUsedCharge.ToArray(), 0); - - var POWERMON_BatteryQuantity = (double)RegisterConverter.ConvertTo(meter.ReadRegister("POWERMON_BatteryQuantity")); - var POWERMON_BatteryMilliAHrRating = (double)RegisterConverter.ConvertTo(meter.ReadRegister("POWERMON_BatteryMilliAHrRating")); - - - var lifetimeInSeconds = (POWERMON_TotalUsedSeconds / (double)(POWERMON_TotalUsedCharge)) * (POWERMON_BatteryQuantity * POWERMON_BatteryMilliAHrRating * 1000 * 3600); - var remainingLifetime = lifetimeInSeconds - POWERMON_TotalUsedSeconds; - - var sbMSG = new StringBuilder(); sbMSG.AppendLine($"Pcb = {meter.PcbId}"); - sbMSG.AppendLine($"POWERMON_TotalUsedSeconds = {POWERMON_TotalUsedSeconds}"); - sbMSG.AppendLine($"POWERMON_TotalUsedCharge = {POWERMON_TotalUsedCharge}"); - sbMSG.AppendLine($"POWERMON_BatteryQuantity = {POWERMON_BatteryQuantity}"); - sbMSG.AppendLine($"POWERMON_BatteryMilliAHrRating = {POWERMON_BatteryMilliAHrRating}"); + sbMSG.AppendLine($"POWERMON_TotalUsedSeconds = {genesisStatus.ExceededLifeTime_s}"); + sbMSG.AppendLine($"POWERMON_TotalUsedCharge = {genesisStatus.DrainedBatteryPower_uAs}"); + sbMSG.AppendLine($"POWERMON_BatteryQuantity = {genesisStatus.BatteryQuantity}"); + sbMSG.AppendLine($"POWERMON_BatteryMilliAHrRating = {genesisStatus.InitialBatteryLoad_mAh}"); sbMSG.AppendLine(""); - sbMSG.AppendLine($"lifetimeInSeconds = (POWERMON_TotalUsedSeconds / POWERMON_TotalUsedCharge) * (POWERMON_BatteryQuantity * POWERMON_BatteryMilliAHrRating * 1000 * 3600)"); - sbMSG.AppendLine($"{lifetimeInSeconds} = ({POWERMON_TotalUsedSeconds} / {POWERMON_TotalUsedCharge}) * ({POWERMON_BatteryQuantity} * {POWERMON_BatteryMilliAHrRating} * 1000 * 3600)"); - sbMSG.AppendLine(""); - sbMSG.AppendLine("remainingLifetime = lifetimeInSeconds - POWERMON_TotalUsedSeconds"); - sbMSG.AppendLine($"{remainingLifetime} = {lifetimeInSeconds} - {POWERMON_TotalUsedSeconds}"); - sbMSG.AppendLine(""); - sbMSG.AppendLine($"in Years {(remainingLifetime / 86400 / 365)}"); + sbMSG.AppendLine($"Remaining life time in years {genesisStatus.RemainingLifeTimeYears:F2}"); + sbMSG.AppendLine($"Totally drained battery load in % {genesisStatus.DrainedBatteryLoadPercent:F2}"); - - - - //// Time Span in h in mAhr In % with one battery is 100% - ////(((total used change difference / (Time span / 3600) ) / 3600000) / 19000)*100 - var loadAtH = ((((double)POWERMON_TotalUsedCharge / ((double)POWERMON_TotalUsedSeconds / 3600)) / 3600000) / (19000 * 2)) * 100; - var totalUsed = (((double)POWERMON_TotalUsedCharge / 1000000 / 3.6) / ((19000 * 2))) * 100; - - sbMSG.AppendLine($"in % {totalUsed}"); - - if (totalUsed >= 7.5) + if (genesisStatus.DrainedBatteryLoadPercent >= 7.5) { lblS08Text = "Batterieentladung über 7.5%"; lblS08Color = _progressError; ret = false; } meter.WriteLog(sbMSG.ToString()); - - - - - } - - - } if (_skipProcessSteps == null || !_skipProcessSteps.SkipLUT) @@ -679,8 +616,6 @@ namespace CordonelAssemblyLine.Model if (ret) { - - lblS08Text = "2"; lblS08Color = _progressDone; lblS10Color = _progressCurrent; diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisCore.csproj b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisCore.csproj index 008a4078..51eaf560 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisCore.csproj +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisCore.csproj @@ -327,6 +327,10 @@ {F013A56B-7BE6-4852-9CD8-B971CD1ADD0C} GenesisConfig + + {AC434B18-4D7B-49BA-9AD5-0527C79E8297} + GenesisPwd + {8BDD2789-96D4-43EA-AAD7-0F49D0347998} ProtocolCore diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs index 64430032..b9f0dfc6 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisCore/GenesisMeter.cs @@ -26,6 +26,7 @@ using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages; using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.EventArguments; using Xylem.Common.Hardware.WaterMeter.Genesis.DataPackages.MeasurementRecords; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd; using Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.ProtocolCore; using Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol; using Xylem.Common.Hardware.WaterMeter.Genesis.Protocols.RequestProtocol.Consts; @@ -959,13 +960,13 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore /// /// - Password had been reset to empty string if read from file, corrected! /// + /// + /// - Used + /// private String GetPassword() { - var url = ServiceUrls.GenesisGetPasswordServiceUrl(); - var password = ""; - - //without PCB ID it is not possible to login, - //but if it is already assigned to this Gensis, don't read it again + // without PCB ID it is not possible to login, + // but if it is already assigned to this Genesis, don't read it again if (string.IsNullOrEmpty(PcbId)) { //GetPcbId fills the PsbId property @@ -976,41 +977,29 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore { return ""; } - } } - url += PcbId; - try + // on unknown password try to get it from DB + if (MeterPwdHandlerDb.GetPasswordFromDb(PcbId, out var password)) { - //use - var http = (HttpWebRequest)WebRequest.Create(url); - var response = (HttpWebResponse)http.GetResponse(); - var responseStream = response.GetResponseStream(); - if (responseStream == null) - { - throw new InvalidOperationException(); - } - using (var sr = new StreamReader(responseStream)) - { - var responseJson = sr.ReadToEnd(); - password = responseJson.Trim('"'); - } - _logger.Info($"Slot:{Slot} - Got password from GenesisPasswordServiceUrl, URL({url})"); + _logger.Info($"Slot:{Slot} - Got password from GenesisPasswordService, " + + $"URL({ServiceUrls.GenesisGetPasswordServiceUrl() + PcbId})"); } - catch (Exception ex) + else { _logger.Info($"Slot:{Slot} - Cannot get password from GenesisPasswordService, " + - $"URL({url}), Error({ex.Message})"); - if (File.Exists(ProgramConfig.OfflineInfoFile)) + $"URL({ServiceUrls.GenesisGetPasswordServiceUrl() + PcbId}))"); + // try to read the password from an offline password file + if (!File.Exists(ProgramConfig.OfflineInfoFile)) return password; + + var listOfOfflinePasswords = JsonConvert.DeserializeObject>( + File.ReadAllText(ProgramConfig.OfflineInfoFile)); + password = listOfOfflinePasswords.First(x => x.PcbId == PcbId).Password; + + if (!string.IsNullOrEmpty(password)) { - var listOfOfflinePasswords = JsonConvert.DeserializeObject>( - File.ReadAllText(ProgramConfig.OfflineInfoFile)); - password = listOfOfflinePasswords.First(x => x.PcbId == PcbId).Password; - if (!string.IsNullOrEmpty(password)) - { - _logger.Info($"Slot:{Slot} - Got password from password file!"); - } + _logger.Info($"Slot:{Slot} - Got password for PcbId:{PcbId} from password file!"); } } diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdDb.cs b/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdDb.cs index 44c8b2a3..bfd7194b 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdDb.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdDb.cs @@ -8,42 +8,53 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd /// - passwords, /// - password-hashes (12 char from password - SHA1), /// - Order number, - /// - Radio address and + /// - Radio address, + /// - Key set id, + /// - Password file id and /// - Skeleton key. /// public class MeterPwdDb { - //password file length is 160 bytes (8 passwords a 20 bytes SHA1) + /// + /// password file length is 160 bytes (8 passwords a 20 bytes SHA1) + /// public const Int32 PwdFileLength = 160; /// /// Skeleton key index in password list. /// public const Int32 SkeletonKeyIdx = 2; + /// /// Password Level 8 index in 8 elements password list. /// public const Int32 PwdLevel8Idx = 7; + /// /// Order number for this Genesis. /// public Int64? OrderNumber = null; + /// /// Optional radio address. /// public Int64? RadioAddress = null; + /// /// Skeleton key for login if password file is not installed. /// public String Skeleton = ""; + /// /// Password, which is the Skeleton, if password file not installed, or the PwdLevel8, if the password file is installed . /// public String Password = ""; + /// /// List of hashes. /// public List ListOfHashes = new List(); + /// /// List of passwords. /// diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdHandlerDb.cs b/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdHandlerDb.cs index a52a3fb4..c15f6599 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdHandlerDb.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisPwd/MeterPwdHandlerDb.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net; using System.Text; @@ -26,29 +24,31 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisPwd /// /// - Initial. /// + /// + /// - Used JsonConvert instead of StreamReader. + /// public static Boolean GetPasswordFromDb(String pcbId, out String password) { - var url = ServiceUrls.GenesisGetPasswordServiceUrl(); password = ""; + if (string.IsNullOrEmpty(pcbId)) + { + return false; + } try { - //todo: roland umstellen auf localwebrequest - var http = (HttpWebRequest)WebRequest.Create(url + pcbId); - var response = (HttpWebResponse)http.GetResponse(); - var responseStream = response.GetResponseStream(); - if (responseStream == null) + var url = ServiceUrls.GenesisGetPasswordServiceUrl(); + var response = LocalWebRequest.GetRequest(url + pcbId, 2000); + password = JsonConvert.DeserializeObject(response); + if (string.IsNullOrEmpty(password)) { + password = ""; return false; } - using (var sr = new StreamReader(responseStream)) - { - var responseJson = sr.ReadToEnd(); - password = responseJson.Trim('"'); - } } catch (Exception ) { + password = ""; return false; } diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs new file mode 100644 index 00000000..ba9d2aa9 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.cs @@ -0,0 +1,125 @@ +using System; + +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus +{ + /// + /// Status of Cordonel like: + /// - Battery drainage, + /// - Production date of electronics, + /// - Due date for production, + /// - Remaining life time, + /// - Special permissions for production capability check for + /// - Battery Drainage in %, + /// - Remaining Life Time in years, + /// - Production Due Date as DateTime. + /// + public class GenesisStatus + { + /// + /// Data base primary key + /// + public Int32 Id; + + /// + /// Order number + /// + public Int32 OrderNumber; + + /// + /// PcbId. + /// + public String PcbId; + + /// + /// Skip radio parameter check + /// + public Boolean SkipRadioParametersCheck; + + /// + /// Skip FW check. Normally the FW will be assigned to the latest released version + /// and taken from the data base. Here special versions can be used for FW tests. + /// + public Boolean SkipFwCheck; + + /// + /// Skip the look-up-table installation as this device may be used for development. + /// + public Boolean SkipLutCheck; + + /// + /// Internally used to signal that production and shipping is proved and validated. + /// + public Boolean ProductionAccepted; + + /// + /// Date and time of production of electronics. + /// + public DateTime KitronProductionDate; + + /// + /// Last date until production has to be finished, can be extended by special permission + /// + public DateTime ProductionDueDate; + + /// + /// Remaining life time for Cordonel in years based on battery drainage. + /// + public Double RemainingLifeTimeYears; + + /// + /// Exceeded life time of all batteries in seconds. + /// + public UInt64 ExceededLifeTime_s; + + /// + /// Required life time in years for assembly, is dependent on region and special permission. + /// + public Double RequiredLifeTimeYearsAssembly; + + /// + /// Required life time in years for shipping, is dependent on region and special permission. + /// + public Double RequiredLifeTimeYearsShipping; + + /// + /// Battery drainage in percent. + /// + public Double DrainedBatteryLoadPercent; + + /// + /// Maximum drained Battery load in percent. + /// + public Double MaxDrainedBatteryLoadPercent; + + /// + /// Number of batteries attached to Cordonel. + /// + public Int32 BatteryQuantity; + + /// + /// Initial capacity of one battery in mAh. + /// + public UInt64 InitialBatteryLoad_mAh; + + /// + /// Drained capacity of all batteries in uAs. + /// + public UInt64 DrainedBatteryPower_uAs; + + /// + /// Comment for approval and permissions reasons: + /// e.g. "On customer requirement for test purposes the life time isn't of importance". + /// + public String ApprovalComment; + + /// + /// Name of approver for special permissions. + /// + public String ApproverName; + + /// + /// Date of approval. + /// + public DateTime ApprovalDate; + } +} diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.csproj b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.csproj new file mode 100644 index 00000000..19a59454 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatus.csproj @@ -0,0 +1,73 @@ + + + + + Debug + AnyCPU + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} + Library + Properties + Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus + Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus + v4.0 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net40\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + {9EB1F659-6F73-4F65-BCAB-4114FD94F5FC} + CommonCore.Configuration + + + {A33E3C6D-EAAE-4A20-A0EE-F9E6922FD029} + SoftwareAccessHelper + + + {04201E95-90A0-4B73-A72F-379739B2A3AE} + GenesisCore + + + {F4AAF7E6-7333-4284-B735-E32DEB076C64} + Registers + + + + + + + \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs new file mode 100644 index 00000000..4afc1dfb --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/GenesisStatusHandler.cs @@ -0,0 +1,136 @@ +using System; +using Newtonsoft.Json; +using Xylem.Common.CommonCore.Configuration; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; +using Xylem.Common.Logic.SoftwareAccessHelper; + +namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus +{ + /// + /// Handler for the production status check. This will be feed by the DB. + /// - Calculation of drained battery, + /// - Assembly capability check, + /// - Shipping capability check. + /// + public static class GenesisStatusHandler + { + /// + /// Get all production infos for skip process checks or limits for production like: + /// - Battery drained percentage upper limit, + /// - Production due date for a special register, + /// - Required life time for assembly line, + /// - Required life time for shipping line. + /// + /// + /// + /// production status + /// true if successfully executed + /// + /// - Initial. + /// + public static Boolean GetProductionSkipAndLifeTimeInfoFromDb(String pcbId, Int32 orderNumber, + out GenesisStatus status) + { + if (string.IsNullOrEmpty(pcbId)) + { + status = null; + return false; + } + + try + { + var url = ServiceUrls.GetProductionSkipAndLifeTimeInfoServiceUrl(); + url += $"{pcbId}&orderNumber={orderNumber}"; + var response = LocalWebRequest.GetRequest(url, 2000); + status = JsonConvert.DeserializeObject(response); + } + catch (Exception ) + { + status = null; + return false; + } + + return true; + } + + /// + /// Read and calculate life time information. + /// + /// + /// + /// + public static Boolean BuildLifeTimeInformation(GenesisMeter currentGenesis, GenesisStatus status) + { + Boolean retVal; + if (currentGenesis == null || status == null) return false; + + // read information from genesis + try + { + if (!currentGenesis.IsLoggedOn) currentGenesis.Login(); + + status.ExceededLifeTime_s = RegisterConverter.ConvertTo( + currentGenesis.ReadRegister(Register.Powermon.BatteryExceededSeconds)); + status.DrainedBatteryPower_uAs = RegisterConverter.ConvertTo( + currentGenesis.ReadRegister(Register.Powermon.BatteryDrainedLoad, 8)); + status.BatteryQuantity = RegisterConverter.ConvertTo( + currentGenesis.ReadRegister(Register.Powermon.BatteryQuantity)); + status.InitialBatteryLoad_mAh = RegisterConverter.ConvertTo( + currentGenesis.ReadRegister(Register.Powermon.BatteryInitialLoad)); + + currentGenesis.Logout(); + + retVal = CalculateLifeTime(status); + } + catch (Exception) + { + retVal = false; + } + + return retVal; + } + /// + /// Calculation of life time values. + /// + /// + /// true if all calculations could be executed + public static Boolean CalculateLifeTime(GenesisStatus status) + { + var retVal = true; + // Calculate the initial overall battery load of all batteries in uAs as the drained load uses this unit. + var initialBatteryLoad_uAs = 1000 * 3600 * status.InitialBatteryLoad_mAh * (UInt64)status.BatteryQuantity; + + // Relation of drained to initial load, set the battery to fully unloaded for failed check to force a recalculation + var drainedBatteryLoad_rel = 1.0; + if (initialBatteryLoad_uAs != 0) + { + drainedBatteryLoad_rel = (Double)status.DrainedBatteryPower_uAs / initialBatteryLoad_uAs; + } + else + { + retVal = false; + } + status.DrainedBatteryLoadPercent = drainedBatteryLoad_rel * 100; + + // The estimated life time uses the drained load over the actual exceeded life time and assumes, that further on + // an identical load will be consumed over the remaining life cycle. The initial load will be multiplied with the + // drained load relation. Set the estimated time to the exceeded time to force a recalculation on failed input. + var estimatedLifeTime_s = (Double)status.ExceededLifeTime_s; + if (drainedBatteryLoad_rel != 0.0) + { + estimatedLifeTime_s = status.ExceededLifeTime_s / drainedBatteryLoad_rel; + } + else + { + retVal = false; + } + + var remainingLifetime_s = estimatedLifeTime_s - status.ExceededLifeTime_s; + // convert the seconds to years + status.RemainingLifeTimeYears = remainingLifetime_s / 3600 / 24 / 365.25; + + return retVal; + } + } +} diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/Properties/AssemblyInfo.cs b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..a7b2723a --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GenesisStatus")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("GenesisStatus")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2023")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0f646872-d8dc-4ee5-989f-d4c73f0ace3f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisStatus/packages.config b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/packages.config new file mode 100644 index 00000000..0fa4e015 --- /dev/null +++ b/Common/Hardware/WaterMeter/Genesis/GenesisStatus/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs index 8e8d7488..9c436014 100644 --- a/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs +++ b/Common/Hardware/WaterMeter/Genesis/Registers/Registers.cs @@ -89,6 +89,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers { public static readonly String BatteryVoltage = "POWERMON_BatteryVoltage"; public static readonly String BatteryQuantity = "POWERMON_BatteryQuantity"; + public static readonly String BatteryDrainedLoad = "POWERMON_TotalUsedCharge"; + public static readonly String BatteryInitialLoad = "POWERMON_BatteryMilliAHrRating"; + public static readonly String BatteryExceededSeconds = "POWERMON_TotalUsedSeconds"; } diff --git a/Common/ProductionUiCordonel/ProductionProcesses/Actions/ProductionCheckShippingState.cs b/Common/ProductionUiCordonel/ProductionProcesses/Actions/ProductionCheckShippingState.cs index c523b7e4..81eb8097 100644 --- a/Common/ProductionUiCordonel/ProductionProcesses/Actions/ProductionCheckShippingState.cs +++ b/Common/ProductionUiCordonel/ProductionProcesses/Actions/ProductionCheckShippingState.cs @@ -1,11 +1,11 @@ using System; -using System.Linq; using System.Windows.Controls; using System.Windows.Threading; using Newtonsoft.Json; using ProductionUiCordonel.ProductionProcesses.Enum; using ProductionUiCordonel.UserControls.FinalTest; using Xylem.Common.CommonCore.Configuration; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Logic.SoftwareAccessHelper; namespace ProductionUiCordonel.ProductionProcesses.Actions @@ -108,9 +108,10 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions Progress = 50; - var nowSeconds = Meter.ReadRegister("POWERMON_TotalUsedSeconds"); - var nowCharge = Meter.ReadRegister("POWERMON_TotalUsedCharge", 8); - if (nowCharge == null) + var genesisStatus = new GenesisStatus(); + + // this calculates all life time values + if (!GenesisStatusHandler.BuildLifeTimeInformation(Meter, genesisStatus)) { UserControl.lblText.Dispatcher.Invoke(DispatcherPriority.Send, @@ -122,26 +123,15 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions Meter.WriteLog("Batterie nicht lesbar"); break; } - var nowChargeV = BitConverter.ToUInt64(nowCharge.ToArray(), 0); - var nowSecondsV = BitConverter.ToUInt32(nowSeconds.ToArray(), 0); - - - - //// Time Span in h in mAhr In % with one battery is 100% - ////(((total used change difference / (Time span / 3600) ) / 3600000) / 19000)*100 - // ReSharper disable once UnusedVariable used for debug purposes - var loadAtH = nowChargeV / ((Double)nowSecondsV / 3600) / 3600000 / (19000 * 2) * 100; - var totalUsed = (Double)nowChargeV / 1000000 / 3.6 / (19000 * 2) * 100; - + //lastFrame - Meter.WriteLog($"totalUsed at EOL {totalUsed}"); - - - if (totalUsed > 10) + Meter.WriteLog($"totalUsed at EOL {genesisStatus.DrainedBatteryLoadPercent:F2}"); + + if (genesisStatus.DrainedBatteryLoadPercent > 10.0) { currentProcessState = ProductionProcessState.Error; - UserControl.lblText.Content = "Batterie über 15% entladen"; - Meter.WriteLog("Batterie über 15% entladen"); + UserControl.lblText.Content = "Batterie über 10% entladen"; + Meter.WriteLog("Batterie über 10% entladen"); } if (currentProcessState != ProductionProcessState.Error) @@ -149,7 +139,7 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions currentProcessState = ProductionProcessState.Done; return; } - retriesRemaining = retriesRemaining - 1; + retriesRemaining -= 1; currentProcessState = ProductionProcessState.Error; } @@ -157,10 +147,8 @@ namespace ProductionUiCordonel.ProductionProcesses.Actions { Meter.WriteLog($"{ex}"); currentProcessState = ProductionProcessState.Error; - retriesRemaining = retriesRemaining - 1; + retriesRemaining -= 1; } - - } currentProcessState = ProductionProcessState.Error; } diff --git a/Common/ProductionUiCordonel/ProductionUiCordonel.csproj b/Common/ProductionUiCordonel/ProductionUiCordonel.csproj index a606a75d..ee1d811e 100644 --- a/Common/ProductionUiCordonel/ProductionUiCordonel.csproj +++ b/Common/ProductionUiCordonel/ProductionUiCordonel.csproj @@ -339,6 +339,10 @@ {AC434B18-4D7B-49BA-9AD5-0527C79E8297} GenesisPwd + + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} + GenesisStatus + {F4AAF7E6-7333-4284-B735-E32DEB076C64} Registers diff --git a/Common/Service/MeterProcessState/Controllers/ProccesStateController.cs b/Common/Service/MeterProcessState/Controllers/ProccesStateController.cs index 9e132d72..c1e47823 100644 --- a/Common/Service/MeterProcessState/Controllers/ProccesStateController.cs +++ b/Common/Service/MeterProcessState/Controllers/ProccesStateController.cs @@ -8,6 +8,7 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Web.Http; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore.Consts; using Xylem.Common.Logic.ProductionOrderCore.ProcessState; using Xylem.Common.Logic.ProductionOrderCore.TestResults; @@ -690,7 +691,7 @@ namespace Service.MeterProcessState.Controllers } } - [Route("GetCordonelSkipProcessStates")] + [Route("GetCordonelSkipProcessStates")] public async Task GetCordonelSkipProcessStates(Int32 PcbId, Int32 OrderNumber) { try @@ -701,7 +702,6 @@ namespace Service.MeterProcessState.Controllers { StringBuilder sb = new StringBuilder(); - sb.AppendLine($" select [id] "); sb.AppendLine($" ,[OrderNumber] "); sb.AppendLine($" ,[PcbId] "); @@ -720,9 +720,9 @@ namespace Service.MeterProcessState.Controllers var dt = dataacces.ExecuteQuery(sb.ToString()); - if (dt.Rows.Count != 1 ) + if (dt.Rows.Count < 1 ) { - return new SkipProcess() { SkipBatteyCheck = false, SkipFWCheck = false, SkipLUT = false, SkipRadioParameters = false}; + return new SkipProcess { SkipBatteyCheck = false, SkipFWCheck = false, SkipLUT = false, SkipRadioParameters = false}; } var ret = new SkipProcess(); foreach (var item in dt.Select()) @@ -759,6 +759,101 @@ namespace Service.MeterProcessState.Controllers } } + [Route("GetProductionSkipAndLifeTimeInfo")] + public async Task GetProductionSkipAndLifeTimeInfo(Int32 pcbId, Int32 orderNumber) + { + try + { + return Request.CreateResponse(HttpStatusCode.OK, await Task.Run(() => + { + using (var dataAccess = new SqlDataAccess(GlobalConfig.connectionString.Value)) + { + StringBuilder sb = new StringBuilder(); + + //TODO Roland Design new Table + sb.AppendLine($" select [id] "); + sb.AppendLine($" ,[OrderNumber] "); + sb.AppendLine($" ,[PcbId] "); + sb.AppendLine($" ,[SkipRadioParametersCheck] "); + sb.AppendLine($" ,[SkipFwCheck] "); + sb.AppendLine($" ,[SkipLutCheck] "); + sb.AppendLine($" ,[RequiredLifeTimeYearsAssembly] "); + sb.AppendLine($" ,[RequiredLifeTimeYearsShipping] "); + sb.AppendLine($" ,[KitronProductionDate] "); + sb.AppendLine($" ,[MaxDrainedBatteryLoadPercent] "); + sb.AppendLine($" ,[MaxStorageMonths] "); + sb.AppendLine($" ,[ApprovalDate] "); + sb.AppendLine($" ,[ApproverName] "); + sb.AppendLine($" ,[ApprovalComment] "); + sb.AppendLine($" FROM [Auftrag].[dbo].[ProductionSkipAndLifeTimeInfo] "); + sb.AppendLine($" where "); + sb.AppendLine($" (OrderNumber = {orderNumber} or OrderNumber is null) "); + sb.AppendLine($" and (PcbId = {pcbId} or PcbId is null) "); + + //TODO Roland: The defaults should come from a DefaultProductionSkipAndLifeTimeInfo table + const Int32 DefaultMaxMonthsNaRegion = 6; + const Int32 DefaultMaxMonthsEmeaRegion = 3; + const Double DefaultRequiredLifeTimeYearsAssembly = 21.0; + const Double DefaultRequiredLifeTimeYearsShipping = 20.0; + const Double DefaultMaxDrainedBatteryLoadPercent = 10.0; + + var dt = dataAccess.ExecuteQuery(sb.ToString()); + + if (dt.Rows.Count < 1 ) + { + var stat = new GenesisStatus + { + SkipFwCheck = false, + SkipLutCheck = false, + SkipRadioParametersCheck = false, + RequiredLifeTimeYearsAssembly = DefaultRequiredLifeTimeYearsAssembly, + RequiredLifeTimeYearsShipping = DefaultRequiredLifeTimeYearsShipping, + MaxDrainedBatteryLoadPercent = DefaultMaxDrainedBatteryLoadPercent, + }; + //TODO Roland implement defaults + // get region from order if (Region == "NA") + stat.ProductionDueDate = stat.KitronProductionDate + TimeSpan.FromDays(30.0 * DefaultMaxMonthsNaRegion); + // else + stat.ProductionDueDate = stat.KitronProductionDate + TimeSpan.FromDays(30.0 * DefaultMaxMonthsEmeaRegion); + return stat; + } + var ret = new GenesisStatus(); + //TODO Roland check for multiple rows take the last? + foreach (var item in dt.Select()) + { + try + { + ret.OrderNumber = orderNumber; + ret.PcbId = pcbId.ToString(); + ret.SkipRadioParametersCheck = (Boolean)item["SkipRadioParametersCheck"]; + ret.SkipFwCheck = (Boolean)item["SkipFWCheck"]; + ret.SkipLutCheck = (Boolean)item["SkipLutCheck"]; + ret.RequiredLifeTimeYearsAssembly = (Double)item["RequiredLifeTimeYearsAssembly"]; + ret.RequiredLifeTimeYearsShipping = (Double)item["RequiredLifeTimeYearsShipping"]; + ret.MaxDrainedBatteryLoadPercent = (Double)item["MaxDrainedBatteryLoadPercent"]; + ret.KitronProductionDate = (DateTime)item["KitronProductionDate"]; + var maxStorageMonths = (Int32)item["MaxStorageMonths"]; + ret.ProductionDueDate = ret.KitronProductionDate + TimeSpan.FromDays(30.0 * maxStorageMonths); + ret.ApprovalDate = (DateTime)item["ApprovalDate"]; + ret.ApproverName = item["ApproverName"].ToString(); + ret.ApprovalComment = item["ApprovalComment"].ToString(); + } + catch (Exception) + { + } + } + + return ret; + } + + })); + } + catch (Exception ex) + { + return Request.CreateResponse(HttpStatusCode.ExpectationFailed, ex.ToString() + "
" + ex.InnerException.ToString()); + } + } + } } \ No newline at end of file diff --git a/Common/Service/MeterProcessState/MeterProcessState.csproj b/Common/Service/MeterProcessState/MeterProcessState.csproj index 8c8cd0b8..52a2f58e 100644 --- a/Common/Service/MeterProcessState/MeterProcessState.csproj +++ b/Common/Service/MeterProcessState/MeterProcessState.csproj @@ -385,6 +385,10 @@ {2C6378C6-6BA1-4CEE-8992-8404D8369A90} GenesisFile
+ + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} + GenesisStatus + {AC434B18-4D7B-49BA-9AD5-0527C79E8297} GenesisPwd diff --git a/Common/Ui/GenesisToolBox/GenesisToolBox.csproj b/Common/Ui/GenesisToolBox/GenesisToolBox.csproj index d0a13992..bc4bf65e 100644 --- a/Common/Ui/GenesisToolBox/GenesisToolBox.csproj +++ b/Common/Ui/GenesisToolBox/GenesisToolBox.csproj @@ -629,6 +629,10 @@ {ac434b18-4d7b-49ba-9ad5-0527c79e8297} GenesisPwd + + {0F646872-D8DC-4EE5-989F-D4C73F0ACE3F} + GenesisStatus + {8BDD2789-96D4-43EA-AAD7-0F49D0347998} ProtocolCore diff --git a/Common/Ui/GenesisToolBox/frmRegisterStore.cs b/Common/Ui/GenesisToolBox/frmRegisterStore.cs index 165a68cf..c65d1305 100644 --- a/Common/Ui/GenesisToolBox/frmRegisterStore.cs +++ b/Common/Ui/GenesisToolBox/frmRegisterStore.cs @@ -17,6 +17,7 @@ using Xylem.Common.CommonCore.Configuration; using Xylem.Common.CommonCore.Consts; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisConfig; using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore; +using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisStatus; using Xylem.Common.Hardware.WaterMeter.Genesis.Registers; using Xylem.Common.Hardware.WaterMeter.WaterMeterCore; using Xylem.Common.Logic.ServiceCore; @@ -2201,82 +2202,50 @@ namespace Xylem.Common.Ui.GenesisToolBox private void btnBatLife_Click(Object sender, EventArgs e) { - if (cbComSlot.SelectedItem != null) // && cbComSlot.SelectedValue is ListBoxItem) + if (cbComSlot.SelectedItem == null) return; + if (string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) || + !int.TryParse(cbComSlot.SelectedItem.ToString(), out var slotNR)) return; + try { - Int32 slotNR = 0; - if (!string.IsNullOrEmpty(cbComSlot.SelectedItem.ToString()) && - int.TryParse(cbComSlot.SelectedItem.ToString(), out slotNR)) + conntect(slotNR); + foreach (var me in _meterBatch.ListOfMeters) { - try + if (me is GenesisMeter) { - conntect(slotNR); - foreach (var me in _meterBatch.ListOfMeters) + if (((GenesisMeter)me).IsLoggedOn) { - if (me is GenesisMeter) + _currentGenesis = ((GenesisMeter)me); + + var genesisStatus = new GenesisStatus(); + if (GenesisStatusHandler.BuildLifeTimeInformation(_currentGenesis, genesisStatus)) { - if (((GenesisMeter)me).IsLoggedOn) - { - _currentGenesis = ((GenesisMeter)me); + var sbMSG = new StringBuilder(); + sbMSG.AppendLine($"Pcb = {_currentGenesis.PcbId}"); - var POWERMON_TotalUsedSeconds = (double)(RegisterConverter.ConvertTo(_currentGenesis.ReadRegister("POWERMON_TotalUsedSeconds"))); - - var tmp_POWERMON_TotalUsedCharge = _currentGenesis.ReadRegister("POWERMON_TotalUsedCharge", 8); - - var POWERMON_TotalUsedCharge = BitConverter.ToUInt64(tmp_POWERMON_TotalUsedCharge.ToArray(), 0); - - var POWERMON_BatteryQuantity = (double)RegisterConverter.ConvertTo(_currentGenesis.ReadRegister("POWERMON_BatteryQuantity")); - var POWERMON_BatteryMilliAHrRating = (double)RegisterConverter.ConvertTo(_currentGenesis.ReadRegister("POWERMON_BatteryMilliAHrRating")); - - - var lifetimeInSeconds = (POWERMON_TotalUsedSeconds / (double)(POWERMON_TotalUsedCharge)) * (POWERMON_BatteryQuantity * POWERMON_BatteryMilliAHrRating * 1000 * 3600); - var remainingLifetime = lifetimeInSeconds - POWERMON_TotalUsedSeconds; - - - var sbMSG = new StringBuilder(); - sbMSG.AppendLine($"Pcb = {_currentGenesis.PcbId}"); - - sbMSG.AppendLine($"POWERMON_TotalUsedSeconds = {POWERMON_TotalUsedSeconds}"); - sbMSG.AppendLine($"POWERMON_TotalUsedCharge = {POWERMON_TotalUsedCharge}"); - sbMSG.AppendLine($"POWERMON_BatteryQuantity = {POWERMON_BatteryQuantity}"); - sbMSG.AppendLine($"POWERMON_BatteryMilliAHrRating = {POWERMON_BatteryMilliAHrRating}"); - sbMSG.AppendLine(""); - sbMSG.AppendLine($"lifetimeInSeconds = (POWERMON_TotalUsedSeconds / POWERMON_TotalUsedCharge) * (POWERMON_BatteryQuantity * POWERMON_BatteryMilliAHrRating * 1000 * 3600)"); - sbMSG.AppendLine($"{lifetimeInSeconds} = ({POWERMON_TotalUsedSeconds} / {POWERMON_TotalUsedCharge}) * ({POWERMON_BatteryQuantity} * {POWERMON_BatteryMilliAHrRating} * 1000 * 3600)"); - sbMSG.AppendLine(""); - sbMSG.AppendLine("remainingLifetime = lifetimeInSeconds - POWERMON_TotalUsedSeconds"); - sbMSG.AppendLine($"{remainingLifetime} = {lifetimeInSeconds} - {POWERMON_TotalUsedSeconds}"); - sbMSG.AppendLine(""); - sbMSG.AppendLine($"in Years {(remainingLifetime/86400/365)}"); - - - - - //// Time Span in h in mAhr In % with one battery is 100% - ////(((total used change difference / (Time span / 3600) ) / 3600000) / 19000)*100 - var loadAtH = ((((double)POWERMON_TotalUsedCharge / ((double)POWERMON_TotalUsedSeconds / 3600)) / 3600000) / (19000 * 2)) * 100; - var totalUsed = (((double)POWERMON_TotalUsedCharge / 1000000 / 3.6) / ((19000 * 2))) * 100; - - sbMSG.AppendLine($"in % {totalUsed}"); - - - MessageBox.Show(sbMSG.ToString(), $"Battery for {_currentGenesis.PcbId} has remaning life time of {(remainingLifetime / 86400 / 365)} years"); - } + sbMSG.AppendLine($"POWERMON_TotalUsedSeconds = {genesisStatus.ExceededLifeTime_s}"); + sbMSG.AppendLine($"POWERMON_TotalUsedCharge = {genesisStatus.DrainedBatteryPower_uAs}"); + sbMSG.AppendLine($"POWERMON_BatteryQuantity = {genesisStatus.BatteryQuantity}"); + sbMSG.AppendLine($"POWERMON_BatteryMilliAHrRating = {genesisStatus.InitialBatteryLoad_mAh}"); + sbMSG.AppendLine(""); + sbMSG.AppendLine($"Remaining life time in years {genesisStatus.RemainingLifeTimeYears:F2}"); + sbMSG.AppendLine($"Totally drained battery load in % {genesisStatus.DrainedBatteryLoadPercent:F2}"); + MessageBox.Show(sbMSG.ToString(), $"Battery for {_currentGenesis.PcbId} has remaining life " + + $"time of {genesisStatus.RemainingLifeTimeYears:F2} years"); + } + else + { + MessageBox.Show("Failed to get life time information"); } } } - catch (Exception ex) - { - - return; - } - - - return; - } } + catch (Exception ex) + { + MessageBox.Show(ex.ToString()); + } } } } \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs index 02a32027..f69b7c27 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs @@ -1562,9 +1562,7 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder cordonelDbInfo.ReasonForUpdateDenial += Resources.StrUpdateCapabilityCheckMeterSize; checkPassed = false; } - else - ; - + // if the installed version is unknown or not set, leave the approval to the user if (string.IsNullOrEmpty(cordonelDbInfo.Metrology) || cordonelDbInfo.Metrology == Constants.StrUnknown) { @@ -3781,6 +3779,10 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder /// one region and one metrology version as only identical Cordonels should be placed to one safe /// according to the one FW-Package policy. /// + /// + /// - Preselect order number and position to last production number to simplify update order generation, + /// this will cause the update order-pos = production order-pos.. + /// private void gridViewCordonelsSelection_CellClick(Object sender, DataGridViewCellEventArgs e) { try @@ -3837,6 +3839,16 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder cordSearch.IsRemoved = false; if (_cordonelProductionPreSelectInfos.All(x => x.PcbId != cordSelect.PcbId)) _cordonelProductionPreSelectInfos.Add(cordSearch); + // fill text box for update order + if (cordSearch.CustomerOrderNumber > 0 ) + { + tbxOrderNumber.Text = cordSearch.CustomerOrderNumber.ToString(); + } + // fill text box for update position + if (cordSearch.CustomerOrderPos > 0 ) + { + tbxOrderPosition.Text = cordSearch.CustomerOrderPos.ToString(); + } // fill search masks for FW package selection if (!string.IsNullOrEmpty(cordSearch.Diameter) && cordSearch.Diameter != Constants.StrUnknown) diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs index d0fc349d..6862f01e 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs @@ -253,7 +253,6 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw break; case ProcessState.Idle: - ReleaseDisplay(); break; case ProcessState.Stop: @@ -2690,6 +2689,9 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw /// /// - Switch radio on if not NA version. /// + /// + /// - "Release Display" before "Store Configuration". + /// private Boolean ExecConnect() { // logout if already logged in into meter @@ -2730,6 +2732,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw if (_currentGenesis.Login(password)) { if (_currentGenesis.RadioFrequencyMhz != null) ActivateRadio(); + ReleaseDisplay(); StoreConfigurations(); _passwordFileIsCorrupted = false; return true; @@ -2752,6 +2755,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw if (_currentGenesis.Login(skeletonKey)) { if (_currentGenesis.RadioFrequencyMhz != null) ActivateRadio(); + ReleaseDisplay(); StoreConfigurations(); return true; }