diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index e9cd9d280..f7a8e0d3f 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.27.1851.0")] -[assembly: AssemblyFileVersion("2.27.1851.0")] +[assembly: AssemblyVersion("2.27.1871.0")] +[assembly: AssemblyFileVersion("2.27.1871.0")] diff --git a/TBF/Rig/TestMethods/iPerlCommunication/TestMethod.cs b/TBF/Rig/TestMethods/iPerlCommunication/TestMethod.cs index 282eb0f43..8b4849536 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/TestMethod.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/TestMethod.cs @@ -2,12 +2,10 @@ /// Copyright (c) 2015-2021 Sensus Slovensko a.s. /// using System; -using System.IO.Ports; using System.Collections.Generic; using log4net; using Common; using Config.Entities; -using TBF.Rig; using TBF.Rig.Sequences; using TBF.UiBridge; diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs index 44ae0ed99..7c27b0bc2 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationForm.cs @@ -1116,9 +1116,34 @@ namespace TBF.Rig.TestMethods.iPerlCommunication if (threadID == 0) { - rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data + /// Check whether previous activity was 'Set test mode A0' or 'A4' + if (i > 0 && multiTestParams[i - 1].Activity.ToLower().Contains(SetTestModeStr.ToLower()) && !multiTestParams[i - 1].Activity.Contains("80")) + { + /// Start processing of opto-datastreams from all iPERL-s + int count = 0; + for (int wmNr0 = 0; wmNr0 < iperlHeads.Count; wmNr0++) + { + Results.Entities.WaterMeter wm = (ProcessData.BatchRslts.Batch.WaterMeters != null && ProcessData.BatchRslts.Batch.WaterMeters.Count > wmNr0) + ? ProcessData.BatchRslts.Batch.WaterMeters[wmNr0] : null; + + IperlHead ihead = iperlHeads[wmNr0]; + + if (ihead != null && wm != null && !wm.Disabled) + { + lock (ihead) + { + ihead.StartDataStreamProcessing(); + count++; + } + } + } + log.WarnFormat("End of activity '{0}', StartDataStreamProcessing() of {1} heads was called.", multiTestParams[i - 1].Activity, count); + } + + /// A new activity starts - information into RFID data log + rfidDataLogger.InfoFormat(""); rfidDataLogger.WarnFormat("Activity = {0}", currentActivity); - rfidDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data + rfidDataLogger.InfoFormat(""); } for (int group = 1; group <= lastGroup; group++) @@ -2578,8 +2603,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication } - if ((q2CorrType == Q2CorrType.ConditionalUpdate && q2adjResult.Passed && q2adjResult2.Passed) || - ((q2CorrType == Q2CorrType.ConditionalUpdateRL || q2CorrType == Q2CorrType.ConditionalUpdateLR) && q2adjResult.Passed)) + if ((q2CorrType == Q2CorrType.ConditionalUpdate || + q2CorrType == Q2CorrType.ConditionalUpdateRL || + q2CorrType == Q2CorrType.ConditionalUpdateLR) && wm.PassedFromTests()) { resultStr = string.Format("No Q2 correction update"); rfidDataLogger.InfoFormat("{0}({1}): No Q2 correction update", ihead.Name, ihead.SerialNr); @@ -2620,18 +2646,31 @@ namespace TBF.Rig.TestMethods.iPerlCommunication /// double q2Correction = 0; double q2Correction2 = 0; /// L-R direction in case of Q2CorrType.Update and Q2CorrType.ConditionalUpdate - /// + + int metroR = 800; + if (string.IsNullOrEmpty(wm.MetrologicalClass()) || + (wm.MetrologicalClass()[0] != 'R' && wm.MetrologicalClass()[0] != 'r') || + !int.TryParse(wm.MetrologicalClass().Substring(1), out metroR) || + metroR <= 0) + { + metroR = 800; /// R800 is the default metrological class + } + if (q2CorrType == Q2CorrType.Update || q2CorrType == Q2CorrType.ConditionalUpdate) { /// Calculate two Q2 correction factors from two tests done in both directions - q2Correction = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, q2adjResult.Q2CorrRL); - q2Correction2 = ihead.CalculateQ2CorrectionFactor(q2adjResult2, ihead.CalibTargetQ2, q2adjTestData2.Qfrom, q2adjResult2.Q2CorrLR); + q2Correction = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, + metroR, q2adjResult.Q2CorrRL); + q2Correction2 = ihead.CalculateQ2CorrectionFactor(q2adjResult2, ihead.CalibTargetQ2, q2adjTestData2.Qfrom, + metroR, q2adjResult2.Q2CorrLR); } else { /// Calculate Q2 correction factors from a single test - q2Correction = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, q2adjResult.Q2CorrRL); - q2Correction2 = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, q2adjResult.Q2CorrLR); + q2Correction = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, + metroR, q2adjResult.Q2CorrRL); + q2Correction2 = ihead.CalculateQ2CorrectionFactor(q2adjResult, ihead.CalibTargetQ2, q2adjTestData.Qfrom, + metroR, q2adjResult.Q2CorrLR); } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationParams.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationParams.cs index c9adc291e..2817a65df 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationParams.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationParams.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2015-2021 Sensus Slovensko a.s. +/// Copyright (c) 2015-2022 Sensus Slovensko a.s. /// using System; using System.IO; @@ -68,6 +68,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionGreeceIncl05Str); retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionRLIncl05Str); retVal.Add(iPerlCommunicationForm.WriteQ2CorrectionLRIncl05Str); + retVal.Add(iPerlCommunicationSeq.Q2correctedFromCmd + "Qx"); + retVal.Add(iPerlCommunicationSeq.StrictQ2ErrorCheckStr + "Qx"); + retVal.Add(iPerlCommunicationSeq.Q2correctionCheckCmd); + retVal.Add(iPerlCommunicationSeq.IperlCheckCmd); retVal.Add(iPerlCommunicationForm.UpdateBothQ2FactorsTestRLOnlyStr); retVal.Add(iPerlCommunicationForm.UpdateBothQ2FactorsTestLROnlyStr); retVal.Add(iPerlCommunicationForm.UpdateQ2CorrectionsStr); diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs index 73e53c948..604b5c293 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlCommunicationSeq.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2015-2020 Sensus Slovensko a.s. +/// Copyright (c) 2015-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -18,6 +18,11 @@ namespace TBF.Rig.TestMethods.iPerlCommunication { private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationSeq)); + public const string Q2correctedFromCmd = "Q2 corrected from "; + public const string StrictQ2ErrorCheckStr = "Strict Q2 error check "; + public const string Q2correctionCheckCmd = "Q2 correction check "; + public const string IperlCheckCmd = "iPERL_check "; + System.Windows.Forms.Form modelessDlg; /// @@ -54,12 +59,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication modelessDlg = null; processDataLoggingOp = new TBF.Rig.Operations.ProcessDataLoggingOp(processDataLogger, this, false); - - const string Q2correctedFromCmd = "q2 corrected from "; - const string Q2correctionCheckCmd = "q2 correction check "; - const string IperlCheckCmd = "iperl_check "; - if (testParams.Activity.ToLower().Equals(iPerlCommunicationForm.GetDefaultQ2CorrectionsStr.ToLower())) + string cmd; + if (testParams.Activity.ToLower().Equals(cmd = iPerlCommunicationForm.GetDefaultQ2CorrectionsStr.ToLower())) { TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); @@ -113,13 +115,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication return new List { Event.Done }; } - else if (testParams.Activity.ToLower().Contains(Q2correctedFromCmd)) + else if (testParams.Activity.ToLower().Contains(cmd = Q2correctedFromCmd.ToLower())) { TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); - string fromTestName = testParams.Activity.Substring(Q2correctedFromCmd.Length); + string fromTestName = testParams.Activity.Substring(cmd.Length); MakeQ2CorrectedFrom(test.Name, fromTestName); @@ -129,13 +131,29 @@ namespace TBF.Rig.TestMethods.iPerlCommunication return new List { Event.Done }; } - else if (testParams.Activity.ToLower().Contains(Q2correctionCheckCmd)) + else if (testParams.Activity.ToLower().Contains(cmd = StrictQ2ErrorCheckStr.ToLower())) { TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); - string[] testNames = testParams.Activity.Substring(Q2correctionCheckCmd.Length).Split(new char[] { ' ' }); + string fromTestName = testParams.Activity.Substring(cmd.Length); + + StrictQ2ErrorCheck(test.Name, fromTestName); + + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed)); + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(test.Name, 0))); + allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file + + return new List { Event.Done }; + } + else if (testParams.Activity.ToLower().Contains(cmd = Q2correctionCheckCmd.ToLower())) + { + TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); + + string[] testNames = testParams.Activity.Substring(cmd.Length).Split(new char[] { ' ' }); if (testNames.Length >= 2) { @@ -148,18 +166,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication return new List { Event.Done }; } - else if (testParams.Activity.ToLower().Contains(IperlCheckCmd)) + else if (testParams.Activity.ToLower().Contains(cmd = IperlCheckCmd.ToLower())) { TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); - string[] args = testParams.Activity.Substring(IperlCheckCmd.Length).Split(new char[] { ' ' }); + string[] args = testParams.Activity.Substring(cmd.Length).Split(new char[] { ' ' }); int maxTestIndex = (ProcessData.BenchInfo is DataContainers.BenchInfo.iPerl.Component) ? (ProcessData.BenchInfo as DataContainers.BenchInfo.iPerl.Component).MaxTestIndex : int.MaxValue; - + Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(test.Name, 0); if (tstRslt != null) @@ -267,77 +285,77 @@ namespace TBF.Rig.TestMethods.iPerlCommunication return new List { Event.Done }; } - else if (testParams.Activity.ToLower().Contains("simulate ")) - { - TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 } ); - Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); - Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); + else if (testParams.Activity.ToLower().Contains(cmd = "simulate ")) + { + TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 }); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.JustStarted)); + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.FlowSetting)); - if (testParams.Activity.ToLower().Contains("q3")) MakeSimulated(test, 1, 0, -0.5f); - else if (testParams.Activity.ToLower().Contains("q2")) MakeSimulated(test, 1, 0, 0.5f); - else if (testParams.Activity.ToLower().Contains("q1")) MakeSimulated(test, 1, 0, -5.1f); - else if (testParams.Activity.ToLower().Contains("compound ok")) MakeSimulatedCompound(test, 1, 0, 0.7f, 1.0f); - else if (testParams.Activity.ToLower().Contains("compound nok")) MakeSimulatedCompound(test, 1, 0, 4.7f, 0.9f); - else if (testParams.Activity.ToLower().Contains("compound rise")) MakeSimulatedCompound(test, 1, 0, 0.7f, 0.0f); - else if (testParams.Activity.ToLower().Contains("compound fall")) MakeSimulatedCompound(test, 1, 0, 0.7f, 0.9f); + if (testParams.Activity.ToLower().Contains("q3")) MakeSimulated(test, 1, 0, -0.5f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "q2") MakeSimulated(test, 1, 0, 0.5f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "q1") MakeSimulated(test, 1, 0, -5.1f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound ok") MakeSimulatedCompound(test, 1, 0, 0.7f, 1.0f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound nok") MakeSimulatedCompound(test, 1, 0, 4.7f, 0.9f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound rise") MakeSimulatedCompound(test, 1, 0, 0.7f, 0.0f); + else if (testParams.Activity.Substring(cmd.Length).ToLower() == "compound fall") MakeSimulatedCompound(test, 1, 0, 0.7f, 0.9f); - Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed)); - Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0))); - allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file + Bridge.OnTestProgress(this, new TestProgressEventArgs(test, Progress.Completed)); + Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, ProcessData.BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0))); + allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file - //------------------------------------------------ - Bridge.OnActivity(this, testParams.Activity); - //------------------------------------------------ + //------------------------------------------------ + Bridge.OnActivity(this, testParams.Activity); + //------------------------------------------------ - State.Create(string.Format("iPerlCommunicationSeq : {0}", testParams.Activity)) - .AddOperation(checkUiOp) - .EnterState(); - e = StateMachine.WaitRunDevsRunOps(); + State.Create(string.Format("iPerlCommunicationSeq : {0}", testParams.Activity)) + .AddOperation(checkUiOp) + .EnterState(); + e = StateMachine.WaitRunDevsRunOps(); if (TestAndLogUiCmdStop(test, e)) { return new List { Event.UiCmdStop }; } - } - else - { - /// - /// Show the modeless dialog with error indication - /// - Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, cfg, test, testParams }); + } + else + { + /// + /// Show the modeless dialog with error indication + /// + Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, cfg, test, testParams }); - //------------------------------------------------ - Bridge.OnActivity(this, Strings.iPerl_Communication_in_progress); - //------------------------------------------------ + //------------------------------------------------ + Bridge.OnActivity(this, Strings.iPerl_Communication_in_progress); + //------------------------------------------------ - bool stopPressed = false; /// true when STOP button pressed - bool completed = false; + bool stopPressed = false; /// true when STOP button pressed + bool completed = false; - State.Create("iPerlCommunicationSeq : Wait until the entry form is closed") - .AddOperation(checkUiOp) - .EnterState(); - do - { - e = StateMachine.WaitRunDevsRunOps(); - stopPressed = TestAndLogUiCmdStop(test,e); - completed = (modelessDlg is GenericDevices.IHasCompleted) - && (modelessDlg as GenericDevices.IHasCompleted).Completed; - } - while (!stopPressed && !completed); + State.Create("iPerlCommunicationSeq : Wait until the entry form is closed") + .AddOperation(checkUiOp) + .EnterState(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + stopPressed = TestAndLogUiCmdStop(test, e); + completed = (modelessDlg is GenericDevices.IHasCompleted) + && (modelessDlg as GenericDevices.IHasCompleted).Completed; + } + while (!stopPressed && !completed); - if (stopPressed) - { - CloseIPerlCommForm(); - return new List { Event.UiCmdStop }; - } - else - { - TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(test.Name, Progress.Completed)); - } + if (stopPressed) + { + CloseIPerlCommForm(); + return new List { Event.UiCmdStop }; + } + else + { + TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(test.Name, Progress.Completed)); + } - /// Test 'Quit' - modelessDlg = null; /// Modeless dialog is closed now - } + /// Test 'Quit' + modelessDlg = null; /// Modeless dialog is closed now + } return new List { Event.Done }; } @@ -603,6 +621,154 @@ namespace TBF.Rig.TestMethods.iPerlCommunication } } + /// + /// Evaluate a given Q2 test result agains stricter error limits when Oruefindex == 1. + /// + /// This test name + /// Name of Q2 test done before Q2 correction (Q2adj) + /// Assuming this test does not have multiple parts (part = 0) + void StrictQ2ErrorCheck(string testName, string oriTestName) + { + Results.Entities.TestRslt oriTestRslt = ProcessData.BatchRslts.GetTestRslt(oriTestName, 0); + Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(testName, 0); + + if (oriTestRslt == null || tstRslt == null) return; + + tstRslt.Components = oriTestRslt.Components; + + /// Auxiliary results, as in SequenceBase.UpdateTemoPressDensAmb() + tstRslt.AmbTempMean = oriTestRslt.AmbTempMean; + tstRslt.AmbTempStart = oriTestRslt.AmbTempStart; + tstRslt.AmbTempEnd = oriTestRslt.AmbTempEnd; + tstRslt.AmbTempMin = oriTestRslt.AmbTempMin; + tstRslt.AmbTempMax = oriTestRslt.AmbTempMax; + tstRslt.AmbPressMean = oriTestRslt.AmbPressMean; + tstRslt.AmbPressStart = oriTestRslt.AmbPressStart; + tstRslt.AmbPressEnd = oriTestRslt.AmbPressEnd; + tstRslt.AmbPressMin = oriTestRslt.AmbPressMin; + tstRslt.AmbPressMax = oriTestRslt.AmbPressMax; + tstRslt.AmbHumiMean = oriTestRslt.AmbHumiMean; + tstRslt.AmbHumiStart = oriTestRslt.AmbHumiStart; + tstRslt.AmbHumiEnd = oriTestRslt.AmbHumiEnd; + tstRslt.AmbHumiMin = oriTestRslt.AmbHumiMin; + tstRslt.AmbHumiMax = oriTestRslt.AmbHumiMax; + tstRslt.PressUpMean = oriTestRslt.PressUpMean; + tstRslt.PressUpStart = oriTestRslt.PressUpStart; + tstRslt.PressUpEnd = oriTestRslt.PressUpEnd; + tstRslt.PressUpMin = oriTestRslt.PressUpMin; + tstRslt.PressUpMax = oriTestRslt.PressUpMax; + tstRslt.PressDownMean = oriTestRslt.PressDownMean; + tstRslt.PressDownStart = oriTestRslt.PressDownStart; + tstRslt.PressDownEnd = oriTestRslt.PressDownEnd; + tstRslt.PressDownMin = oriTestRslt.PressDownMin; + tstRslt.PressDownMax = oriTestRslt.PressDownMax; + tstRslt.PressDeltaMean = oriTestRslt.PressDeltaMean; + tstRslt.PressDeltaStart = oriTestRslt.PressDeltaStart; + tstRslt.PressDeltaEnd = oriTestRslt.PressDeltaEnd; + tstRslt.PressDeltaMin = oriTestRslt.PressDeltaMin; + tstRslt.PressDeltaMax = oriTestRslt.PressDeltaMax; + tstRslt.ConductMean = oriTestRslt.ConductMean; + tstRslt.ConductStart = oriTestRslt.ConductStart; + tstRslt.ConductEnd = oriTestRslt.ConductEnd; + tstRslt.ConductMin = oriTestRslt.ConductMin; + tstRslt.ConductMax = oriTestRslt.ConductMax; + tstRslt.TempUpMean = oriTestRslt.TempUpMean; + tstRslt.TempUpStart = oriTestRslt.TempUpStart; + tstRslt.TempUpEnd = oriTestRslt.TempUpEnd; + tstRslt.TempUpMin = oriTestRslt.TempUpMin; + tstRslt.TempUpMax = oriTestRslt.TempUpMax; + tstRslt.TempDownMean = oriTestRslt.TempDownMean; + tstRslt.TempDownStart = oriTestRslt.TempDownStart; + tstRslt.TempDownEnd = oriTestRslt.TempDownEnd; + tstRslt.TempDownMin = oriTestRslt.TempDownMin; + tstRslt.TempDownMax = oriTestRslt.TempDownMax; + tstRslt.TempDivMean = oriTestRslt.TempDivMean; + tstRslt.TempDivStart = oriTestRslt.TempDivStart; + tstRslt.TempDivEnd = oriTestRslt.TempDivEnd; + tstRslt.TempDivMin = oriTestRslt.TempDivMin; + tstRslt.TempDivMax = oriTestRslt.TempDivMax; + tstRslt.DensityIn = oriTestRslt.DensityIn; + tstRslt.DensityLine = oriTestRslt.DensityLine; + tstRslt.DensityDiv = oriTestRslt.DensityDiv; + + tstRslt.StartTime = oriTestRslt.StartTime; + tstRslt.EndTime = oriTestRslt.EndTime; + tstRslt.FlowSetTime = oriTestRslt.FlowSetTime; + tstRslt.TestTime = oriTestRslt.TestTime; + tstRslt.PulsesMaster = oriTestRslt.PulsesMaster; + tstRslt.ConstMasterRaw = oriTestRslt.ConstMasterRaw; + tstRslt.ConstMaster = oriTestRslt.ConstMaster; + tstRslt.MassStartRaw = oriTestRslt.MassStartRaw; + tstRslt.MassStart = oriTestRslt.MassStart; + tstRslt.MassEndRaw = oriTestRslt.MassEndRaw; + tstRslt.MassEnd = oriTestRslt.MassEnd; + tstRslt.MassOfEvapWater = oriTestRslt.MassOfEvapWater; + tstRslt.FlowMass = oriTestRslt.FlowMass; + tstRslt.FlowVolume = oriTestRslt.FlowVolume; + tstRslt.VolumeCTV = oriTestRslt.VolumeCTV; + tstRslt.VolumeMaster = oriTestRslt.VolumeMaster; + tstRslt.ErrorMaster = oriTestRslt.ErrorMaster; + + tstRslt.FlowMean = oriTestRslt.FlowMean; + tstRslt.FlowMin = oriTestRslt.FlowMin; + tstRslt.FlowMax = oriTestRslt.FlowMax; + + tstRslt.Custom1 = oriTestRslt.Custom1; + tstRslt.Custom2 = oriTestRslt.Custom2; + tstRslt.Custom3 = oriTestRslt.Custom3; + tstRslt.Custom4 = oriTestRslt.Custom4; + tstRslt.Custom5 = oriTestRslt.Custom5; + tstRslt.Custom6 = oriTestRslt.Custom6; + tstRslt.Custom7 = oriTestRslt.Custom7; + tstRslt.Custom8 = oriTestRslt.Custom8; + + for (int i = 0; i < ProcessData.BatchRslts.WMPositionsCount; i++) + { + Results.Entities.MeterTestRslt oriMeterRslt = ProcessData.BatchRslts.GetMeterTestRslt(oriTestName, i, CompoundMeterId.Single); + Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(testName, i, CompoundMeterId.Single); + + /// Reference to iPerl water meter or null: + TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = ((sensPath != null) && (sensPath.RegisterReaders != null) && (i < sensPath.RegisterReaders.Length)) + ? (sensPath.RegisterReaders[i] as TestMethods.iPerlCommunication.iPerlHead.IperlHead) + : null; + + if (meterRslt != null && oriMeterRslt != null) + { +#if ORACLE_DB + meterRslt.ErrorBC = oriMeterRslt.Error; +#endif + meterRslt.PulsesMeter = oriMeterRslt.PulsesMeter; + meterRslt.PulsesMaster = oriMeterRslt.PulsesMaster; + meterRslt.PulsesPerLiter = oriMeterRslt.PulsesPerLiter; + meterRslt.VolumeRef = oriMeterRslt.VolumeRef; + meterRslt.TestTime = oriMeterRslt.TestTime; + + if (iPerl != null && ProcessData.BatchRslts.Batch.WaterMeters[i] != null && + !ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled) + { + /// Either no iPerl head or no Q2 correction + meterRslt.Error = oriMeterRslt.Error; + meterRslt.VolumeMeter = oriMeterRslt.VolumeMeter; + meterRslt.VolumeStart = oriMeterRslt.VolumeStart; + meterRslt.VolumeEnd = oriMeterRslt.VolumeEnd; +#if ORACLE_DB + if (ProcessData.BatchRslts.Batch.WaterMeters[i].Pruefindex == 1) + { + meterRslt.Passed = (oriMeterRslt.Error >= tstRslt.ErrLimLo() + tstRslt.ErrLimMargin() + && oriMeterRslt.Error <= tstRslt.ErrLimHi() - tstRslt.ErrLimMargin()); + } + else +#endif + { + meterRslt.Passed = oriMeterRslt.Passed; + } + meterRslt.TestDone = true; + tstRslt.TestDone = true; + } + } + } + } + /// /// Check results of 2 tests: before Q2 correction and after Q2 correction. diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index 15dc1af22..736ca2e0a 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -211,7 +211,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// Nominal flow in m3/h /// 0 or the current Q2 correction factor when updating the factor /// Calculated Q2 correction factor - public double CalculateQ2CorrectionFactor(Results.Entities.MeterTestRslt q2adjResult, double calibTarget, double nominalFlow, int currentFactor = 0) + public double CalculateQ2CorrectionFactor(Results.Entities.MeterTestRslt q2adjResult, double calibTarget, double nominalFlow, int metroR, int currentFactor = 0) { double nominalTestFlowLph = Common.Units.ConvertTo(Common.Unit.lph, nominalFlow); double volumeRefShiftedToTarget = q2adjResult.VolumeRef * (1.0 + calibTarget / 100.0); @@ -224,7 +224,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead double F = D / (nominalTestFlowLph * 10.0); /// Error corrected with 8 Raw Units per minute [%] double G = F / B; /// Error corrected with 1 Raw Unit per minute [%] - double q2CorrectionFactor = (double)currentFactor - (q2adjErrorShiftedToTarget / G) * (volumeRefShiftedToTarget / q2adjResult.VolumeMeter); + double q2CorrectionFactor = (double)currentFactor + - (800.0 / metroR) * (q2adjErrorShiftedToTarget / G) * (volumeRefShiftedToTarget / q2adjResult.VolumeMeter); log.WarnFormat("CalculateQ2CorrectionFactor() : Pos={0}, PCB#={1}, Error={2}%, CalTarget={3}%, Q2CorrFactor={4}", Name, @@ -291,6 +292,18 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { StopDataStreamProcessing(); + /// Dummy '#### start test ####' and '#### end of test ####' marks are added + /// to the raw data file on request of Joern Goege + if (optoDataCount >= 100 && optoDataCount <= optoData.Length && + optoData[40].Flags == OptoTelegramFlags.OK && + optoData[optoDataCount - 40].Flags == OptoTelegramFlags.OK) + { + optoData[40].Flags = OptoTelegramFlags.OK_TestStart; + optoData[optoDataCount - 40].Flags = OptoTelegramFlags.OK_TestEnd; + } + + DataStreamPostProcessing(); + string pcbNr = (ConfigStruct != null) ? ConfigStruct.GetPcbNrString() : "UnknownPcbNr"; string wmPosition = Name.Substring(5); /// WMPosition is extracted from a component name in form 'iPerl#' if (wmPosition.Length == 1) wmPosition = "0" + wmPosition; @@ -408,7 +421,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead if (DebugLevel == DebugMode.Normal) { - /// Prepare serial port + /// Open serial port: 9600 Bd, 8 data bits, 1 stop bit, no parity string portName = string.Format("COM{0}", iperlHeadCfg.OptoComPortNr); optoSerialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One); optoSerialPort.Handshake = Handshake.None; @@ -445,14 +458,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead Q2CorrRL = 0; Q2CorrLR = 0; - if (optoSerialPort != null && optoSerialPort.IsOpen) - { - optoSerialPort.DiscardInBuffer(); - } - StartDataStreamProcessing(); + dataStreamState = DataStreamState.Flush; currentFlowDir = InitFlowDir; - if (flowDirectionDetection != null) flowDirectionDetection.ClearFifo(); /// Clear FIFO for flow direction detection } public void SaveMark(object mark) @@ -581,9 +589,12 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// public void Start() { - Clear(); - ReadPulses(); - StartDataStreamProcessing(); + lock (this) + { + Clear(); + ReadPulses(); + StartDataStreamProcessing(); + } } /// @@ -592,22 +603,25 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// eventDone public Event Run() { - timeFromStart += StateMachine.Period; - ReadPulses(); + lock (this) + { + timeFromStart += StateMachine.Period; + ReadPulses(); - if (!startSampleAcquired && (timeFromStart >= 8) && (currentTelegramIx >= 0)) - { - /// Take the test start sample - startSampleAcquired = true; - TestStartTelegramIx = currentTelegramIx; - } - else if (startSampleAcquired) - { - /// Shift data in pipelines - TestEndTelegramIx = endTelegramIdx3; - endTelegramIdx3 = endTelegramIdx2; - endTelegramIdx2 = endTelegramIdx1; - endTelegramIdx1 = currentTelegramIx; + if (!startSampleAcquired && (timeFromStart >= 8) && (currentTelegramIx >= 0)) + { + /// Take the test start sample + startSampleAcquired = true; + TestStartTelegramIx = currentTelegramIx; + } + else if (startSampleAcquired) + { + /// Shift data in pipelines + TestEndTelegramIx = endTelegramIdx3; + endTelegramIdx3 = endTelegramIdx2; + endTelegramIdx2 = endTelegramIdx1; + endTelegramIdx1 = currentTelegramIx; + } } return Event.ReadRegisterDone; @@ -622,8 +636,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead int startIx; int endIx; - AddTestStartEndMarksToData(out startIx, out endIx); - StopDataStreamProcessing(); + + lock (this) + { + StopDataStreamProcessing(); + AddTestStartEndMarksToData(out startIx, out endIx); + } + DataStreamPostProcessing(); // TODO: Enable when calculations completed @@ -835,7 +854,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// /// Reset counters / indices / time and start processing and saving datastream data /// - void StartDataStreamProcessing() + public void StartDataStreamProcessing() { /// Reset opto-data, etc. optoDataCount = 0; @@ -848,6 +867,10 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead endTelegramIdx3 = 0; TestEndTelegramIx = 0; + if (optoSerialPort != null && optoSerialPort.IsOpen) optoSerialPort.DiscardInBuffer(); + + if (flowDirectionDetection != null) flowDirectionDetection.ClearFifo(); /// Clear FIFO for flow direction detection + /// Enable opto-data parsing and saving dataStreamState = DataStreamState.ProcessAndSave; } @@ -876,110 +899,111 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead string partOfTelegram; /// - /// 9600 Bd, 8 data bits, 1 stop bit, no parity - /// + /// Reads opto-datastream via serual port. Invoked from RunDeviceBefore() + /// /// Telegram description: - /// - /// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes) - /// + /// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes) /// Example: - /// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86 - /// FFDD3A 51F9 0000 65324E 0088 F631A60B 45 + /// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86 + /// FFDD3A 51F9 0000 65324E 0088 F631A60B 45 /// ... /// /// OptoState.Read or OptoState.Flush void ReadOptoData(DataStreamState optoState) { - int nrBytes = optoSerialPort.BytesToRead; - if (nrBytes > 0) - { - char[] buffer = new char[nrBytes]; - optoSerialPort.Read(buffer, 0, nrBytes); - string received = new string(buffer); + lock (this) + { + int nrBytes = optoSerialPort.BytesToRead; + if (nrBytes > 0) + { + char[] buffer = new char[nrBytes]; + optoSerialPort.Read(buffer, 0, nrBytes); + string received = new string(buffer); - string allRcvd = partOfTelegram + received; + string allRcvd = partOfTelegram + received; - while (true) - { - int pos = allRcvd.IndexOf("\r\n"); + while (true) + { + int pos = allRcvd.IndexOf("\r\n"); - if (pos < 0) - { - /// No CR+LF found, wait for more characters in the next invocation - partOfTelegram = allRcvd; - return; - } - else - { - /// CR+LF found - if (optoState == DataStreamState.ProcessAndSave) - { - int bufferIx = BufferIdx(optoDataCount); + if (pos < 0) + { + /// No CR+LF found, wait for more characters in the next invocation + partOfTelegram = allRcvd; + return; + } + else + { + /// CR+LF found + if (optoState == DataStreamState.ProcessAndSave) + { + int bufferIx = BufferIdx(optoDataCount); - if (pos < OptoTelegramRaw.Length - 2) - { - /// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop - allRcvd = allRcvd.Substring(pos + 2); - if (synchronized) - { - optoData[bufferIx].Counter = optoDataCount; - optoData[bufferIx].SetFlags(OptoTelegramFlags.SyncError); - } - synchronized = true; - } - else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), - optoDataCount, - Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), - ref volumeRawExtLast, ref timestampExtLast)) - { - /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK - flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); - OptoTelegramRreceived(optoDataCount, synchronized2, volumeRawExtLast, timestampExtLast); - synchronized2 = synchronized; - allRcvd = allRcvd.Substring(pos + 2); - } - else - { - /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) but the telgram was not OK - optoData[bufferIx].Counter = optoDataCount; - optoDataCount++; - allRcvd = allRcvd.Substring(pos + 2); - } + if (pos < OptoTelegramRaw.Length - 2) + { + /// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop + allRcvd = allRcvd.Substring(pos + 2); + if (synchronized) + { + optoData[bufferIx].Counter = optoDataCount; + optoData[bufferIx].SetFlags(OptoTelegramFlags.SyncError); + } + synchronized = true; + } + else if (optoData[bufferIx].UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), + optoDataCount, + Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), + ref volumeRawExtLast, ref timestampExtLast)) + { + /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) && the telegram is OK + flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); + OptoTelegramRreceived(optoDataCount, synchronized2, volumeRawExtLast, timestampExtLast); + synchronized2 = synchronized; + allRcvd = allRcvd.Substring(pos + 2); + } + else + { + /// CR+LF was found && (pos >= OptoTelegramRaw.Length - 2) but the telgram was not OK + optoData[bufferIx].Counter = optoDataCount; + optoDataCount++; + allRcvd = allRcvd.Substring(pos + 2); + } - optoDataCount++; - } - else /// optoState == OptoState.Flush - { - if (pos < OptoTelegramRaw.Length - 2) - { - /// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop - allRcvd = allRcvd.Substring(pos + 2); - synchronized = true; - } - // CR+LF found and (pos >= OptoTelegram.Length - 2) - else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), - 0, - Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), - ref volumeRawExtLast, ref timestampExtLast)) - { - flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); - synchronized2 = synchronized; - allRcvd = allRcvd.Substring(pos + 2); - } - else - { - allRcvd = allRcvd.Substring(pos + 2); - } - } - } - } + optoDataCount++; + } + else /// optoState == OptoState.Flush + { + if (pos < OptoTelegramRaw.Length - 2) + { + /// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop + allRcvd = allRcvd.Substring(pos + 2); + synchronized = true; + } + // CR+LF found and (pos >= OptoTelegram.Length - 2) + else if (toBeFlushed.UpdateFromString(allRcvd.Substring(pos - OptoTelegramRaw.Length + 2), + 0, + Convert.ToSingle(Sequences.ProcessData.RefFlow.Val), + ref volumeRawExtLast, ref timestampExtLast)) + { + flowDirectionDetection.WriteToFifo(volumeRawExtLast, timestampExtLast); + synchronized2 = synchronized; + allRcvd = allRcvd.Substring(pos + 2); + } + else + { + allRcvd = allRcvd.Substring(pos + 2); + } + } + } + } - //OnOptoReceived(this, new OptoReceivedEventArgs(s)); - } - else - { - //OnOptoReceived(this, new OptoReceivedEventArgs(".")); - } + //OnOptoReceived(this, new OptoReceivedEventArgs(s)); + } + else + { + //OnOptoReceived(this, new OptoReceivedEventArgs(".")); + } + } }