tbf/TBF/Rig/TestMethods/FlyingStartMassCollectionMassFlow/FlyingStartMassCollectionMassFlowSeq.cs
Michal Buzik 2b3e0dfa32 Remove SharedComponents + UNI shows Serial Nr
Remove `SharedComponents` references and legacy `LiveLogCache` logic:

- Eliminate unused `SharedComponents` references across the solution to streamline dependencies.
- Comment out `LiveLogCache` interactions in multiple modules, transitioning to alternative or undefined logging mechanisms.
- Add optional `regReadersOptional` parameters to `ShowCycleBeginFormOp` methods for improved flexibility.
- Introduce `ITestMethodSmart` interface to support smart reader functionality.
- Add new `LogCacheAppender` configuration to `log4netConfig.xml` for diagnostic use.
- Update project files to remove outdated references and include newly introduced files.
2026-02-23 15:55:24 +01:00

1401 lines
73 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Common;
using Config.Entities;
using FluentNHibernate.Data;
using log4net;
///
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.Serialization;
using TBF.Boxes;
using TBF.Resources;
using TBF.Rig;
using TBF.Rig.GenericDevices;
using TBF.Rig.RegisterReaders.KPackE.Radio;
using TBF.Rig.RegisterReaders.PulsesFromUniCB;
using TBF.UiBridge;
namespace TBF.Rig.TestMethods.FlyingStartMassCollectionMassFlow
{
public class FlyingStartMassCollectionMassFlowSeq : Sequences.SequenceBase
{
private static readonly ILog log = LogManager.GetLogger(typeof(FlyingStartMassCollectionMassFlowSeq));
/// <summary>
/// Check capabilities of devces in the output path required for this test method
/// </summary>
/// <param name="devices">Devices</param>
/// <returns>true when capabilities of devices are OK</returns>
public static bool CheckDeviceCaps(Config.Entities.Test test, OutputPath devices, out string message)
{
if (!(StateMachine.ControlBoardMain is ControlBoard.Uni.UniCB))
{
/// Control board does not support this method
message = string.Format("{0}: {1}", test.Name, Strings.Test_bench_does_not_suport_selected_test_method);
return false;
}
if (!(devices.Scale is IScale))
{
/// Scale is missing
message = string.Format("{0}: {1}", test.Name, Strings.Missing_a_scale);
return false;
}
if (test.Volume > devices.Scale.Capacity * Constants.TankFullFactor)
{
/// Scale capacity is not sufficient
message = string.Format("{0}: {1}", test.Name, Strings.Test_volume_exceeds_the_scale_capacity);
return false;
}
if (!(devices.Diverter is IDiverter))
{
/// Scale is missing
message = string.Format("{0}: {1}", test.Name, Strings.Missing_a_diverter);
return false;
}
if (!(devices.FlowMeter is IFlowMeter))
{
/// Flow meter is missing
message = string.Format("{0}: {1}", test.Name, Strings.Missing_a_flow_meter);
return false;
}
if (!(devices.RegValve is GenericDevices.IRegValve))
{
/// Regulation valve is missing
message = string.Format("{0}: {1}", test.Name, Strings.Missing_a_regulation_valve);
return false;
}
message = string.Empty;
return true;
}
/// <summary>
/// Flying start mass collection method sequence
/// </summary>
/// <param name="test">Test entity</param>
/// <returns>
/// Event.Done . . . . . . . OK
/// Event.UiCmdStop . . . . Stopped by the user using the on-screen button STOP
/// Event.OpArgumentError . Target flow is out of range
/// Event.Error . . . . . . Unspecified error
/// </returns>
public IList<Event> Execute(Test test, int repetitionNr, bool isLastRepetition,
bool isDelayedStart, DebugMode debugLevel)
{
if (debugLevel == Common.DebugMode.Simulate)
{
return Simulate1(test, repetitionNr, isLastRepetition);
}
else if (debugLevel == Common.DebugMode.Inherit)
{
return Simulate2(test, repetitionNr, isLastRepetition);
}
ControlBoard.Uni.UniCB cBrd = StateMachine.ControlBoardMain as ControlBoard.Uni.UniCB;
IScale scale = cBrd.Devices.Scale as IScale;
if ((outPath.FlowMeter is IFlowMeterSingle) &&
(outPath.FlowMeter as IFlowMeterSingle).GetRange(test.TempLimLo, test.TempLimHi) == -1)
{
Bridge.OnError(this, Strings.Flow_meter_temperature_range_does_not_fit_this_test_conditions);
return new List<Event> { Event.ConfigurationError }; /// or Event.UiCmdStop ???
}
IList<Event> e; /// Events from currently running operations
Event retVal = Event.Done;
int tMass1 = 0;
int tMass2 = 0;
checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state
processDataLoggingOp = new TBF.Rig.Operations.ProcessDataLoggingOp(processDataLogger, this, false);
/// Since CheckDeviceCaps() passed cBrd is ControlBoard.Uni.UniCB
int[] filters = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };
if (sensPath != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
{
IRegReaderPulses rrPls = rr as IRegReaderPulses;
if (rrPls != null && rrPls.Position >= 1 && rrPls.Position <= 8)
{
filters[rrPls.Position - 1] = rrPls.Filter;
}
}
}
cBrd.SetFiltersPidShortPulses(filters, outPath.PidCoef, test.ShortPulses);
IList<IOperation> readTempPressOps = new List<IOperation>();
if (benchPath.TempMtrUp != null) readTempPressOps.Add(benchPath.TempMtrUp.ReadTempOp(ref TempUp));
if (benchPath.TempMtrDown != null) readTempPressOps.Add(benchPath.TempMtrDown.ReadTempOp(ref TempDown));
if (outPath.TempMtrDiv != null) readTempPressOps.Add(outPath.TempMtrDiv.ReadTempOp(ref TempDiv));
if (benchPath.PressMtrUp != null) readTempPressOps.Add(benchPath.PressMtrUp.ReadPressureOp(ref PressUp));
if (benchPath.PressMtrDown != null) readTempPressOps.Add(benchPath.PressMtrDown.ReadPressureOp(ref PressDown));
if (benchPath.PressMtrDelta != null) readTempPressOps.Add(benchPath.PressMtrDelta.ReadPressureOp(ref PressDelta));
if (benchPath.ElectricMtrUp != null) readTempPressOps.Add(benchPath.ElectricMtrUp.ReadPressureOp(ref ElectricUp));
if (benchPath.ElectricMtrDown != null) readTempPressOps.Add(benchPath.ElectricMtrDown.ReadPressureOp(ref ElectricDown));
if (benchPath.ElectricMtrDelta != null) readTempPressOps.Add(benchPath.ElectricMtrDelta.ReadPressureOp(ref ElectricDelta));
if (heatMetersPath != null) readTempPressOps.Add(heatMetersPath.TMeterRefWarm1.ReadTempOp(ref TempRefHi1));
if (heatMetersPath != null) readTempPressOps.Add(heatMetersPath.TMeterRefWarm2.ReadTempOp(ref TempRefHi2));
if (heatMetersPath != null) readTempPressOps.Add(heatMetersPath.TMeterRefCold1.ReadTempOp(ref TempRefLo1));
if (heatMetersPath != null) readTempPressOps.Add(heatMetersPath.TMeterRefCold2.ReadTempOp(ref TempRefLo2));
int totalPulses = Convert.ToInt32(test.Volume / outPath.FlowMeter.LtrPerPulse);
///============================================================================================
/// Read pressure and temperature once before calling Bridge.OnTestSelected(...)
State.Create(string.Format("{0}({1}) : Measuring process data", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (e.Contains(Event.Busy));
/// Start the test, initialize test results
Bridge.OnTestSelected(this, new TestSelectedEventArgs(test, repetitionNr, inPath, benchPath, outPath, sensPath, heatMetersPath));
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
//------------------------------------------------
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
//------------------------------------------------
double estEndMass = scale.Mass + test.Volume;
bool drainTheTank =
test.DoDraining || (estEndMass >= scale.Capacity * Constants.TankFullFactor);
///
if (drainTheTank)
{
#if BERLIN || SENTEC
switch (DrainTheTank(scale, readTempPressOps))
{
case Event.Error: { retVal = Event.Error; goto stopTest; }
case Event.UiCmdStop: { retVal = Event.UiCmdStop; goto stopTest; }
}
drainTheTank = false;
#else
State.Create(string.Format("{0}({1}) : Open the drain valve", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(cBrd.SetValvesOp(scale.DrainValve, null))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (e.Contains(Event.ValvesBusy));
#endif
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Starting_the_pump);
//------------------------------------------------
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
int flowSetTime0 = StateMachine.Time;
if (inPath.Pump is GenericDevices.IPumpFM)
{
(inPath.Pump as GenericDevices.IPumpFM).TurnOn(test.PumpPower);
}
///
State.Create(string.Format("{0}({1}) : Starting pump {2}", test.Method, test.Name, (inPath.Pump != null) ? inPath.Pump.Name : "?"))
.AddOperation(checkUiOp)
// .AddOperation(new Operations.SetAllRegulValvesOp(inPath.RegulValves, inPath.RegulValvesPct, 60))
.AddOperations(readTempPressOps)
.AddOperation(inPath.Pump != null ? cBrd.SetValvesOp(inPath.Pump, null) : null)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
}
while (e.Contains(Event.ValvesBusy) /* || !e.Contains(Event.AllPositionsReached)*/);
if (test.TimePump2StartV > 0)
{
State.Create(string.Format("{0}({1}) : Waiting after the pump started", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(new Operations.TimerOp(test.TimePump2StartV))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (!e.Contains(Event.TimerExpired));
}
if (benchPath.StopBFValve != null)
{
State.Create(string.Format("{0}({1}) : Opening the stop backflow valve", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(cBrd.SetValvesOp(benchPath.StopBFValve, null))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
}
while (!e.Contains(Event.ValvesSet));
}
if (test.TimeBeforeFlow > 0)
{
State.Create(string.Format("{0}({1}) : Waiting before flow setting process starts", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(new Operations.TimerOp(test.TimeBeforeFlow))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (!e.Contains(Event.TimerExpired));
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Setting_the_flow);
//------------------------------------------------
State.Create(string.Format("{0}({1}) : Setting the flow", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(cBrd.SetFlowOp(test.QfromM3ph(), test.QtoM3ph(), RefFlow, FlowSettingTimeoutSec))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
if (e.Contains(Event.OpArgumentError)) { retVal = Event.OpArgumentError; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.RegulValveTimeOut))
{
Bridge.OnError(this, Strings.Flow_adjustment_failed);
retVal = Event.RecoverableError;
goto stopTest;
}
if (e.Contains(Event.Next)) goto flow_set;
}
while (!e.Contains(Event.FlowReached));
flow_set:
int flowSetTime = StateMachine.Time - flowSetTime0;
double currentFlow = RefFlow.Val;
if (!string.IsNullOrEmpty(test.TempControl) && benchPath.TempMtrUp != null && benchPath.TempMtrDown != null)
{
//---------------------------------------------------
Bridge.OnActivity(this, Strings.Setting_temperature);
//---------------------------------------------------
State.Create(string.Format("{0}({1}) : Wait until the water temperature is within limits", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.Next)) goto temperature_set;
if ((test.TempLimLo <= TempUp.Val) && (TempUp.Val <= test.TempLimHi) &&
(test.TempLimLo <= TempDown.Val) && (TempDown.Val <= test.TempLimHi))
{
goto temperature_set;
}
}
while (true);
}
temperature_set:
///
/// Prepare cameras, ROI-s and measurementOperations
///
/// Find successfully detected ROI-s
IList<GenericDevices.IRegReaderLiveCamera> rois = new List<GenericDevices.IRegReaderLiveCamera>();
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IRegReaderLiveCamera cameraRoI = rr as GenericDevices.IRegReaderLiveCamera;
if ((cameraRoI != null) && cameraRoI.Detected)
{
rois.Add(cameraRoI);
}
}
/// Find cameras
IList<GenericDevices.ICamera> cameras = new List<GenericDevices.ICamera>();
foreach (var roi in rois)
{
if (roi.Camera != null && !cameras.Contains(roi.Camera))
{
cameras.Add(roi.Camera);
roi.Camera.ClearRoiParams();
}
}
/// Register ROI-parameters to cameras
foreach (var roi in rois) roi.RegisterRoiToCamera();
/// Prepare measurementOperations
IList<IOperation> cameraMeasurementOps = new List<IOperation>();
foreach (var camera in cameras)
{
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)
{
//------------------------------------------------
Bridge.OnActivity(this, Strings.Closing_the_tank);
//------------------------------------------------
///
/// Make sure tank draining completed
///
switch (DrainTheTank(scale, readTempPressOps))
{
case Event.Error: { retVal = Event.Error; goto stopTest; }
case Event.UiCmdStop: { retVal = Event.UiCmdStop; goto stopTest; }
}
drainTheTank = false;
}
else
{
/// Close the drain valve anyway
State.Create(string.Format("{0}({1}) : Close the drain valve", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(cBrd.SetValvesOp(null, scale.DrainValve))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (e.Contains(Event.ValvesBusy));
}
//----------------------------------------------------
Bridge.OnActivity(this, Strings.Measuring_the_weight);
//----------------------------------------------------
LogProcessDataTestInfo(processDataLogger, test.Procedure.Name, test.Name);
if (heatMetersPath == null) LogProcessDataHeader(processDataLogger, "Start mass");
else LogProcessDataHeaderHeatMeters(processDataLogger, "Start mass");
State.Create(string.Format("{0}({1}) : Measuring the start mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperations(cameraMeasurementOps)
.AddOperation(scale.ReadStableMassOp(ref StartMass, test.TimeFlow2Mass, test.MassMethod, test.MassRepeats, test.MassSpread))
.AddOperation(processDataLoggingOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.ScaleTimeout))
{
Bridge.OnError(this, Strings.Mass_measurement_timeout);
retVal = Event.RecoverableError;
goto stopTest;
}
}
while (!e.Contains(Event.ScaleDone) && !e.Contains(Event.Next));
tMass1 = StateMachine.Time;
log.WarnFormat("Start mass = {0}kg", StartMass);
if (heatMetersPath == null)
LogProcessDataHeader(processDataLogger, "Measurement");
else
LogProcessDataHeaderHeatMeters(processDataLogger, "Measurement");
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_in_progress);
//------------------------------------------------
/// Measurement loop preparation
int estimtdEndTime = StateMachine.Time + Convert.ToInt32(test.TestTime);
int remainingTime;
StartNewStatistics(outPath.FlowMeter, BatchRslts.Batch.BatchNr, test, repetitionNr, 0);
DiverterStart.Start(BatchRslts.Batch.BatchNr, test.Name, repetitionNr);
DiverterEnd.Start(BatchRslts.Batch.BatchNr, test.Name, repetitionNr);
/// Measurement loop
State.Create(string.Format("{0}({1}) : FlyingStartStopTestWithDivOp is running", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperations(readDatastreamOps)
.AddOperations(cameraMeasurementOps)
.AddOperation(cBrd.FlyingStartStopTestOp(test, test.QfromM3ph(), test.QtoM3ph(), totalPulses, true, isDelayedStart, false, 0, true, DiverterStart, DiverterEnd))
.AddOperation(processDataLoggingOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.OpArgumentError)) { retVal = Event.OpArgumentError; goto stopTest; }
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
/// Show remaining time
if ((remainingTime = Math.Max(estimtdEndTime - StateMachine.Time, 0)) > 60)
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Test_in_progress, remainingTime / 60, "min", remainingTime % 60, Strings.sec));
else
Bridge.OnActivity(this, string.Format("{0} ... {1} s", Strings.Test_in_progress, remainingTime));
/// Update statistics
RefFrequency.Val = cBrd.RefFrequency;
RefFlow.Val = outPath.FlowMeter.ReadFlow();
UpdateAllStatistics();
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Test));
}
while (!e.Contains(Event.TestCompleted) && !e.Contains(Event.Next)); /// 'Next' button is enabled in Debug version only
/// Measurement loop end
StopRecordingStatistics();
///
/// (Berlin:) Water is stopped immediately after the test and before the 2nd mass measurement in case:
/// - no 'transition sequence after test' is used
/// - this is the last (or the only) test repetition or test is a part of an 'outer loop'
///
#if !CEVAK_200
if (isLastRepetition && transitionAfter == null)
#endif
{
if (inPath.Pump is GenericDevices.IPumpFM) (inPath.Pump as GenericDevices.IPumpFM).TurnOff();
State.Create("SequenceBase : Transition : TestEnd - Default action")
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(cBrd.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(e)) { retVal = Event.UiCmdStop; goto stopTest; }
}
while (!e.Contains(Event.ValvesSet));
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Measuring_the_weight);
//------------------------------------------------
if (heatMetersPath == null) LogProcessDataHeader(processDataLogger, "End mass");
else LogProcessDataHeaderHeatMeters(processDataLogger, "End mass");
State.Create(string.Format("{0}({1}) : Measuring the end mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(scale.ReadStableMassOp(ref EndMass, test.TimeStop2Mass, test.MassMethod, test.MassRepeats, test.MassSpread))
.AddOperation(new Operations.TimerOp(StableMassMsrmntTimeoutSec))
.AddOperation(processDataLoggingOp)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
if (e.Contains(Event.ScaleTimeout))
{
Bridge.OnError(this, Strings.Mass_measurement_timeout);
retVal = Event.RecoverableError;
goto stopTest;
}
}
while (!e.Contains(Event.ScaleDone) && !e.Contains(Event.Next));
///
tMass2 = StateMachine.Time;
log.WarnFormat("End mass = {0}kg", EndMass);
TestEndTime = DateTime.Now;
if (test.DoDrainingAfter)
{
State.Create(string.Format("{0}({1}) : Open the drain valve", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(cBrd.SetValvesOp(scale.DrainValve, null))
.AddOperations(readTempPressOps)
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
}
while (e.Contains(Event.ValvesBusy));
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_completed);
//------------------------------------------------
///
/// Populate TestResult data entity with data
///
Results.Entities.TestRslt tstRslt = BatchRslts.GetTestRslt(testName, test.Part);
bool stopCycle = false;
if (tstRslt != null)
{
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
//===========================================
LiveLogDiag.Log1("================= Kontext a vstupne data ==================");
/*/// Raw data
UpdateTempPressDensAmb(tstRslt);
tstRslt.MethodClass = TbfComponents.FindComponent(test.Method).ClassName;
tstRslt.StartTime = TestStartTime;
tstRslt.EndTime = TestEndTime;
tstRslt.FlowSetTime = flowSetTime;
tstRslt.TestTime = cBrd.TestTime; /// [s] measurement time
tstRslt.PulsesMaster = Convert.ToDouble(cBrd.RefPulses); /// Pulses of the master flow meter (test total)
tstRslt.MassStartRaw = StartMass.Val;
tstRslt.MassEndRaw = EndMass.Val;
tstRslt.TimeBtwnMassMsrmnts = tMass2 - tMass1;
tstRslt.ConstMasterRaw = outPath.FlowMeter.LtrPerPulse;
tstRslt.VolumeMaster = tstRslt.ConstMasterRaw * tstRslt.PulsesMaster; /// [l] volume from the master flow meter
double flowMID = 3.6 * tstRslt.VolumeMaster / tstRslt.TestTime; /// [m3/h] flow before correction from the master flow meter
/// Corrected data
tstRslt.MassStart = MeasurementCorrection.CorrectedValue(tstRslt.MassStartRaw, scale.Corrections);
tstRslt.MassEnd = MeasurementCorrection.CorrectedValue(tstRslt.MassEndRaw, scale.Corrections);
tstRslt.MassOfEvapWater = tstRslt.TimeBtwnMassMsrmnts * outPath.Scale.EvaporationRate(tstRslt.TempDivMean);
double mass = tstRslt.MassEnd - tstRslt.MassStart + tstRslt.MassOfEvapWater;
tstRslt.ConstMasterCorr = outPath.FlowMeter.LtrPerPulseCorrected(flowMID, tstRslt.TempDownMean);*/
string LP = "[INPUT]";
Action<string, object> LV = (n, v) =>
LiveLogDiag.Log1(string.Format("{0} {1}={2}", LP, n, v ?? "null"));
LV = (n, v) => LiveLogDiag.Log1(string.Format("{0} {1}={2}", LP, n, v ?? "null"));
// ---------- Kontext a vstupy pred spracovaním ----------
LV("tstRslt.TempDivMean (pre-call)", tstRslt.TempDivMean);
LV("tstRslt.TempDownMean (pre-call)", tstRslt.TempDownMean);
LV("tstRslt.DensityLine (pre-call)", tstRslt.DensityLine);
LV("scale.Corrections != null", (scale != null && scale.Corrections != null));
LV("outPath != null", (outPath != null));
LV("outPath.FlowMeter != null", (outPath != null && outPath.FlowMeter != null));
LV("outPath.Scale != null", (outPath != null && outPath.Scale != null));
// ---------- Raw data ----------
UpdateTempPressDensAmb(tstRslt);
LV("UpdateTempPressDensAmb(tstRslt) done", true);
tstRslt.MethodClass = TbfComponents.FindComponent(test.Method).ClassName;
LV("tstRslt.MethodClass", tstRslt.MethodClass);
tstRslt.StartTime = TestStartTime;
LV("tstRslt.StartTime", tstRslt.StartTime);
tstRslt.EndTime = TestEndTime;
LV("tstRslt.EndTime", tstRslt.EndTime);
tstRslt.FlowSetTime = flowSetTime;
LV("tstRslt.FlowSetTime", tstRslt.FlowSetTime);
tstRslt.TestTime = cBrd.TestTime; // [s]
LV("tstRslt.TestTime", tstRslt.TestTime);
LV("cBrd.TestTime", cBrd.TestTime);
tstRslt.PulsesMaster = Convert.ToDouble(cBrd.RefPulses);
LV("tstRslt.PulsesMaster", tstRslt.PulsesMaster);
LV("cBrd.RefPulses", cBrd.RefPulses);
tstRslt.MassStartRaw = StartMass.Val;
LV("tstRslt.MassStartRaw", tstRslt.MassStartRaw);
LV("StartMass.Val", StartMass.Val);
tstRslt.MassEndRaw = EndMass.Val;
LV("tstRslt.MassEndRaw", tstRslt.MassEndRaw);
LV("EndMass.Val", EndMass.Val);
tstRslt.TimeBtwnMassMsrmnts = tMass2 - tMass1;
LV("tstRslt.TimeBtwnMassMsrmnts", tstRslt.TimeBtwnMassMsrmnts);
LV("tMass1", tMass1);
LV("tMass2", tMass2);
tstRslt.ConstMasterRaw = outPath.FlowMeter.LtrPerPulse;
LV("tstRslt.ConstMasterRaw", tstRslt.ConstMasterRaw);
LV("outPath.FlowMeter.LtrPerPulse", outPath.FlowMeter.LtrPerPulse);
tstRslt.VolumeMaster = tstRslt.ConstMasterRaw * tstRslt.PulsesMaster; // [l]
LV("tstRslt.VolumeMaster", tstRslt.VolumeMaster);
double flowMID = 3.6 * tstRslt.VolumeMaster / tstRslt.TestTime; // [m3/h]
LV("flowMID", flowMID);
// ---------- Corrected data ----------
tstRslt.MassStart = MeasurementCorrection.CorrectedValue(tstRslt.MassStartRaw, scale.Corrections);
LV("tstRslt.MassStart", tstRslt.MassStart);
tstRslt.MassEnd = MeasurementCorrection.CorrectedValue(tstRslt.MassEndRaw, scale.Corrections);
LV("tstRslt.MassEnd", tstRslt.MassEnd);
LV("tstRslt.TempDivMean (before EvaporationRate)", tstRslt.TempDivMean);
tstRslt.MassOfEvapWater = tstRslt.TimeBtwnMassMsrmnts * outPath.Scale.EvaporationRate(tstRslt.TempDivMean);
LV("tstRslt.MassOfEvapWater", tstRslt.MassOfEvapWater);
double mass = tstRslt.MassEnd - tstRslt.MassStart + tstRslt.MassOfEvapWater;
LV("mass", mass);
LV("flowMID (before LtrPerPulseCorrected)", flowMID);
LV("tstRslt.TempDownMean (before LtrPerPulseCorrected)", tstRslt.TempDownMean);
tstRslt.ConstMasterCorr = outPath.FlowMeter.LtrPerPulseCorrected(flowMID, tstRslt.TempDownMean);
LV("tstRslt.ConstMasterCorr", tstRslt.ConstMasterCorr);
// ---------- Súhrn ----------
LiveLogDiag.Log1(
string.Format(
"{0} SUMMARY StartTime={1}, EndTime={2}, FlowSetTime={3}, TestTime={4}, PulsesMaster={5}, " +
"VolumeMaster={6}, flowMID={7}, MassStartRaw={8}, MassEndRaw={9}, " +
"MassStart={10}, MassEnd={11}, MassOfEvapWater={12}, mass={13}, " +
"ConstMasterRaw={14}, ConstMasterCorr={15}, TempDivMean={16}, TempDownMean={17}, TimeBtwnMassMsrmnts={18}",
LP,
tstRslt.StartTime,
tstRslt.EndTime,
tstRslt.FlowSetTime,
tstRslt.TestTime,
tstRslt.PulsesMaster,
tstRslt.VolumeMaster,
flowMID,
tstRslt.MassStartRaw,
tstRslt.MassEndRaw,
tstRslt.MassStart,
tstRslt.MassEnd,
tstRslt.MassOfEvapWater,
mass,
tstRslt.ConstMasterRaw,
tstRslt.ConstMasterCorr,
tstRslt.TempDivMean,
tstRslt.TempDownMean,
tstRslt.TimeBtwnMassMsrmnts
)
);
//===========================================
//===========================================
LiveLogDiag.Log1("================= Prepocty volume a mass ==================");
/*///-----------------------------------------------
/// Main result calculation for volume method
tstRslt.VolumeCTV = 1000 * tstRslt.Batch.Buoyancy * mass / tstRslt.DensityLine;
if ((outPath.Diverter != null) && (tstRslt.TestTime > float.Epsilon))
{
tstRslt.TestTimeCorrection = outPath.Diverter.TestTimeCorrection(flowMID);
tstRslt.VolumeCTV *= tstRslt.TestTime + tstRslt.TestTimeCorrection;
tstRslt.VolumeCTV /= tstRslt.TestTime;
}
tstRslt.Flow = 3.6 * tstRslt.VolumeCTV / tstRslt.TestTime; /// Flow from VolumeCTV and time
tstRslt.ErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.VolumeCTV);
tstRslt.ConstMaster = (tstRslt.PulsesMaster != 0) ? (tstRslt.VolumeCTV / tstRslt.PulsesMaster) : tstRslt.ConstMasterCorr;
/// Master pulses per liter from the measured mass
///-----------------------------------------------
/// Main result calculation for mass method
tstRslt.MassCTV = tstRslt.Batch.Buoyancy * mass;
if ((outPath.Diverter != null) && (tstRslt.TestTime > float.Epsilon))
{
tstRslt.TestTimeCorrection = outPath.Diverter.TestTimeCorrection(flowMID);
tstRslt.MassCTV *= tstRslt.TestTime + tstRslt.TestTimeCorrection;
tstRslt.MassCTV /= tstRslt.TestTime;
}
tstRslt.MassFlow = 3.6 * tstRslt.MassCTV / tstRslt.TestTime; /// Flow from MassCTV and time
tstRslt.MassErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.MassCTV);
tstRslt.MassConstMaster = (tstRslt.PulsesMaster != 0) ? (tstRslt.MassCTV / tstRslt.PulsesMaster) : tstRslt.ConstMasterCorr;
/// Master pulses per liter from the measured mass
///-----------------------------------------------
///*/
LP = "[CALC]";
LV = (n, v) => LiveLogDiag.Log1(string.Format("{0} {1}={2}", LP, n, v ?? "null"));
// ------- vstupy pre výpočty -------
LV("mass", mass);
LV("tstRslt.Batch.Buoyancy", (tstRslt.Batch != null) ? (object)tstRslt.Batch.Buoyancy : "null Batch");
LV("tstRslt.DensityLine", tstRslt.DensityLine);
LV("tstRslt.TestTime", tstRslt.TestTime);
LV("outPath.Diverter != null", (outPath != null && outPath.Diverter != null));
LV("flowMID", flowMID);
LV("tstRslt.VolumeMaster", tstRslt.VolumeMaster);
LV("tstRslt.PulsesMaster", tstRslt.PulsesMaster);
LV("tstRslt.ConstMasterCorr", tstRslt.ConstMasterCorr);
// -----------------------------------------------
// Main result calculation for volume method
tstRslt.VolumeCTV = 1000 * tstRslt.Batch.Buoyancy * mass / tstRslt.DensityLine;
LV("tstRslt.VolumeCTV (base)", tstRslt.VolumeCTV);
if ((outPath.Diverter != null) && (tstRslt.TestTime > float.Epsilon))
{
tstRslt.TestTimeCorrection = outPath.Diverter.TestTimeCorrection(flowMID);
LV("tstRslt.TestTimeCorrection", tstRslt.TestTimeCorrection);
// log iba premenné pred/po
LV("tstRslt.VolumeCTV (before time correction)", tstRslt.VolumeCTV);
LV("tstRslt.TestTime + tstRslt.TestTimeCorrection", tstRslt.TestTime + tstRslt.TestTimeCorrection);
tstRslt.VolumeCTV *= tstRslt.TestTime + tstRslt.TestTimeCorrection;
tstRslt.VolumeCTV /= tstRslt.TestTime;
LV("tstRslt.VolumeCTV (after time correction)", tstRslt.VolumeCTV);
}
else
{
LV("TimeCorrectionApplied", false);
}
tstRslt.Flow = 3.6 * tstRslt.VolumeCTV / tstRslt.TestTime; /// Flow from VolumeCTV and time
LV("tstRslt.Flow", tstRslt.Flow);
tstRslt.ErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.VolumeCTV);
LV("tstRslt.ErrorMaster", tstRslt.ErrorMaster);
tstRslt.ConstMaster = (tstRslt.PulsesMaster != 0) ? (tstRslt.VolumeCTV / tstRslt.PulsesMaster) : tstRslt.ConstMasterCorr;
LV("tstRslt.ConstMaster", tstRslt.ConstMaster);
// -----------------------------------------------
// Main result calculation for mass method
tstRslt.MassCTV = tstRslt.Batch.Buoyancy * mass;
LV("tstRslt.MassCTV (base)", tstRslt.MassCTV);
if ((outPath.Diverter != null) && (tstRslt.TestTime > float.Epsilon))
{
tstRslt.TestTimeCorrection = outPath.Diverter.TestTimeCorrection(flowMID);
LV("tstRslt.TestTimeCorrection", tstRslt.TestTimeCorrection);
LV("tstRslt.MassCTV (before time correction)", tstRslt.MassCTV);
LV("tstRslt.TestTime + tstRslt.TestTimeCorrection", tstRslt.TestTime + tstRslt.TestTimeCorrection);
tstRslt.MassCTV *= tstRslt.TestTime + tstRslt.TestTimeCorrection;
tstRslt.MassCTV /= tstRslt.TestTime;
LV("tstRslt.MassCTV (after time correction)", tstRslt.MassCTV);
}
else
{
LV("TimeCorrectionApplied", false);
}
tstRslt.MassFlow = 3.6 * tstRslt.MassCTV / tstRslt.TestTime; /// Flow from MassCTV and time
LV("tstRslt.MassFlow", tstRslt.MassFlow);
tstRslt.MassErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.MassCTV);
LV("tstRslt.MassErrorMaster", tstRslt.MassErrorMaster);
tstRslt.MassConstMaster = (tstRslt.PulsesMaster != 0) ? (tstRslt.MassCTV / tstRslt.PulsesMaster) : tstRslt.ConstMasterCorr;
LV("tstRslt.MassConstMaster", tstRslt.MassConstMaster);
// ------- súhrn pre rýchly prehľad -------
LiveLogDiag.Log1(
string.Format("{0} SUMMARY VolumeCTV={1}, Flow={2}, ErrorMaster={3}, ConstMaster={4}, MassCTV={5}, MassFlow={6}, MassErrorMaster={7}, MassConstMaster={8}, TestTime={9}, TestTimeCorrection={10}",
LP,
tstRslt.VolumeCTV,
tstRslt.Flow,
tstRslt.ErrorMaster,
tstRslt.ConstMaster,
tstRslt.MassCTV,
tstRslt.MassFlow,
tstRslt.MassErrorMaster,
tstRslt.MassConstMaster,
tstRslt.TestTime,
tstRslt.TestTimeCorrection
));
//===========================================
/// Flow statistics correction
tstRslt.FlowMean = Convert.ToSingle(tstRslt.ConstMaster * RefFlowStat.Average / tstRslt.ConstMasterRaw);
tstRslt.FlowStart = Convert.ToSingle(tstRslt.ConstMaster * RefFlowStat.First / tstRslt.ConstMasterRaw);
tstRslt.FlowEnd = Convert.ToSingle(tstRslt.ConstMaster * RefFlowStat.Last / tstRslt.ConstMasterRaw);
tstRslt.FlowMin = Convert.ToSingle(tstRslt.ConstMaster * RefFlowStat.Min / tstRslt.ConstMasterRaw);
tstRslt.FlowMax = Convert.ToSingle(tstRslt.ConstMaster * RefFlowStat.Max / tstRslt.ConstMasterRaw);
tstRslt.DiverterStart = outPath.Diverter.SwitchTimeStart.Val;
tstRslt.DivStart10 = 0;
tstRslt.DivStart50 = 0;
tstRslt.DivStart90 = 0;
tstRslt.DiverterEnd = outPath.Diverter.SwitchTimeEnd.Val;
tstRslt.DivEnd90 = 0;
tstRslt.DivEnd50 = 0;
tstRslt.DivEnd10 = 0;
log.DebugFormat("Diverter switch time [s]: Start: {0}ms ({1} {2} {3}) End: {4}ms ({5} {6} {7})",
(tstRslt.DiverterStart * 1000).ToString("F0"), tstRslt.DivStart10, tstRslt.DivStart50, tstRslt.DivStart90,
(tstRslt.DiverterEnd * 1000).ToString("F0"), tstRslt.DivEnd90, tstRslt.DivEnd50, tstRslt.DivEnd10);
long infoFlags = 0;
tstRslt.ErrorFlags = (ErrorFlagsComp != null)
? ErrorFlagsComp.GetErrorFlags(tstRslt, true, false, tstRslt.DiverterStart, tstRslt.DiverterEnd, out infoFlags, out stopCycle)
: 0;
tstRslt.InfoFlags = infoFlags;
///
/// Single meters
///
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
{
if (!test.IsPartCompatible(Utils.PartNr(i + 1, BatchRslts.Batch.Compound))) continue;
/// MetersKind.Single meters
Results.Entities.MeterTestRslt meterRslt = BatchRslts.GetMeterTestRslt(testName, i, Common.CompoundMeterId.Single);
GenericDevices.IRegReader regReader = sensPath.RegisterReaders[i];
GenericDevices.IRegReaderDatastream dstrReader = regReader as GenericDevices.IRegReaderDatastream;
TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = regReader as TestMethods.iPerlCommunication.iPerlHead.IperlHead;
GenericDevices.IRegReaderLiveCamera cameraRoi = regReader as GenericDevices.IRegReaderLiveCamera;
if (meterRslt != null && regReader != null)
{
//citanie konfiguracie RR musi prebehnut z entity RR v konkretnej procedure a nie z univerzalnej konfiguracie z komponentu... odtial sa berie uz len ziva hodnota|
meterRslt.RegReaderType = (int)regReader.RegisterReaderType;
ComponentProcedure procParamsEntity = test.Procedure.GetProcedureParamsEntity(regReader.Name);
try
{
if (regReader.RegisterReaderType == RegisterReaderType.Pulses)
{
XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RRProcParams) })[0];
RRProcParams tmp = Serializer.Deserialize(new StringReader(procParamsEntity.Parameters.ToString())) as RRProcParams;
regReader.PulsesPerLtr = tmp.PulsesPerLtr;
regReader.QuantityUnits = tmp.Units;
}
else
{
//MessageBox.Show("Cannot create or initialize a printer", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}
catch (Exception ex)
{
/*log.DebugFormat(
"Error during Procedure parameters deserialization. CmpntName='{0}', Procedure='{1}', Parameters='{2}', Exception: {3}",
dbEntity?.CmpntName,
dbEntity?.Procedure,
dbEntity?.Parameters,
ex
);*/
}
//meterRslt.PulsesMeter = regReader.PulsesPerLtr;
meterRslt.PulsesPerLiter = regReader.PulsesPerLtr;//...MF 11.12.2025 toto chybalo, v .csv bol stlpec naplneny nulami
meterRslt.QuantityUnits = regReader.QuantityUnits;
meterRslt.PulsesMeter = Convert.ToDouble(regReader.WMPulses);
if (dstrReader != null)
{
meterRslt.TimestampStart = dstrReader.TimestampSecStart;
meterRslt.TimestampEnd = !dstrReader.NoSamples ? dstrReader.TimestampSecEnd : (dstrReader.TimestampSecStart + tstRslt.TestTime);
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
meterRslt.VolumeStart = dstrReader.VolumeLtrStart; /// liter
meterRslt.VolumeEnd = dstrReader.VolumeLtrEnd; /// liter
meterRslt.VolumeMeter = Math.Abs(dstrReader.VolumeLtrEnd - dstrReader.VolumeLtrStart);
meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.PulsesMaster = tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
if (iPerl != null)
{
if (iPerl.ResultCode != 0 && (meterRslt.WaterMeter.ResultCode & (int)Results.Entities.ResultCode.OptoErrorCodeMask) == 0)
{
meterRslt.WaterMeter.ResultCode |= iPerl.ResultCode;
}
#if IPERL
meterRslt.WaterMeter.CalibFactor = iPerl.CalibFactor;
meterRslt.ExtraDataPath = iPerl.ExtraDataPath;
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 1) meterRslt.X1 = iPerl.X[0];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 2) meterRslt.X2 = iPerl.X[1];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 3) meterRslt.X3 = iPerl.X[2];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 4) meterRslt.X4 = iPerl.X[3];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 5) meterRslt.X5 = iPerl.X[4];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 6) meterRslt.X6 = iPerl.X[5];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 7) meterRslt.X7 = iPerl.X[6];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 8) meterRslt.X8 = iPerl.X[7];
if (TestMethods.iPerlCommunication.iPerlHead.IperlHead.FeatureVectorSize >= 9) meterRslt.X9 = iPerl.X[8];
#endif
iPerl.LastTestResult2 = iPerl.LastTestResult; /// Save shift previous test result
iPerl.LastTestResult = meterRslt; /// Save this test result
}
log.DebugFormat("Datastream: Tst={0} Tend={1} Tmtr={2} Ttime={3} Vst={4} Vend={5} Vmtr={6} Vref={7}",
meterRslt.TimestampStart,
meterRslt.TimestampEnd,
meterRslt.TestTime,
tstRslt.TestTime,
meterRslt.VolumeStart,
meterRslt.VolumeEnd,
meterRslt.VolumeMeter,
meterRslt.VolumeRef);
}
else if (cameraRoi != null)
{
meterRslt.TimestampStart = cameraRoi.TimestampStart; /// [s]
meterRslt.TimestampEnd = cameraRoi.TimestampEnd; /// [s]
meterRslt.VolumeStart = cameraRoi.VolumeStart; /// [l]
meterRslt.VolumeEnd = cameraRoi.VolumeEnd; /// [l]
meterRslt.VolumeMeter = cameraRoi.VolumeEnd - cameraRoi.VolumeStart; /// [l]
if (meterRslt.VolumeMeter != 0)
{
/// Normal measurement with camera
meterRslt.TestTime = cameraRoi.TimestampEnd - cameraRoi.TimestampStart; /// [s]
meterRslt.VolumeRef = tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
meterRslt.PulsesMaster = tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
}
else
{
/// None or one pulse from the water meter using camera
meterRslt.TestTime = tstRslt.TestTime;
meterRslt.VolumeRef = tstRslt.VolumeCTV;
meterRslt.PulsesMaster = tstRslt.PulsesMaster;
}
log.DebugFormat("Camera: Tst={0} Tend={1} Tmtr={2} Ttime={3} Vst={4} Vend={5} Vmtr={6} Vref={7}",
meterRslt.TimestampStart,
meterRslt.TimestampEnd,
meterRslt.TestTime,
tstRslt.TestTime,
meterRslt.VolumeStart,
meterRslt.VolumeEnd,
meterRslt.VolumeMeter,
meterRslt.VolumeRef);
}
else
{
meterRslt.PulsesMaster = Convert.ToDouble(regReader.WMRefPulses);
meterRslt.VolumeStart = 0;
meterRslt.VolumeEnd = 0;
//===========================================
LiveLogDiag.Log1("================= Referencie ==================");
/*
meterRslt.VolumeMeter = meterRslt.PulsesMeter * regReader.LtrsPerPulse; /// [l] ... tieto dva riadky zavisia na tom, aky typ registerReadera mam, ci je to objemovy alebo hmotnostny (procedure/pulse)
//...MF
meterRslt.MassMeter = meterRslt.PulsesMeter * regReader.KilogramsPerPulse; /// [kg]
if (regReader.WMPulses >= 1)
{
/// Normal measurement
meterRslt.TestTime = cBrd.TestTimeWM(regReader.Position);
meterRslt.VolumeRef = meterRslt.PulsesMaster * tstRslt.ConstMaster; /// [l]
//...MF
meterRslt.MassRef = meterRslt.PulsesMaster * tstRslt.ConstMaster; /// [kg]
}
else
{
/// None or one pulse from the water meter
meterRslt.TestTime = tstRslt.TestTime;
meterRslt.VolumeRef = tstRslt.VolumeCTV; /// [l]
//...MF
meterRslt.MassRef = tstRslt.MassCTV; /// [kg]
}*/
LP = "[CTVCALC]";
LV = (n, v) => LiveLogDiag.Log1(string.Format("{0} {1}={2}", LP, n, v ?? "null"));
// --- Kontext / typ čítača (ak vieš rozlíšiť) ---
var readerType = regReader?.GetType()?.Name ?? "null";
LV("RR ReaderType", readerType);
LV("RR PulsesPerLiter", meterRslt.PulsesPerLiter);
LV("RR QuantityUnits", meterRslt.QuantityUnits);
LV("RR PulsesQuantity", meterRslt.GetQuantityFromUnits());
// --- Vstupy pre meranie metra ---
LV("PulsesMeter", meterRslt.PulsesMeter);
LV("LtrsPerPulse", regReader.LtrsPerPulse); // [l/pulse]
// --- Výpočet hodnôt zo samotného merača ---
meterRslt.VolumeMeter = meterRslt.PulsesMeter * regReader.LtrsPerPulse; // [l]
meterRslt.MassMeter = meterRslt.PulsesMeter * /*regReader.KilogramsPerPulse*/regReader.LtrsPerPulse; // [kg]
LV("VolumeMeter[l]", meterRslt.VolumeMeter);
LV("MassMeter[kg]", meterRslt.MassMeter);
// --- Info pre rozhodovaciu vetvu ---
LV("WMPulses", regReader.WMPulses);
LV("BoardPosition", regReader.Position);
LV("PulsesMaster", meterRslt.PulsesMaster);
LV("ConstMaster[l/p]", tstRslt.ConstMaster);
LV("MassConstMaster[kg/p]", tstRslt.MassConstMaster);
LV("CTV.Volume[l]", tstRslt.VolumeCTV);
LV("CTV.Mass[kg]", tstRslt.MassCTV);
LV("CTV.TestTime[s]", tstRslt.TestTime);
// --- Vetvenie podľa WMPulses (len logy + existujúca logika) ---
if (regReader.WMPulses >= 1)
{
meterRslt.TestTime = cBrd.TestTimeWM(regReader.Position);
LV("Branch", "NORMAL (WMPulses>=1)");
LV("TestTimeWM[s]", meterRslt.TestTime);
// Referencie z pulzov mastera
meterRslt.VolumeRef = meterRslt.PulsesMaster * tstRslt.ConstMaster; // [l]
meterRslt.MassRef = meterRslt.PulsesMaster * tstRslt.MassConstMaster; // [kg] ← pozri poznámku nižšie
LV("VolumeRef[l]", meterRslt.VolumeRef);
LV("MassRef[kg]", meterRslt.MassRef);
}
else
{
meterRslt.TestTime = tstRslt.TestTime;
meterRslt.VolumeRef = tstRslt.VolumeCTV; // [l]
meterRslt.MassRef = tstRslt.MassCTV; // [kg]
LV("Branch", "FALLBACK (WMPulses<1)");
LV("TestTime[s]", meterRslt.TestTime);
LV("VolumeRef[l]", meterRslt.VolumeRef);
LV("MassRef[kg]", meterRslt.MassRef);
}
// --- Záverečný súhrn pre rýchly grep ---
LiveLogDiag.Log1(
$"{LP} SUMMARY " +
$"type={readerType}, WMPulses={regReader.WMPulses}, pos={regReader.Position}, " +
$"PM={meterRslt.PulsesMaster}, CM={tstRslt.ConstMaster}, MCM={tstRslt.MassConstMaster}, " +
$"Vmet={meterRslt.VolumeMeter}, Mmet={meterRslt.MassMeter}, " +
$"Vref={meterRslt.VolumeRef}, Mref={meterRslt.MassRef}, " +
$"t={meterRslt.TestTime}"
);
//===========================================
log.DebugFormat("Pulses: Pref4meter={0} Vmeter={1} Vref4meter={2} Mmeter={3} Mref4meter={4} Ttime4meter={5} Ttime={6}",
meterRslt.PulsesMaster,
meterRslt.VolumeMeter,
meterRslt.VolumeRef,
meterRslt.MassMeter,
meterRslt.MassRef,
meterRslt.TestTime,
tstRslt.TestTime);
}
//===========================================
LiveLogDiag.Log1("================= Vyhodnotenie ==================");
/*meterRslt.Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef);
meterRslt.ErrorMass = Formulas.ErrorFromVolumes(meterRslt.MassMeter, meterRslt.MassRef);
meterRslt.Passed = (meterRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty)
&& (meterRslt.Error <= test.GetErrLimHi(tstRslt.VolumeCTV, tstRslt.TestTime) - test.Uncertainty)
&& (tstRslt.ErrorFlags == 0);
meterRslt.PassedMass = (meterRslt.ErrorMass >= test.GetErrLimLo(tstRslt.MassCTV, tstRslt.TestTime) + test.Uncertainty)
&& (meterRslt.ErrorMass <= test.GetErrLimHi(tstRslt.MassCTV, tstRslt.TestTime) - test.Uncertainty)
&& (tstRslt.ErrorFlags == 0);*/
LP = "[CHECK]";
LV = (n, v) => LiveLogDiag.Log1(string.Format("{0} {1}={2}", LP, n, v ?? "null"));
string LogPrefix = "[Diagnostics]";
// výpočet chýb
double Error = 0;
if (meterRslt.GetQuantityFromUnits() == "Mass")
Error = Formulas.ErrorFromVolumes(meterRslt.MassMeter, meterRslt.MassRef);
else
Error = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef);
meterRslt.Error = Error;
//meterRslt.ErrorMass = Formulas.ErrorFromVolumes(meterRslt.MassMeter, meterRslt.MassRef);
// prehľad vstupov do limitov
LiveLogDiag.Log1($"{LogPrefix} {nameof(tstRslt.VolumeCTV)}={tstRslt.VolumeCTV}");
LiveLogDiag.Log1($"{LogPrefix} {nameof(tstRslt.MassCTV)}={tstRslt.MassCTV}");
LiveLogDiag.Log1($"{LogPrefix} {nameof(tstRslt.TestTime)}={tstRslt.TestTime}");
LiveLogDiag.Log1($"{LogPrefix} {nameof(test.Uncertainty)}={test.Uncertainty}");
LiveLogDiag.Log1($"{LogPrefix} {nameof(tstRslt.ErrorFlags)}={tstRslt.ErrorFlags}");
// výpočet limitov (uložené do premenných len kvôli logu; logika zostáva rovnaká)
var ErrLimLo_Volume = test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime);
var ErrLimHi_Volume = test.GetErrLimHi(tstRslt.VolumeCTV, tstRslt.TestTime);
var ErrLimLo_Mass = test.GetErrLimLo(tstRslt.MassCTV, tstRslt.TestTime);
var ErrLimHi_Mass = test.GetErrLimHi(tstRslt.MassCTV, tstRslt.TestTime);
// log hodnoty chýb a limity
LiveLogDiag.Log1($"{LogPrefix} {nameof(meterRslt.Error)}={meterRslt.Error}");
//LiveLogDiag.Log1($"{LogPrefix} {nameof(meterRslt.ErrorMass)}={meterRslt.ErrorMass}");
LiveLogDiag.Log1($"{LogPrefix} ErrLimLo_Volume={ErrLimLo_Volume}, ErrLimHi_Volume={ErrLimHi_Volume}");
LiveLogDiag.Log1($"{LogPrefix} ErrLimLo_Mass={ErrLimLo_Mass}, ErrLimHi_Mass={ErrLimHi_Mass}");
// pôvodné vyhodnotenie (nezmenené), len doplnené logy výsledkov
bool Passed;
if (meterRslt.GetQuantityFromUnits() == "Mass")
Passed = (meterRslt.Error >= ErrLimLo_Volume + test.Uncertainty) &&
(meterRslt.Error <= ErrLimHi_Volume - test.Uncertainty) &&
(tstRslt.ErrorFlags == 0);
else
Passed = (meterRslt.Error >= ErrLimLo_Mass + test.Uncertainty) &&
(meterRslt.Error <= ErrLimHi_Mass - test.Uncertainty) &&
(tstRslt.ErrorFlags == 0);
meterRslt.Passed = Passed;
//meterRslt.Passed =
// (meterRslt.Error >= ErrLimLo_Volume + test.Uncertainty) &&
// (meterRslt.Error <= ErrLimHi_Volume - test.Uncertainty) &&
// (tstRslt.ErrorFlags == 0);
//meterRslt.PassedMass =
// (meterRslt.ErrorMass >= ErrLimLo_Mass + test.Uncertainty) &&
// (meterRslt.ErrorMass <= ErrLimHi_Mass - test.Uncertainty) &&
// (tstRslt.ErrorFlags == 0);
// log výsledky PASS/FAIL
LiveLogDiag.Log1($"{LogPrefix} {nameof(meterRslt.Passed)}={meterRslt.Passed}");
//LiveLogDiag.Log1($"{LogPrefix} {nameof(meterRslt.PassedMass)}={meterRslt.PassedMass}");
LiveLogDiag.Log1("==================================================");
//===========================================
meterRslt.TestDone = true;
tstRslt.TestDone = true;
#if ORACLE_DB
meterRslt.ErrorBC = meterRslt.Error;
#endif
}
}
tstRslt.Components = Results.Entities.Components.UpdateList(BatchRslts.ComponentsList,
new Results.Entities.Components((BenchInfo != null) ? BenchInfo.TestBenchId : 1,
(BenchInfo != null) ? BenchInfo.TestBenchName : "testbench",
inPath.Pump != null ? inPath.Pump.Name : string.Empty,
outPath.FlowMeter != null ? outPath.FlowMeter.Name : string.Empty,
cBrd.Devices.Scale.Name,
outPath.RegValve != null ? outPath.RegValve.Name : string.Empty,
outPath.Diverter != null ? outPath.Diverter.Name : string.Empty));
/// Update water meter error flags
if (ErrorFlagsComp != null)
{
if (BatchRslts.Batch != null && BatchRslts.Batch.WaterMeters != null)
{
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
{
if (BatchRslts.Batch.WaterMeters[i] != null && !BatchRslts.Batch.WaterMeters[i].Disabled)
{
long wmInfoFlags;
BatchRslts.Batch.WaterMeters[i].ErrorFlags = ErrorFlagsComp.GetWMtrErrorFlags(BatchRslts.Batch.WaterMeters[i].MeterTestRslts, out wmInfoFlags);
BatchRslts.Batch.WaterMeters[i].InfoFlags = wmInfoFlags;
}
}
}
}
/// Update results
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(testName, tstRslt));
}
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.TransitionAfter));
/// Append the results to the CSV-file
allResults.Info(TestResult2CsvLine(testName, test.Part));
if (stopCycle) retVal = Event.ErrorFlagsStop;
stopTest:
StopRecordingStatistics(); /// Make sure graph files are closed
///
/// Quit this sequence
///
if (isLastRepetition || retVal == Event.UiCmdStop
|| retVal == Event.OpArgumentError
|| retVal == Event.RecoverableError
|| retVal == Event.ErrorFlagsStop
|| retVal == Event.Error
|| retVal == Event.ConfigurationError)
{
cBrd.StopAll(false);
}
return new List<Event> { retVal };
}
IList<Event> Simulate1(Config.Entities.Test test, int repetitionNr, bool isLastRepetition)
{
///
/// Test method simulation
///
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
foreach (var rr in sensPath.RegisterReaders)
{
if (rr is IRegReaderDatastream) (rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
}
State.Create(string.Format("{0}({1}) : Reading watermeters", test.Method, test.Name))
.AddOperation(checkUiOp)
.EnterState();
StateMachine.WaitRunDevsRunOps();
StateMachine.WaitRunDevsRunOps();
float errorPctBase = -1.0f;
if (test.Name.ToLower().Contains("q3")) errorPctBase = -0.5f;
else if (test.Name.ToLower().Contains("q2")) errorPctBase = 0.5f;
else if (test.Name.ToLower().Contains("q1")) errorPctBase = -5.1f;
MakeSimulated(test, repetitionNr, test.Part, errorPctBase + repetitionNr * 0.1f);
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Completed));
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, 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, string.Format("{0} Simulation", test.Name));
//-------------------------------------------------------------------
State.Create(string.Format("{0}({1}) : Simulation", test.Method, test.Name))
.AddOperation(checkUiOp)
.EnterState();
IList<Event> e = StateMachine.WaitRunDevsRunOps();
return new List<Event> { TestAndLogUiCmdStop(test, e) ? Event.UiCmdStop : Event.Done };
}
IList<Event> Simulate2(Config.Entities.Test test, int repetitionNr, bool isLastRepetition)
{
IList<Event> e;
Event retVal = Event.Done;
///
/// Test method with flow chart simulation
///
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.FlowSetting));
/// Simulate flow
StartNewStatistics(null, BatchRslts.Batch.BatchNr, test, repetitionNr, 0);
IntBox remainingTime = new IntBox((int)test.TestTime);
State.Create(string.Format("{0}({1}) : Simulation", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperation(new Operations.TimerOp((int)test.TestTime, remainingTime))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; break; }
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Test));
if (remainingTime.Val > 60)
{
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Test_in_progress, remainingTime.Val / 60, "min", remainingTime.Val % 60, Strings.sec));
}
else
{
Bridge.OnActivity(this, string.Format("{0} ... {1} s", Strings.Test_in_progress, remainingTime.Val));
}
//------------------------------------------------
RefFlow.Val = (1.0 + 0.2 * Math.Sin(2 * Math.PI * (float)remainingTime.Val / test.TestTime)) * (test.QfromM3ph() + test.QtoM3ph()) / 2.0;
PressUp.Val = 2.7f;
PressDown.Val = 2.2f;
UpdateAllStatistics();
}
while (!e.Contains(Event.TimerExpired));
StopRecordingStatistics();
if (retVal != Event.UiCmdStop)
{
float errorPctBase = -1.0f;
if (test.Name.ToLower().Contains("q3")) errorPctBase = -0.5f;
else if (test.Name.ToLower().Contains("q2")) errorPctBase = 0.5f;
else if (test.Name.ToLower().Contains("q1")) errorPctBase = -5.1f;
MakeSimulated(test, repetitionNr, test.Part, errorPctBase + repetitionNr * 0.1f);
Bridge.OnTestProgress(this, new TestProgressEventArgs(test, repetitionNr, Progress.Completed));
Bridge.OnTestCompleted(this, new TestCompletedEventArgs(test.Name, BatchRslts.GetTestRslt(Results.Utils.GetTestName(test.Name, 1, 1), 0)));
allResults.Info(TestResult2CsvLine(test.Name, 0)); /// Append the results to the CSV-file
}
return new List<Event> { retVal }; /// default 'retVal' value is Event.Done
}
/// <summary>
/// Diagnostic logging MF
/// Activated by compilation condition: DIAG_ENDURANCE_xyz
/// </summary>
static class LiveLogDiag
{
[Conditional("DIAG_LOG_MASS1")]
public static void Log1(string format, params object[] args)
{
//LiveLogCache.Instance.AddLog(string.Format(format, args));
}
}
}
}