diff --git a/Results/Entities/MeterTestRslt.cs b/Results/Entities/MeterTestRslt.cs index 1896ac4f4..e73c0509f 100644 --- a/Results/Entities/MeterTestRslt.cs +++ b/Results/Entities/MeterTestRslt.cs @@ -31,6 +31,9 @@ namespace Results.Entities public virtual double KorrErrQ { get; set; } /// [%] not mapped to results DB, saved to Oracle DB public virtual bool TestDone { get; set; } /// true = test was completed public virtual bool Passed { get; set; } /// true = test passed, water meter is OK +#if IPERL + public virtual string ExtraDataPath { get; set; } /// Relative path to a file with opto-data/raw-data +#endif #if ORACLE_DB public virtual double LastError { get; set; } /// [%] Previous test error at this Q in case Pruefindex > 1 #endif @@ -146,6 +149,9 @@ namespace Results.Entities KorrErrQ = src.KorrErrQ; TestDone = src.TestDone; Passed = src.Passed; +#if IPERL + ExtraDataPath = src.ExtraDataPath; +#endif #if ORACLE_DB LastError = src.LastError; #endif @@ -177,6 +183,9 @@ namespace Results.Entities writer.Write(KorrErrQ); writer.Write(TestDone); writer.Write(Passed); +#if IPERL + writer.Write((ExtraDataPath != null) ? ExtraDataPath : string.Empty); +#endif #if ORACLE_DB writer.Write(LastError); #endif @@ -205,6 +214,9 @@ namespace Results.Entities KorrErrQ = reader.ReadDouble(); TestDone = reader.ReadBoolean(); Passed = reader.ReadBoolean(); +#if IPERL + ExtraDataPath = reader.ReadString(); +#endif #if ORACLE_DB LastError = reader.ReadDouble(); #endif diff --git a/Results/Mappings/MeterTestRsltMap.cs b/Results/Mappings/MeterTestRsltMap.cs index 0f8518ce7..987123217 100644 --- a/Results/Mappings/MeterTestRsltMap.cs +++ b/Results/Mappings/MeterTestRsltMap.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2015-2018 Sensus Slovensko a.s. +/// Copyright (c) 2015-2021 Sensus Slovensko a.s. /// using FluentNHibernate.Mapping; using Results.Entities; @@ -26,6 +26,9 @@ namespace Results.Mappings Map(x => x.Error); Map(x => x.TestDone); Map(x => x.Passed); +#if IPERL + Map(x => x.ExtraDataPath); +#endif #if ORACLE_DB Map(x => x.LastError); #endif diff --git a/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs b/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs index 8a48e3d5c..f681995e0 100644 --- a/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs +++ b/TBF/Rig/TestMethods/FlyingStart/FlyingStartSeq.cs @@ -625,6 +625,7 @@ namespace TBF.Rig.TestMethods.FlyingStart } #if IPERL meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; + meterRslt.ExtraDataPath = iPerl.ExtraDataPath; #endif iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result iPerl.LastTestResult = meterRslt; /// Save this test result diff --git a/TBF/Rig/TestMethods/FlyingStartMassCollProlonged/FlyingStartMassCollProlongedSeq.cs b/TBF/Rig/TestMethods/FlyingStartMassCollProlonged/FlyingStartMassCollProlongedSeq.cs index f35356295..7c2529186 100644 --- a/TBF/Rig/TestMethods/FlyingStartMassCollProlonged/FlyingStartMassCollProlongedSeq.cs +++ b/TBF/Rig/TestMethods/FlyingStartMassCollProlonged/FlyingStartMassCollProlongedSeq.cs @@ -888,6 +888,7 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollProlonged } #if IPERL meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; + meterRslt.ExtraDataPath = iPerl.ExtraDataPath; #endif iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result iPerl.LastTestResult = meterRslt; /// Save this test result diff --git a/TBF/Rig/TestMethods/FlyingStartMassCollection/FlyingStartMassCollectionSeq.cs b/TBF/Rig/TestMethods/FlyingStartMassCollection/FlyingStartMassCollectionSeq.cs index ebef395b0..d7d67bdd8 100644 --- a/TBF/Rig/TestMethods/FlyingStartMassCollection/FlyingStartMassCollectionSeq.cs +++ b/TBF/Rig/TestMethods/FlyingStartMassCollection/FlyingStartMassCollectionSeq.cs @@ -927,9 +927,10 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection meterRslt.WaterMeter.ResultCode |= iPerl.ResultCode; } #if IPERL - meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; + meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor; + meterRslt.ExtraDataPath = iPerl.ExtraDataPath; #endif - iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result + iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result iPerl.LastTestResult = meterRslt; /// Save this test result } diff --git a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs index f09800ce1..76ff21aa4 100644 --- a/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs +++ b/TBF/Rig/TestMethods/iPerlCommunication/iPerlHead/IperlHead.cs @@ -26,6 +26,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead #else public const int MaxOptoDataCount = 40000; #endif + public const string OptoDataDirectory = "C:\\TBF\\ProcessData"; public const int StartOptoDataCount = MaxOptoDataCount / 2; public const int EndOptoDataCount = MaxOptoDataCount - StartOptoDataCount; public const int StartEndFilterSamplesCount2 = 20; /// StartEndFilterSamplesCount = 2 * StartEndFilterSamplesCount2 + 1 @@ -65,31 +66,19 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { get { - if (ConfigStruct != null) return configStruct.GetPcbNrString(); + if (ConfigStruct != null) return ConfigStruct.GetPcbNrString(); else return string.Empty; } set { } } - public bool Disabled - { - get { return disabled; } - set { disabled = value; } - } - bool disabled; + public bool Disabled; + public bool CommFailed; + public int ResultCode; - public bool CommFailed - { - get { return commFailed; } - set { commFailed = value; } - } - bool commFailed; - public int ResultCode - { - get { return resultCode; } - } - int resultCode; + string extraDataPath; + public string ExtraDataPath { get { return extraDataPath; } } /// @@ -103,29 +92,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public bool PositiveCounting; - /// ConfigStruct of the water meter obtained or updated by iPerlCommunication - public ConfigStruct ConfigStruct - { - get { return configStruct; } - set { configStruct = value; } - } - ConfigStruct configStruct; - - /// CalibrationStruct of the water meter obtained or updated by iPerlCommunication - public CalibrationStruct CalibrationStruct - { - get { return calibrationStruct; } - set { calibrationStruct = value; } - } - CalibrationStruct calibrationStruct; - - /// CalibrationStruct of the water meter obtained or updated by iPerlCommunication - public CalibrationStructV4 CalibrationStructV4 - { - get { return calibrationStructV4; } - set { calibrationStructV4 = value; } - } - CalibrationStructV4 calibrationStructV4; + public ConfigStruct ConfigStruct; /// ConfigStruct of WM obtained or updated by iPerlCommunication + public CalibrationStruct CalibrationStruct; /// CalibrationStruct of WM obtained or updated by iPerlCommunication + public CalibrationStructV4 CalibrationStructV4; /// CalibrationStruct of WM obtained or updated by iPerlCommunication public ushort OrigCalibFactor; public ushort CalibFactor @@ -171,16 +140,16 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// public int WMPulses { get { return wmPulses; } } public int WMRefPulses { get { return wmRefPulses; } } - public double WMVolume { get { return wmVolume; } } public double BeginWMState { get { return beginWMState; } } public double EndWMState { get { return endWMState; } } - public double WMTestTime { get { return wmTestTime; } } + public double WMVolume { get { return wmVolume; } } + public double WMTestTime { get { return wmTestTime; } } - double beginWMState; + int wmPulses; + int wmRefPulses; + double beginWMState; double endWMState; double wmVolume; - int wmPulses; - int wmRefPulses; double wmTestTime; @@ -312,31 +281,6 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// Name set by the test, to be used as a part of the opto-data log file name public string BenchName; - /// - /// Volume of water from the opto telegram - /// - private Int64 lastVolumeRaw; /// Last read raw volume - private double volumeLtr; - private double volumeLtr0; - - /// Test start volume for metrology in liters - public double VolumeLtrStart { get { return VolumeFromSamples(optoData, optoDataCount, TestStartTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } } - /// Test end volume for metrology in liters - public double VolumeLtrEnd { get { return VolumeFromSamples(optoData, optoDataCount, TestEndTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } } - - /// - /// Timestamp from the opto telegram - /// - private Int64 lastTimestamp; - private double timestampSec; - private double timestampSec0; - - public bool NoSamples { get { return (TimestampSecEnd - TimestampSecStart) < float.Epsilon; } } - - /// Test start volume for metrology in seconds - public double TimestampSecStart { get { return TimeFromSamples(optoData, optoDataCount, TestStartTelegramIx, StartEndFilterSamplesCount2); } } - /// Test end time for metrology in seconds - public double TimestampSecEnd { get { return TimeFromSamples(optoData, optoDataCount, TestEndTelegramIx, StartEndFilterSamplesCount2); } } /// /// Indices to determine centers of start / end samples @@ -350,6 +294,47 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead int currentTelegramIx; bool startSampleAcquired; + /// + /// Timestamp from the opto telegram + /// + private Int64 lastTimestamp; + private double timestampSec; + private double timestampSec0; + + /// Test start volume for metrology in seconds + public double TimestampSecStart + { + get { return TimeFromSamples(optoData, optoDataCount, TestStartTelegramIx, StartEndFilterSamplesCount2); } + } + /// Test end time for metrology in seconds + public double TimestampSecEnd + { + get { return TimeFromSamples(optoData, optoDataCount, TestEndTelegramIx, StartEndFilterSamplesCount2); } + } + /// + public bool NoSamples + { + get { return TimestampSecStart == 0 || TimestampSecEnd == 0 || (TimestampSecEnd - TimestampSecStart) < float.Epsilon; } + } + + /// + /// Volume of water from the opto telegram + /// + private Int64 lastVolumeRaw; /// Last read raw volume + private double volumeLtr; + private double volumeLtr0; + + /// Test start volume for metrology in liters + public double VolumeLtrStart + { + get { return NoSamples ? 0 : VolumeFromSamples(optoData, optoDataCount, TestStartTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } + } + /// Test end volume for metrology in liters + public double VolumeLtrEnd + { + get { return NoSamples ? 0 : VolumeFromSamples(optoData, optoDataCount, TestEndTelegramIx, ScalingFactor(), StartEndFilterSamplesCount2); } + } + OptoTelegramRaw[] optoData; int optoDataCount; @@ -369,22 +354,23 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead : base(cfg) { iperlHeadCfg = cfg as IperlHeadCfg; - log.Warn(this.ToString()); } public override void Initialize() { ClearSessionData(); - optoSerialPortParsingEnabled = false; - flowDirectionDetection = new FlowDirectionDetection(); /// Allocate memory for opto-data from iPerl optoData = new OptoTelegramRaw[MaxOptoDataCount]; - for (int i = 0; i < MaxOptoDataCount; i++) optoData[i] = new OptoTelegramRaw(); + for (int i = 0; i < MaxOptoDataCount; i++) + { + optoData[i] = new OptoTelegramRaw(); + } toBeFlushed = new OptoTelegramRaw(); + optoSerialPortParsingEnabled = false; synchronized = false; synchronized2 = false; partOfTelegram = string.Empty; @@ -396,12 +382,12 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead optoSerialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One); optoSerialPort.Handshake = Handshake.None; optoSerialPort.Open(); - log.FatalFormat("{0} - Device successfully initialized", Name); + log.FatalFormat("{0} initialized: {1}", Name, this); } else { optoSerialPort = null; - log.FatalFormat("{0} - Device simulated", Name); + log.FatalFormat("{0} simulated: {1}", Name, this); } } @@ -410,14 +396,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// public void ClearSessionData() { - resultCode = 0; + ResultCode = 0; - disabled = false; - commFailed = false; + Disabled = false; + CommFailed = false; - configStruct = null; - calibrationStruct = null; - calibrationStructV4 = null; + ConfigStruct = null; + CalibrationStruct = null; + CalibrationStructV4 = null; LastTestResult = null; LastTestResult2 = null; @@ -521,7 +507,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead /// public void Clear() { - resultCode = 0; + ResultCode = 0; volumeLtr = 0; volumeLtr0 = 0; @@ -550,34 +536,42 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead endTelegramIdx3 = 0; TestEndTelegramIx = 0; - /// File name is: PCB_AA_BB_HH_MI_SS..txt - string wmPosition = Name.Substring(5); /// WMPosition is extracted from a component name in form 'iPerl#' - if (wmPosition.Length == 1) wmPosition = "0" + wmPosition; - if (StateMachine.Procedure != null && Sequences.ProcessData.CompleteTestInfos == null) - { - Sequences.ProcessData.CompleteTestInfos = Results.Output.SensusTestInfo.CreateFromProcedure(StateMachine.Procedure); - } - - Results.Output.SensusTestInfo[] testInfos = Sequences.ProcessData.CompleteTestInfos; - optoDataLogFileName = null; /// - if (testInfos != null) + /// 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) { - string fullTestName = Results.Utils.GetTestName(testName, testRepeats, repetitionNr); - foreach (var ti in testInfos) + localTestInfos = Results.Output.SensusTestInfo.CreateFromProcedure(StateMachine.Procedure); + } + /// + 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)) { - optoDataLogFileName = string.Format("{0}_{1}_{2}_{3}.txt", - (ConfigStruct != null) ? ConfigStruct.GetPcbNrString() : "UnknownPcbNr", - wmPosition, - string.IsNullOrEmpty(ti.QBezeichnungOpto) ? ti.PruefungsNrOpto.ToString("D2") : ti.QBezeichnungOpto, - StateMachine.CycleStartTimeStamp.ToString("HH_mm_ss")); + 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(); } @@ -636,35 +630,36 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead OptoTelegramRaw.FIRFilterFlow(optoData, 0, StartOptoDataCount - 1); OptoTelegramRaw.FIRFilterFlow(optoData, (optoDataCount - EndOptoDataCount), optoDataCount - 1); } - SaveOptoData(); + + extraDataPath = SaveOptoData(); if (TestStartTelegramIx == 0 || optoDataCount < 100) { - resultCode |= (int)Results.Entities.ResultCode.MissingOptoData; + ResultCode |= (int)Results.Entities.ResultCode.MissingOptoData; } else if (VolumeLtrEnd == VolumeLtrStart) { - resultCode |= (int)Results.Entities.ResultCode.OptoDataWithZeroFlow; + ResultCode |= (int)Results.Entities.ResultCode.OptoDataWithZeroFlow; } } /// /// Save opto data to a file. /// - void SaveOptoData() + string SaveOptoData() { if (!string.IsNullOrEmpty(optoDataLogFileName)) { - string directory = Path.Combine("C:\\TBF\\ProcessData", StateMachine.CycleStartTimeStamp.ToString("yy"), - StateMachine.CycleStartTimeStamp.ToString("MM"), - StateMachine.CycleStartTimeStamp.ToString("dd")); - string fullFileName = Path.Combine(directory, optoDataLogFileName); + 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 { - Directory.CreateDirectory(directory); + Directory.CreateDirectory(Path.Combine(OptoDataDirectory, relativeDirectory)); double scalFact = ScalingFactor(); @@ -704,6 +699,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead optoLogFile.Close(); } + + return Path.Combine(relativeDirectory, optoDataLogFileName); } catch (Exception exc) { @@ -712,7 +709,9 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead log.ErrorFormat(string.Format("Exception message: {0}", exc.Message)); } } - } + + return null; + } void ReadPulses() { @@ -913,8 +912,8 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead { default: case VolumeUnits.m3: return Common.Units.ConvertFrom(Common.Unit.m3, 1.0); /// liter - case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// liter - case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// liter + case VolumeUnits.UK_gallon: return Common.Units.ConvertFrom(Common.Unit.UKgal, 1.0); /// liter + case VolumeUnits.US_gallon: return Common.Units.ConvertFrom(Common.Unit.USgal, 1.0); /// liter } } @@ -1019,29 +1018,29 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public void WriteBinary(BinaryWriter writer) { - writer.Write(disabled); - writer.Write(commFailed); - writer.Write(resultCode); + writer.Write(Disabled); + writer.Write(CommFailed); + writer.Write(ResultCode); writer.Write(PositiveCounting); - if (configStruct != null) + if (ConfigStruct != null) { writer.Write(true); - configStruct.WriteBinary(writer); + ConfigStruct.WriteBinary(writer); } else writer.Write(false); - if (calibrationStruct != null) + if (CalibrationStruct != null) { writer.Write(true); - calibrationStruct.WriteBinary(writer); + CalibrationStruct.WriteBinary(writer); } else writer.Write(false); - if (calibrationStructV4 != null) + if (CalibrationStructV4 != null) { writer.Write(true); - calibrationStructV4.WriteBinary(writer); + CalibrationStructV4.WriteBinary(writer); } else writer.Write(false); @@ -1071,14 +1070,14 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead public void ReadBinary(BinaryReader reader) { - disabled = reader.ReadBoolean(); - commFailed = reader.ReadBoolean(); - resultCode = reader.ReadInt32(); + Disabled = reader.ReadBoolean(); + CommFailed = reader.ReadBoolean(); + ResultCode = reader.ReadInt32(); PositiveCounting = reader.ReadBoolean(); - if (reader.ReadBoolean()) (configStruct = new ConfigStruct()).ReadBinary(reader); - if (reader.ReadBoolean()) (calibrationStruct = new CalibrationStruct()).ReadBinary(reader); - if (reader.ReadBoolean()) (calibrationStructV4 = new CalibrationStructV4()).ReadBinary(reader); + if (reader.ReadBoolean()) (ConfigStruct = new ConfigStruct()).ReadBinary(reader); + if (reader.ReadBoolean()) (CalibrationStruct = new CalibrationStruct()).ReadBinary(reader); + if (reader.ReadBoolean()) (CalibrationStructV4 = new CalibrationStructV4()).ReadBinary(reader); OrigCalibFactor = reader.ReadUInt16(); OrigCalibFactorLNA = reader.ReadUInt16();