TM.iPerlCommunication and IperlHead synced with v.2.27, ISessionDataMngmnt replaces IHasClearSessionData and IHasTestName.

This commit is contained in:
Milan Hanajik
2022-01-28 14:43:33 +01:00
parent b9b609cabf
commit c18f06af07
30 changed files with 1460 additions and 721 deletions
@@ -1,12 +0,0 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
namespace TBF.Rig.GenericDevices
{
public interface IHasClearSessionData
{
void ClearSessionData();
}
}
-14
View File
@@ -1,14 +0,0 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
namespace TBF.Rig.GenericDevices
{
public interface IHasTestName
{
string TestName { set; }
int TestRepeats { set; }
int RepetitionNr { set; }
}
}
@@ -2,6 +2,7 @@
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using Config.Entities;
namespace TBF.Rig.GenericDevices
{
@@ -9,6 +10,8 @@ namespace TBF.Rig.GenericDevices
{
IOperation ReadDatastreamOp();
void TestIsGoingToStartSoon(Test test, int repetitionNr);
bool NoSamples { get; }
double VolumeLtrStart { get; }
double VolumeLtrEnd { get; }
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
namespace TBF.Rig.GenericDevices
{
public interface ISessionDataMngmnt
{
/// <summary>
/// Called when a new session is started
/// </summary>
/// <param name="dataStreamFileName">File name for the log file</param>
void StartSession();
/// <summary>
/// Called when a mark inside a session nees to be saved
/// </summary>
/// <param name="mark">Arbitrary object, ToString() method is used to show marks in log files</param>
void SaveMark(object mark);
/// <summary>
/// Called when a new session is completed
/// </summary>
void EndSession();
}
}
@@ -91,6 +91,17 @@ namespace TBF.Rig.RegisterReaders.DataStream.Reader
public double EndWMState { get { return endWMState; } } /// Test end state of the water meter
/// <summary>
/// Store/update values to be used as a part of the opto-data log file name.
/// </summary>
/// <param name="test">Currently executed test</param>
/// <param name="repetitionNr">Currently executed repetition number</param>
public void TestIsGoingToStartSoon(Config.Entities.Test test, int repetitionNr)
{
/// Nothing needs to be updated
}
/// To be used at the beginning of a test
public void Clear()
{
@@ -14,7 +14,7 @@ namespace TBF.Rig.RegisterReaders.S640Stream
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class S640Stream : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
public class S640Stream : ComponentBase, IDevice, IRegReaderDatastream, ISessionDataMngmnt, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(S640Stream));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
@@ -51,11 +51,19 @@ namespace TBF.Rig.RegisterReaders.S640Stream
double wmTestTime;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string TestName { set { testName = value; } }
public int TestRepeats { set { testRepeats = value; } }
public int RepetitionNr { set { repetitionNr = value; } }
///
/// <summary>
/// Store/update values to be used as a part of the opto-data log file name.
/// </summary>
/// <param name="test">Currently executed test</param>
/// <param name="repetitionNr">Currently executed repetition number</param>
public void TestIsGoingToStartSoon(Config.Entities.Test test, int repetitionNr)
{
/// Store/update values to be used as a part of the opto-data log file name
testName = test.Name;
testRepeats = test.Repeats;
this.repetitionNr = repetitionNr;
}
///
string testName;
int testRepeats;
int repetitionNr;
@@ -170,7 +178,7 @@ namespace TBF.Rig.RegisterReaders.S640Stream
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearSessionData()
public void StartSession()
{
currentRawVolumeUnwrapped = 0;
currentRawTimeUnwrapped = 0;
@@ -194,9 +202,17 @@ namespace TBF.Rig.RegisterReaders.S640Stream
partOfTelegram = string.Empty;
}
public void SaveMark(object mark)
{
}
public void EndSession()
{
datastreamParsingEnabled = false;
}
public override void Initialize()
{
ClearSessionData();
datastreamParsingEnabled = false;
/// Allocate memory for opto-data from iPerl
@@ -312,6 +328,11 @@ namespace TBF.Rig.RegisterReaders.S640Stream
ReadPulses();
}
public void TestCompleted()
{
/// TODO: Implement
}
int timeFromStart; /// This is to determine when the test start sample should be taken
@@ -473,7 +494,7 @@ namespace TBF.Rig.RegisterReaders.S640Stream
beginWMState = volumeLtr0;
endWMState = volumeLtr;
wmVolume = Math.Abs(endWMState - beginWMState);
wmPulses = (int)(wmVolume * (double)PulsesPerLtr + 0.5);
wmPulses = Convert.ToInt32(Math.Round(wmVolume * PulsesPerLtr));
wmRefPulses = StateMachine.ControlBoard.RefPulses;
wmTestTime = timestampSec - timestampSec0;
}
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
namespace TBF.Rig.RegisterReaders.SerialStream
{
@@ -10,13 +11,13 @@ namespace TBF.Rig.RegisterReaders.SerialStream
public readonly int FrameLength; /// Frame length in characters/bytes, 0 = unknown
public readonly double FrameFrequency; /// Number of frames per second (Hz)
public readonly Common.Unit VolumeUnits;
public readonly Unit VolumeUnits;
public readonly double VolumeScaleFactor; /// Volume in VolumeInits = volmeRaw / VolumeScaleFactor
public readonly int VolumeFieldStart; /// Start of the volume field: 0-based index of the first character, -1 = no volume field in the frame
public readonly int VolumeFieldEnd; /// End of the volume field: 0-based index of the last character
public readonly FieldFormat VolumeFieldFormat; /// Hexadecimal or Decimal
public readonly Common.Unit TimeUnits;
public readonly Unit TimeUnits;
public readonly double TimeScaleFactor; /// Time in TimeUnits = timeRaw / TimeScaleFactor
public readonly int TimeFieldStart; /// Start of the time field: 0-based index of the first character, -1 = no time field in the frame
public readonly int TimeFieldEnd; /// End of the time field: 0-based index of the last character
@@ -38,9 +39,9 @@ namespace TBF.Rig.RegisterReaders.SerialStream
public readonly long RawTimeIncrementPerFrame;
public FrameFormat(int frameLength, double frameFrequency,
Common.Unit volumeUnits, double volumeScaleFactor,
Unit volumeUnits, double volumeScaleFactor,
int volumeFieldStart, int volumeFieldEnd, FieldFormat volumeFieldFormat,
Common.Unit timeUnits, double timeScaleFactor,
Unit timeUnits, double timeScaleFactor,
int timeFieldStart, int timeFieldEnd, FieldFormat timeFieldFormat)
{
FrameLength = frameLength;
@@ -112,9 +112,9 @@ namespace TBF.Rig.RegisterReaders.SerialStream
case 2: FrameFrequency = Utils.ParseUDouble(strValue); return CfgUpdateFlags.None;
case 3:
for (Common.Unit u = 0; u < Common.Unit.Count; u++)
for (Unit u = 0; u < Unit.Count; u++)
{
if (Common.Units.IsQuantity(u, Quantity.Volume) && u.ToDescription().Equals(strValue))
if (Units.IsQuantity(u, Quantity.Volume) && u.ToDescription().Equals(strValue))
{
VolumeUnits = u;
return CfgUpdateFlags.None;
@@ -132,9 +132,9 @@ namespace TBF.Rig.RegisterReaders.SerialStream
break;
case 8:
for (Common.Unit u = 0; u < Common.Unit.Count; u++)
for (Unit u = 0; u < Unit.Count; u++)
{
if (Common.Units.IsQuantity(u, Quantity.Time) && u.ToDescription().Equals(strValue))
if (Units.IsQuantity(u, Quantity.Time) && u.ToDescription().Equals(strValue))
{
TimeUnits = u;
return CfgUpdateFlags.None;
@@ -180,9 +180,9 @@ namespace TBF.Rig.RegisterReaders.SerialStream
break;
case 3:
for (Common.Unit u = 0; u < Common.Unit.Count; u++)
for (Unit u = 0; u < Unit.Count; u++)
{
if (Common.Units.IsQuantity(u, Quantity.Volume) && u.ToDescription().Equals(strValue))
if (Units.IsQuantity(u, Quantity.Volume) && u.ToDescription().Equals(strValue))
{
return true;
}
@@ -199,9 +199,9 @@ namespace TBF.Rig.RegisterReaders.SerialStream
break;
case 8:
for (Common.Unit u = 0; u < Common.Unit.Count; u++)
for (Unit u = 0; u < Unit.Count; u++)
{
if (Common.Units.IsQuantity(u, Quantity.Time) && u.ToDescription().Equals(strValue))
if (Units.IsQuantity(u, Quantity.Time) && u.ToDescription().Equals(strValue))
{
return true;
}
@@ -16,7 +16,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class SerialStream : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
public class SerialStream : ComponentBase, IDevice, IRegReaderDatastream, ISessionDataMngmnt, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SerialStream));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
@@ -92,18 +92,24 @@ namespace TBF.Rig.RegisterReaders.SerialStream
double wmTestTime;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string TestName { set { testName = value; } }
public int TestRepeats { set { testRepeats = value; } }
public int RepetitionNr { set { repetitionNr = value; } }
/// <summary>
/// Store/update values to be used as a part of the opto-data log file name.
/// Stop data stream processing and saving, if it is enabled.
/// </summary>
/// <param name="test">Currently executed test</param>
/// <param name="repetitionNr">Currently executed repetition number</param>
public void TestIsGoingToStartSoon(Config.Entities.Test test, int repetitionNr)
{
/// Store/update values to be used as a part of the opto-data log file name
testName = test.Name;
testRepeats = test.Repeats;
this.repetitionNr = repetitionNr;
}
///
string testName;
int testRepeats;
int repetitionNr;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string BenchName;
///
/// Volume of water from the opto telegram
@@ -123,6 +129,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
///
/// Timestamp from the opto telegram
///
bool lastTimestampValid;
private Int64 lastTimestamp;
private double timestampSec;
private double timestampSec0;
@@ -183,22 +190,10 @@ namespace TBF.Rig.RegisterReaders.SerialStream
: base(cfg)
{
myCfg = cfg as SerialStreamCfg;
log.Warn(this.ToString());
}
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearSessionData()
{
commFailed = false;
datastreamFramesCount = 0;
}
public override void Initialize()
{
ClearSessionData();
datastreamParsingEnabled = false;
currentFrameFormat = new FrameFormat(FrameLength, FrameFrequency,
VolumeUnits, VolumeScaleFactor,
@@ -228,7 +223,8 @@ namespace TBF.Rig.RegisterReaders.SerialStream
myCfg.StopBits);
serialPort.Handshake = myCfg.Handshake;
serialPort.Open();
serialPort.Open();
log.FatalFormat("{0} initialized: {1}", Name, this);
}
else if (DebugLevel == DebugMode.Simulate)
{
@@ -240,7 +236,32 @@ namespace TBF.Rig.RegisterReaders.SerialStream
{
MessageBox.Show("Missing file C:\\TBF\\Simulate\\seriastream.txt");
}
log.FatalFormat("{0} simulated: {1}", Name, this);
}
else
{
serialPort = null;
log.FatalFormat("{0} in other mode: {1}", Name, this);
}
}
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void StartSession()
{
commFailed = false;
datastreamFramesCount = 0;
}
public void SaveMark(object mark)
{
/// TODO
}
public void EndSession()
{
datastreamParsingEnabled = false;
}
public void RunDeviceBefore()
@@ -313,6 +334,11 @@ namespace TBF.Rig.RegisterReaders.SerialStream
ReadPulses();
}
public void TestCompleted()
{
/// TODO: Implement
}
int sampleNr; /// This is to determine when the test start sample should be taken
@@ -426,8 +452,8 @@ namespace TBF.Rig.RegisterReaders.SerialStream
beginWMState = volumeLtr0;
endWMState = volumeLtr;
wmVolume = Math.Abs(endWMState - beginWMState);
wmPulses = (int)(wmVolume * (double)PulsesPerLtr + 0.5);
wmRefPulses = StateMachine.ControlBoard.RefPulses;
wmPulses = Convert.ToInt32(Math.Round(wmVolume * PulsesPerLtr));
wmRefPulses = StateMachine.ControlBoard.RefPulses;
wmTestTime = timestampSec - timestampSec0;
}
@@ -610,7 +636,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
public static double UnitVolume(Common.Unit units, double scaleFactor)
{
if (Common.Units.IsQuantity(units, Quantity.Volume))
if (Units.IsQuantity(units, Quantity.Volume))
{
return Common.Units.ConvertFrom(units, 1.0) * scaleFactor;
}
+14 -57
View File
@@ -551,11 +551,15 @@ namespace TBF.Rig.Sequences
/// Open iPerlCommunicationForm
ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithPurgingTests[0]).RegisterReaders;
#if IPERL
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
#else
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenS640CommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
#endif
var firstRR = ProcessData.RegisterReaders.FirstOrDefault<IRegReader>(x => x != null);
if (firstRR is TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.IperlHead)
{
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
}
else if (firstRR is TBF.Rig.RegisterReaders.S640Stream.S640Stream)
{
Program.MainWnd.Invoke(new CommunicationFormDlgt(OpenS640CommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingProcParams, simultWithPurgingTests, simultWithPurgingTestParams });
}
}
///
@@ -565,10 +569,10 @@ namespace TBF.Rig.Sequences
switch (evt)
{
case Event.Error:
if (simultWithPurgingCount > 0) CloseCommunicationForm();
if (simultWithPurgingCount > 0) CloseCommunicationForm();
goto error;
case Event.UiCmdStop:
if (simultWithPurgingCount > 0) CloseCommunicationForm();
if (simultWithPurgingCount > 0) CloseCommunicationForm();
goto stop;
default:
break;
@@ -929,22 +933,7 @@ namespace TBF.Rig.Sequences
goto select_cycle_or_test;
}
StateMachine.ControlBoard.Devices = outPath;
if ((sensPath != null) && (sensPath.RegisterReaders != null))
{
ProcessData.RegisterReaders = sensPath.RegisterReaders;
foreach (var rr in sensPath.RegisterReaders)
{
if ((rr is TestMethods.iPerlCommunication.iPerlHead.IperlHead) && (BenchInfo != null))
{
(rr as TestMethods.iPerlCommunication.iPerlHead.IperlHead).BenchName = BenchInfo.TestBenchName;
}
}
}
else
{
ProcessData.RegisterReaders = null;
}
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
///
/// Execute one test (single repetition of a repeated test)
@@ -1064,22 +1053,7 @@ namespace TBF.Rig.Sequences
StateMachine.LoadTestParams(dfrrdData.Test);
StateMachine.ControlBoard.Devices = outPath;
if ((sensPath != null) && (sensPath.RegisterReaders != null))
{
ProcessData.RegisterReaders = sensPath.RegisterReaders;
foreach (var rr in sensPath.RegisterReaders)
{
if ((rr is TestMethods.iPerlCommunication.iPerlHead.IperlHead) && (BenchInfo != null))
{
(rr as TestMethods.iPerlCommunication.iPerlHead.IperlHead).BenchName = BenchInfo.TestBenchName;
}
}
}
else
{
ProcessData.RegisterReaders = null;
}
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
e = testMethod.Execute2ndPass(dfrrdData.Test, dfrrdData.RepetNr, dfrrdData.IntermediateData);
@@ -1141,7 +1115,6 @@ namespace TBF.Rig.Sequences
if (testMethod != null && testMethod.CanTest(StateMachine.Procedure.MetersKind))
{
StateMachine.LoadTestParams(test);
string errMsg;
if (!testMethod.CheckDeviceCaps(test, outPath, out errMsg))
{
@@ -1149,22 +1122,7 @@ namespace TBF.Rig.Sequences
goto select_cycle_or_test;
}
StateMachine.ControlBoard.Devices = outPath;
if ((sensPath != null) && (sensPath.RegisterReaders != null))
{
ProcessData.RegisterReaders = sensPath.RegisterReaders;
foreach (var rr in sensPath.RegisterReaders)
{
if ((rr is TestMethods.iPerlCommunication.iPerlHead.IperlHead) && (BenchInfo != null))
{
(rr as TestMethods.iPerlCommunication.iPerlHead.IperlHead).BenchName = BenchInfo.TestBenchName;
}
}
}
else
{
ProcessData.RegisterReaders = null;
}
ProcessData.RegisterReaders = (sensPath != null && sensPath.RegisterReaders != null) ? sensPath.RegisterReaders : null;
Event rsltTransBefore = Event.Done;
Event rsltTransAfter = Event.Done;
@@ -1224,7 +1182,6 @@ namespace TBF.Rig.Sequences
}
///------------------------------------------------------------------------------------------------------------
/// Cycle or test completed
goto select_cycle_or_test;
+1 -1
View File
@@ -270,7 +270,7 @@ namespace TBF.Rig.Sequences
///
foreach (var cmpnt in StateMachine.Components)
{
if (cmpnt is IHasClearSessionData) (cmpnt as IHasClearSessionData).ClearSessionData();
if (cmpnt is ISessionDataMngmnt) (cmpnt as ISessionDataMngmnt).StartSession();
}
IsQ2PreCorrectionCalculated = false;
+1 -7
View File
@@ -25,13 +25,7 @@ namespace TBF.Rig.Sequences
}
/// <summary>
///
/// </summary>
/// <param name="batchNr"></param>
/// <param name="testName"></param>
/// <param name="repetition"></param>
/// <returns>Graph ID</returns>
public int StartGraph(int batchNr, string testName, int repetition)
{
try
@@ -164,17 +164,6 @@ namespace TBF.Rig.TestMethods.DiverterTest
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
@@ -476,6 +465,11 @@ namespace TBF.Rig.TestMethods.DiverterTest
{
LogProcessDataHeader(processDataLogger, string.Format("Measurement {0}", divRepetNr));
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
int remainingRepetitions = testParams.DivRepetitions - divRepetNr + 1;
int pulsesNow = (remainingPulses + remainingRepetitions - 1) / remainingRepetitions;
remainingPulses -= pulsesNow;
+4 -12
View File
@@ -163,18 +163,6 @@ namespace TBF.Rig.TestMethods.Endurance
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Starting_the_pump);
//------------------------------------------------
@@ -298,6 +286,10 @@ namespace TBF.Rig.TestMethods.Endurance
IList<IOperation> measureOperations = new List<IOperation>();
foreach (var camera in cameras) measureOperations.Add(camera.MeasurementOp());
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
//------------------------------------------------
@@ -149,17 +149,6 @@ namespace TBF.Rig.TestMethods.FlyingStart
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
///
/// Optionally display prompt to emerge temperature meters to appropriate baths for heat meters test
///
@@ -384,6 +373,11 @@ namespace TBF.Rig.TestMethods.FlyingStart
IList<IOperation> cameraMeasurementOps = new List<IOperation>();
foreach (var camera in cameras) cameraMeasurementOps.Add(camera.MeasurementOp());
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_in_progress);
@@ -187,17 +187,6 @@ namespace TBF.Rig.TestMethods.FlyingStartFirstRepetWithMassColl
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
bool drainTheTank = false;
if (repetitionNr == 1)
@@ -531,6 +520,10 @@ namespace TBF.Rig.TestMethods.FlyingStartFirstRepetWithMassColl
log.WarnFormat("Start mass = {0}kg", StartMass);
}
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
if (heatMetersPath == null) LogProcessDataHeader(processDataLogger, "Measurement");
else LogProcessDataHeaderHeatMeters(processDataLogger, "Measurement");
@@ -202,17 +202,6 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollComparative
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
@@ -627,6 +616,12 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollComparative
}
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
if (heatMetersPath == null) LogProcessDataHeader(processDataLogger, "Measurement");
else LogProcessDataHeaderHeatMeters(processDataLogger, "Measurement");
@@ -181,17 +181,6 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
@@ -530,6 +519,12 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged
log.WarnFormat("Start mass = {0}kg", StartMass);
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
if (heatMetersPath == null) LogProcessDataHeader(processDataLogger, "Measurement");
else LogProcessDataHeaderHeatMeters(processDataLogger, "Measurement");
@@ -417,27 +417,6 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
temperature_set:
///
/// Prepare datastream read operations
///
IList<IOperation> readDatastreamOps = new List<IOperation>();
if (sensPath != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
{
var rrWithTestName = rr as GenericDevices.IHasTestName;
if (rrWithTestName != null)
{
rrWithTestName.TestName = test.Name;
rrWithTestName.TestRepeats = test.Repeats;
rrWithTestName.RepetitionNr = repetitionNr;
}
var datastreamRR = rr as GenericDevices.IRegReaderDatastream;
if (datastreamRR != null) readDatastreamOps.Add(datastreamRR.ReadDatastreamOp());
}
}
///
/// Prepare cameras, ROI-s and measurementOperations
///
@@ -474,6 +453,21 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
cameraMeasurementOps.Add(camera.MeasurementOp());
}
/// Prepare datastream read operations
IList<IOperation> readDatastreamOps = new List<IOperation>();
if (sensPath != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
{
var datastreamRR = rr as GenericDevices.IRegReaderDatastream;
if (datastreamRR != null)
{
datastreamRR.TestIsGoingToStartSoon(test, repetitionNr);
readDatastreamOps.Add(datastreamRR.ReadDatastreamOp());
}
}
}
if (drainTheTank)
{
@@ -1097,13 +1091,7 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
State.Create(string.Format("{0}({1}) : Reading watermeters", test.Method, test.Name))
@@ -186,18 +186,6 @@ namespace TBF.Rig.TestMethods.FlyingStartTankCollection
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
///
/// Optionally drain the water tank
///
@@ -377,6 +365,11 @@ namespace TBF.Rig.TestMethods.FlyingStartTankCollection
IList<IOperation> cameraMeasurementOps = new List<IOperation>();
foreach (var camera in cameras) cameraMeasurementOps.Add(camera.MeasurementOp());
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
LogProcessDataTestInfo(processDataLogger, test.Procedure.Name, test.Name);
LogProcessDataHeader(processDataLogger, "Measurement");
@@ -1,9 +1,7 @@
///
/// Copyright (c) 2015-2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Common;
using Config.Entities;
@@ -8,7 +8,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
{
public class TestMethodFactory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
public string ClassName { get { return GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public IComponent DummyComponent() { return new TestMethod(); }
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Copyright (c) 2015-2021 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);
@@ -80,6 +84,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
retVal.Add("---");
retVal.Add(iPerlCommunicationForm.Reset2HzCorrectionStr);
retVal.Add(iPerlCommunicationForm.Write2HzCorrectionStr);
retVal.Add(iPerlCommunicationForm.DewaReworkRLStr);
retVal.Add(iPerlCommunicationForm.DewaReworkLRStr);
retVal.Add(string.Format("{0} if enabled", iPerlCommunicationForm.ReadConfigurationStr));
retVal.Add(string.Format("{0} 80", iPerlCommunicationForm.SetTestModeStr));
retVal.Add("iPerl_check prevWorkStep direction q2factors");
@@ -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;
///
@@ -55,10 +60,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
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()))
{
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
@@ -129,6 +130,22 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
return new List<Event> { Event.Done };
}
else if (testParams.Activity.ToLower().Contains(StrictQ2ErrorCheckStr))
{
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);
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(Q2correctionCheckCmd))
{
TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 0, 30, 0, 30, 0, 0 });
@@ -159,7 +176,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication
int maxTestIndex = (ProcessData.BenchInfo is DataContainer.iPerlBenchInfo.Component)
? (ProcessData.BenchInfo as DataContainer.iPerlBenchInfo.Component).MaxTestIndex
: int.MaxValue;
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(test.Name, 0);
if (tstRslt != null)
@@ -267,77 +284,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("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.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);
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 +620,151 @@ 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 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.
@@ -0,0 +1,23 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
namespace TBF.Rig.TestMethods.iPerlCommunication
{
public class iPerlDataWrite
{
public MessageID MessageID;
public int Offset;
public byte[] Data;
public string Description;
public iPerlDataWrite(MessageID mesageID, int offset, byte[] data, string description)
{
MessageID = mesageID;
Offset = offset;
Data = data;
Description = description;
}
}
}
@@ -99,9 +99,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
Count /// Number of flow states
}
public enum OptoState
public enum DataStreamState
{
Read,
Flush,
Flush = 0,
ProcessAndSave,
}
}
@@ -11,25 +11,26 @@ using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
using TBF.Rig.Output;
using TBF.Rig.Sequences;
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
{
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class IperlHead : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
public class IperlHead : ComponentBase, IDevice, IRegReaderDatastream, ISessionDataMngmnt, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(IperlHead));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
#if TURA_SPECIAL
public const int MaxOptoDataCount = 250000;
public const int OptoDataBufferSize = 250000;
#else
public const int MaxOptoDataCount = 40000;
public const int OptoDataBufferSize = 40000; /// Opto data count is not limitted by the buffer size
#endif
public const string OptoDataDirectory = "C:\\TBF\\ProcessData";
public const int StartOptoDataCount = MaxOptoDataCount / 2;
public const int EndOptoDataCount = MaxOptoDataCount - StartOptoDataCount;
public const int StartOptoDataCount = OptoDataBufferSize / 2;
public const int EndOptoDataCount = OptoDataBufferSize - StartOptoDataCount;
public const int StartEndFilterSamplesCount2 = 20; /// StartEndFilterSamplesCount = 2 * StartEndFilterSamplesCount2 + 1
public const int FeatureVectorSize = 9;
@@ -212,7 +213,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <returns>Calculated Q2 correction factor</returns>
public double CalculateQ2CorrectionFactor(Results.Entities.MeterTestRslt q2adjResult, double calibTarget, double nominalFlow, int currentFactor = 0)
{
double nominalTestFlowLph = Common.Units.ConvertTo(Common.Unit.lph, nominalFlow);
double nominalTestFlowLph = Units.ConvertTo(Common.Unit.lph, nominalFlow);
double volumeRefShiftedToTarget = q2adjResult.VolumeRef * (1.0 + calibTarget / 100.0);
double q2adjErrorShiftedToTarget = Formulas.ErrorFromVolumes(q2adjResult.VolumeMeter, volumeRefShiftedToTarget);
@@ -273,18 +274,57 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
}
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string TestName { set { testName = value; } }
public int TestRepeats { set { testRepeats = value; } }
public int RepetitionNr { set { repetitionNr = value; } }
/// <summary>
/// Store/update values to be used as a part of the opto-data log file name.
/// Stop data stream processing and saving, if it is enabled.
/// </summary>
/// <param name="test">Currently executed test</param>
/// <param name="repetitionNr">Currently executed repetition number</param>
public void TestIsGoingToStartSoon(Test test, int repetitionNr)
{
/// Store/update values to be used as a part of the opto-data log file name
testName = test.Name;
testRepeats = test.Repeats;
this.repetitionNr = repetitionNr;
if (IsDataStreamProcessing())
{
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;
string cycleStartTime = StateMachine.CycleStartTimeStamp.ToString("HH_mm_ss");
///
string relativeDirectory = Path.Combine(StateMachine.CycleStartTimeStamp.ToString("yy"),
StateMachine.CycleStartTimeStamp.ToString("MM"),
StateMachine.CycleStartTimeStamp.ToString("dd"));
string directory = Path.Combine(OptoDataDirectory, relativeDirectory);
string fileName = string.Format("{0}_{1}_{2}_{3}.txt", pcbNr, wmPosition, "WM", cycleStartTime);
if (SaveOptoDataToFile(directory, fileName))
{
extraDataPath = Path.Combine(relativeDirectory, fileName);
}
}
}
///
string testName;
int testRepeats;
int repetitionNr;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string BenchName;
///
/// Indices to determine centers of start / end samples
@@ -341,8 +381,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
OptoTelegramRaw[] optoData;
int optoDataCount;
string optoDataLogFileName;
int optoDataCount; /// Real opto deta count, can be larger then optoData.Length
///
OptoTelegramRaw toBeFlushed;
@@ -363,26 +402,25 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
public override void Initialize()
{
ClearSessionData();
flowDirectionDetection = new FlowDirectionDetection();
/// Allocate memory for opto-data from iPerl
optoData = new OptoTelegramRaw[MaxOptoDataCount];
for (int i = 0; i < MaxOptoDataCount; i++)
optoData = new OptoTelegramRaw[OptoDataBufferSize];
for (int i = 0; i < OptoDataBufferSize; i++)
{
optoData[i] = new OptoTelegramRaw();
}
toBeFlushed = new OptoTelegramRaw();
optoSerialPortParsingEnabled = false;
dataStreamState = DataStreamState.Flush;
synchronized = false;
synchronized2 = false;
partOfTelegram = string.Empty;
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;
@@ -399,7 +437,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearSessionData()
public void StartSession()
{
ResultCode = 0;
@@ -418,12 +456,20 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
Q2ErrWOCorrection = 0;
Q2CorrRL = 0;
Q2CorrLR = 0;
/// Clear the data buffer
optoDataCount = 0;
dataStreamState = DataStreamState.Flush;
currentFlowDir = InitFlowDir;
if (flowDirectionDetection != null) flowDirectionDetection.ClearFifo(); /// Clear FIFO for flow direction detection
}
public void SaveMark(object mark)
{
/// TODO
}
public void EndSession()
{
StopDataStreamProcessing();
}
@@ -462,7 +508,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
{
try
{
ReadOptoData(optoSerialPortParsingEnabled ? OptoState.Read : OptoState.Flush);
ReadOptoData(dataStreamState);
}
catch (Exception e)
{
@@ -520,137 +566,107 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
timestampSec = 0;
timestampSec0 = 0;
/// Clear the feature vector
for (int i = 0; i < FeatureVectorSize; i++) x[i] = 0;
extraDataPath = null;
ReadPulses();
/// Clear the feature vector
for (int i = 0; i < FeatureVectorSize; i++)
{
x[i] = 0;
}
}
public void TestCompleted()
{
/// TODO: Implement
}
int timeFromStart; /// [s] Time from test start to determine when the test start sample should be taken
/// <summary>Start this operation</summary>
/// <summary>
/// Start this operation
/// </summary>
public void Start()
{
Clear();
/// Reset opto data, etc.
timeFromStart = 0;
optoDataCount = 0;
currentTelegramIx = -1;
startSampleAcquired = false;
TestStartTelegramIx = 0;
endTelegramIdx1 = 0;
endTelegramIdx2 = 0;
endTelegramIdx3 = 0;
TestEndTelegramIx = 0;
///
/// Determine opto data file name: PCB_AA_BB_HH_MI_SS..txt
///
Results.Output.SensusTestInfo[] localTestInfos = Sequences.ProcessData.CompleteTestInfos;
if (localTestInfos == null && StateMachine.Procedure != null)
lock (this)
{
localTestInfos = Results.Output.SensusTestInfo.CreateFromProcedure(StateMachine.Procedure);
Clear();
ReadPulses();
StartDataStreamProcessing();
}
///
string fullTestName = Results.Utils.GetTestName(testName, testRepeats, repetitionNr);
string qBezeichnungOpto = null; /// To be determined from TestInfo-s (if there are any)
if (localTestInfos != null)
{
foreach (var ti in localTestInfos)
{
if ((ti.PruefungsNrOpto != 0) && (ti.TestName == fullTestName))
{
qBezeichnungOpto = string.IsNullOrEmpty(ti.QBezeichnungOpto) ? ti.PruefungsNrOpto.ToString("D2") : ti.QBezeichnungOpto;
break;
}
}
}
if (qBezeichnungOpto == null)
{
qBezeichnungOpto = fullTestName; /// No appropriate TestInfo found => set default opto data file name
}
///
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;
string cycleStartTime = StateMachine.CycleStartTimeStamp.ToString("HH_mm_ss");
///
optoDataLogFileName = string.Format("{0}_{1}_{2}_{3}.txt", pcbNr, wmPosition, qBezeichnungOpto, cycleStartTime);
extraDataPath = null;
StartParsingOptoSerialPort();
}
/// <summary>Run this operation</summary>
/// <summary>
/// Run this operation
/// </summary>
/// <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;
}
/// <summary>Stop this operation</summary>
/// <summary>
/// Stop this operation
/// </summary>
public void Stop()
{
int startIx = BufferIdx(TestStartTelegramIx);
int endIx = BufferIdx(TestEndTelegramIx);
log.WarnFormat("IperlHeadd.Stop() startIx={0} endIx={1} optoData.Len={2} filename={3}", startIx, endIx, optoData.Length, !string.IsNullOrEmpty(optoDataLogFileName) ? optoDataLogFileName : "<null>");
if ((startIx > 0) && (startIx < StartOptoDataCount) && (optoData[startIx].Flags == OptoTelegramFlags.OK))
{
optoData[startIx].Flags = OptoTelegramFlags.OK_TestStart;
OptoTelegramRaw.TestStartTimestampDec = optoData[startIx].TimestampDec();
}
if ((endIx > 0) && (optoData[endIx].Flags == OptoTelegramFlags.OK))
{
optoData[endIx].Flags = OptoTelegramFlags.OK_TestEnd;
}
log.DebugFormat("Flow filtering start: {0:HH:mm:ss.fff}", DateTime.Now);
StopParsingOptoSerialPort();
if (optoDataCount <= MaxOptoDataCount)
{
FIRFilterFlow(optoData, 0, optoDataCount - 1);
}
else
{
FIRFilterFlow(optoData, 0, StartOptoDataCount - 1);
FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1);
}
log.DebugFormat("Flow filtering end, feature vector calculation start: {0:HH:mm:ss.fff}", DateTime.Now);
Common.Utils.CalculateFeatureVector(optoData, optoDataCount, startIx, endIx, ref x);
int startIx;
int endIx;
log.DebugFormat("Feature vector calculation end, save opto-file start: {0:HH:mm:ss.fff}", DateTime.Now);
lock (this)
{
StopDataStreamProcessing();
AddTestStartEndMarksToData(out startIx, out endIx);
}
extraDataPath = SaveOptoData();
DataStreamPostProcessing();
log.DebugFormat("Save opto-file end: {0:HH:mm:ss.fff}", DateTime.Now);
// TODO: Enable when calculations completed
//
// float[] offsetV, kOhmsR, kOhmsC, dutFlow, refFlow, flowRatio, magField, emfV;
// x = Common.StatisticalMetrics.Calculate(optoData, optoDataCount, startIx, endIx, true,
// out offsetV, out kOhmsR, out kOhmsC, out dutFlow,
// out refFlow, out flowRatio, out magField, out emfV);
//
// log.DebugFormat("Feature vector calculation end, save opto-file start: {0:HH:mm:ss.fff}", DateTime.Now);
string relativeDirectory = Path.Combine(StateMachine.CycleStartTimeStamp.ToString("yy"),
StateMachine.CycleStartTimeStamp.ToString("MM"),
StateMachine.CycleStartTimeStamp.ToString("dd"));
string directory = Path.Combine(OptoDataDirectory, relativeDirectory);
string fileName = DetermineExtraDataFileName();
if (!string.IsNullOrEmpty(fileName))
{
if (SaveOptoDataToFile(directory, fileName))
{
extraDataPath = Path.Combine(relativeDirectory, fileName);
}
}
log.WarnFormat("IperlHeadd.Stop() startIx={0} endIx={1} optoData.Len={2} filename={3}", startIx, endIx, optoData.Length, !string.IsNullOrEmpty(fileName) ? fileName : "<null>");
if (TestStartTelegramIx == 0 || optoDataCount < 100)
{
@@ -662,73 +678,163 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
}
}
/// <summary>
/// Save opto data to a file.
/// </summary>
string SaveOptoData()
{
if (!string.IsNullOrEmpty(optoDataLogFileName))
void AddTestStartEndMarksToData(out int startIx, out int endIx)
{
startIx = BufferIdx(TestStartTelegramIx);
if ((startIx > 0) && (startIx < StartOptoDataCount) && (optoData[startIx].Flags == OptoTelegramFlags.OK))
{
string relativeDirectory = Path.Combine(StateMachine.CycleStartTimeStamp.ToString("yy"),
StateMachine.CycleStartTimeStamp.ToString("MM"),
StateMachine.CycleStartTimeStamp.ToString("dd"));
string fullFileName = Path.Combine(OptoDataDirectory, relativeDirectory, optoDataLogFileName);
log.WarnFormat("Saving {0} opto data to {1}", Name, fullFileName);
try
optoData[startIx].Flags = OptoTelegramFlags.OK_TestStart;
OptoTelegramRaw.TestStartTimestampDec = optoData[startIx].TimestampDec();
}
else
{
for (int ix = 0; ix < StartOptoDataCount; ix++)
{
Directory.CreateDirectory(Path.Combine(OptoDataDirectory, relativeDirectory));
double scalFact = ScalingFactor();
using (TextWriter optoLogFile = new StreamWriter(fullFileName))
if (optoData[ix].Flags == OptoTelegramFlags.OK)
{
if (optoDataCount <= MaxOptoDataCount)
{
/// Telegrams are stored continuously, save them.
optoLogFile.WriteLine(optoData[0].ToString(scalFact, null));
for (int i = 1; i < optoDataCount; i++)
{
optoLogFile.WriteLine(optoData[i].ToString(scalFact, optoData[i - 1]));
}
}
else /// if (optoDataCount > MaxOptoDataCount)
{
/// Buffer overflow
/// First part of the buffer is saved as is
optoLogFile.WriteLine(optoData[0].ToString(scalFact, null));
for (int i = 1; i < StartOptoDataCount; i++)
{
optoLogFile.WriteLine(optoData[i].ToString(scalFact, optoData[i - 1]));
}
optoLogFile.WriteLine(" ...");
/// Second part of the buffer is an overflowed circular buffer
optoLogFile.WriteLine(optoData[BufferIdx(optoDataCount)].ToString(scalFact, null));
for (int i = optoDataCount - EndOptoDataCount + 1; i < optoDataCount; i++)
{
optoLogFile.WriteLine(optoData[BufferIdx(i)].ToString(scalFact, optoData[BufferIdx(i - 1)]));
}
}
log.WarnFormat("{0} opto data successfully saved: {1} lines", Name, optoDataCount);
optoLogFile.Close();
/// This is the first correct opto-telegram received
OptoTelegramRaw.TestStartTimestampDec = optoData[ix].TimestampDec();
break;
}
return Path.Combine(relativeDirectory, optoDataLogFileName);
}
catch (Exception exc)
{
File.Delete(fullFileName);
log.ErrorFormat(string.Format("Error writing into file {0}", fullFileName));
log.ErrorFormat(string.Format("Exception message: {0}", exc.Message));
}
}
return null;
endIx = BufferIdx(TestEndTelegramIx);
if ((endIx > 0) && (optoData[endIx].Flags == OptoTelegramFlags.OK))
{
optoData[endIx].Flags = OptoTelegramFlags.OK_TestEnd;
}
}
/// <summary>
/// Data stream post processing:
/// Flow from a reference flowmeter is FIR filtered
/// </summary>
void DataStreamPostProcessing()
{
if (optoDataCount <= OptoDataBufferSize)
{
FIRFilterFlow(optoData, 0, optoDataCount - 1);
}
else
{
FIRFilterFlow(optoData, 0, StartOptoDataCount - 1);
FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1);
}
}
/// <summary>
/// Determine opto data file name: PCB_AA_BB_HH_MI_SS..txt
/// </summary>
/// <param name="testName">Test name</param>
/// <param name="testRepeats">Test repeats count (>= 1)</param>
/// <param name="repetitionNr">Repetition number (1 .. testRepeats)</param>
/// <returns></returns>
string DetermineExtraDataFileName()
{
///
/// Select or create appropriate test infos
///
Results.Output.SensusTestInfo[] testInfos = Sequences.ProcessData.CompleteTestInfos;
///
if ((ProcessData.OracleDB != null && ProcessData.OracleDB.DesigMode == Output.DB.SensusOracle.DesigMode.Based_on_procedure) ||
(testInfos == null && StateMachine.Procedure != null))
{
testInfos = Results.Output.SensusTestInfo.CreateFromProcedure(StateMachine.Procedure);
}
///
/// Select or create appropriate 'qBezeichnung'
///
string fullTestName = Results.Utils.GetTestName(testName, testRepeats, repetitionNr);
string qBezeichnungOpto = null; /// To be determined from TestInfo-s (if there are any)
foreach (var ti in testInfos)
{
if ((ti.PruefungsNrOpto != 0) && (ti.TestName == fullTestName))
{
qBezeichnungOpto = string.IsNullOrEmpty(ti.QBezeichnungOpto) ? ti.PruefungsNrOpto.ToString("D2") : ti.QBezeichnungOpto;
break;
}
}
if (qBezeichnungOpto == null)
{
qBezeichnungOpto = fullTestName; /// No appropriate TestInfo found => set default opto data file name
}
///
/// Get other required pieces of information
///
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;
string cycleStartTime = StateMachine.CycleStartTimeStamp.ToString("HH_mm_ss");
///
/// Return the file name
///
return string.Format("{0}_{1}_{2}_{3}.txt", pcbNr, wmPosition, qBezeichnungOpto, cycleStartTime);
}
/// <summary>
/// Save opto data to a file.
/// </summary>
bool SaveOptoDataToFile(string directory, string fileName)
{
string fullFileName = Path.Combine(directory, fileName);
log.WarnFormat("Saving {0} opto data to {1}", Name, fullFileName);
try
{
Directory.CreateDirectory(directory);
double scalFact = ScalingFactor();
using (TextWriter optoLogFile = new StreamWriter(fullFileName))
{
if (optoDataCount <= OptoDataBufferSize)
{
/// Telegrams are stored continuously, save them.
optoLogFile.WriteLine(optoData[0].ToString(scalFact, null));
for (int i = 1; i < optoDataCount; i++)
{
optoLogFile.WriteLine(optoData[i].ToString(scalFact, optoData[i - 1]));
}
}
else /// if (optoDataCount > MaxOptoDataCount)
{
/// Buffer overflow
/// First part of the buffer is saved as is
optoLogFile.WriteLine(optoData[0].ToString(scalFact, null));
for (int i = 1; i < StartOptoDataCount; i++)
{
optoLogFile.WriteLine(optoData[i].ToString(scalFact, optoData[i - 1]));
}
optoLogFile.WriteLine(" ...");
/// Second part of the buffer is an overflowed circular buffer
optoLogFile.WriteLine(optoData[BufferIdx(optoDataCount)].ToString(scalFact, null));
for (int i = optoDataCount - EndOptoDataCount + 1; i < optoDataCount; i++)
{
optoLogFile.WriteLine(optoData[BufferIdx(i)].ToString(scalFact, optoData[BufferIdx(i - 1)]));
}
}
log.WarnFormat("{0} opto data successfully saved: {1} lines", Name, optoDataCount);
optoLogFile.Close();
}
return true;
}
catch (Exception exc)
{
File.Delete(fullFileName);
log.ErrorFormat(string.Format("Error writing into file {0}", fullFileName));
log.ErrorFormat(string.Format("Exception message: {0}", exc.Message));
return false;
}
}
void ReadPulses()
@@ -742,18 +848,46 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
}
bool optoSerialPortParsingEnabled;
DataStreamState dataStreamState;
/// <summary> Flush internal buffers and start parsing the opto serial port data </summary>
void StartParsingOptoSerialPort()
/// <summary>
/// Reset counters / indices / time and start processing and saving datastream data
/// </summary>
public void StartDataStreamProcessing()
{
optoSerialPortParsingEnabled = true;
/// Reset opto-data, etc.
optoDataCount = 0;
timeFromStart = 0;
currentTelegramIx = -1;
startSampleAcquired = false;
TestStartTelegramIx = 0;
endTelegramIdx1 = 0;
endTelegramIdx2 = 0;
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;
}
/// <summary> Stop parsig the opto serial port data </summary>
void StopParsingOptoSerialPort()
/// <summary>
/// Returns true when processing and saving datastream data is in progress
/// </summary>
bool IsDataStreamProcessing()
{
optoSerialPortParsingEnabled = false;
return dataStreamState == DataStreamState.ProcessAndSave;
}
/// <summary>
/// Stop processing and saving datastream data
/// </summary>
void StopDataStreamProcessing()
{
dataStreamState = DataStreamState.Flush;
}
///
@@ -764,110 +898,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(OptoState optoState)
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 == OptoState.Read)
{
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("."));
}
}
}
@@ -1113,13 +1248,13 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <returns>Index to the buffer</returns>
public static int BufferIdx(int index)
{
if (index < IperlHead.MaxOptoDataCount)
if (index < IperlHead.OptoDataBufferSize)
{
return index;
}
else
{
return IperlHead.StartOptoDataCount + (index - IperlHead.MaxOptoDataCount) % IperlHead.EndOptoDataCount;
return IperlHead.StartOptoDataCount + (index - IperlHead.OptoDataBufferSize) % IperlHead.EndOptoDataCount;
}
}
@@ -1,15 +1,10 @@
///
/// Copyright (c) 2015-2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Xml.Serialization;
using Common;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
{
+1 -2
View File
@@ -586,14 +586,13 @@
<Compile Include="Rig\GenericDevices\IEvaporation.cs" />
<Compile Include="Rig\GenericDevices\IEventTrigger.cs" />
<Compile Include="Rig\GenericDevices\IHasCalendarEvents.cs" />
<Compile Include="Rig\GenericDevices\IHasClearSessionData.cs" />
<Compile Include="Rig\GenericDevices\IParallelOutput.cs" />
<Compile Include="Rig\GenericDevices\IReceivesDataFromRadio.cs" />
<Compile Include="Rig\GenericDevices\IRegReaderPulses.cs" />
<Compile Include="Rig\GenericDevices\IResultsProcessor.cs" />
<Compile Include="Rig\GenericDevices\ISessionDataMngmnt.cs" />
<Compile Include="Rig\GenericDevices\IStartInfoReader.cs" />
<Compile Include="Rig\GenericDevices\IHart.cs" />
<Compile Include="Rig\GenericDevices\IHasTestName.cs" />
<Compile Include="Rig\GenericDevices\ICameraDisplay.cs" />
<Compile Include="Rig\GenericDevices\IDataEntryForCamera.cs" />
<Compile Include="Rig\GenericDevices\IErrorFlags.cs" />