iPerlComm : Strict Q2 Error Check, Datastr.proc.started simult.after 'Set test mode', Input ser.buffers flushed, MT locking, Q2 corr.for all Rxyz, ver. 2.27.1870

This commit is contained in:
Milan Hanajik 2022-01-24 12:55:39 +01:00
parent d7fd270cd5
commit 75c97d99e8
6 changed files with 436 additions and 205 deletions

View File

@ -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")]

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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> { 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> { 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> { 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> { 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> { 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> { 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> { Event.UiCmdStop };
}
else
{
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(test.Name, Progress.Completed));
}
if (stopPressed)
{
CloseIPerlCommForm();
return new List<Event> { 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> { Event.Done };
}
@ -603,6 +621,154 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
}
}
/// <summary>
/// Evaluate a given Q2 test result agains stricter error limits when Oruefindex == 1.
/// </summary>
/// <param name="testName">This test name</param>
/// <param name="oriTestRslt">Name of Q2 test done before Q2 correction (Q2adj)</param>
/// <remarks>Assuming this test does not have multiple parts (part = 0)</remarks>
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;
}
}
}
}
/// <summary>
/// Check results of 2 tests: before Q2 correction and after Q2 correction.

View File

@ -211,7 +211,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <param name="nominalFlow">Nominal flow in m3/h</param>
/// <param name="currentFactor">0 or the current Q2 correction factor when updating the factor</param>
/// <returns>Calculated Q2 correction factor</returns>
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
/// </summary>
public void Start()
{
Clear();
ReadPulses();
StartDataStreamProcessing();
lock (this)
{
Clear();
ReadPulses();
StartDataStreamProcessing();
}
}
/// <summary>
@ -592,22 +603,25 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <returns>eventDone</returns>
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
/// <summary>
/// Reset counters / indices / time and start processing and saving datastream data
/// </summary>
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;
/// <summary>
/// 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
/// ...
/// </summary>
/// <param name="optoState">OptoState.Read or OptoState.Flush</param>
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("."));
}
}
}