Upgrade - StandingStartMassCollectionAdvance method - 1. changed structure and residual flow delays by changes in StandingStartMassCollection method, 2. added variables, counting and evaluation for volume/mass type of RegisterReader

This commit is contained in:
Marek Frniak 2026-07-17 12:42:07 +02:00
parent b703297f5e
commit 271200a8da
3 changed files with 195 additions and 44 deletions

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("3.9.3134.103")]
[assembly: AssemblyFileVersion("3.9.3134.103")]
[assembly: AssemblyVersion("3.9.3134.104")]
[assembly: AssemblyFileVersion("3.9.3134.104")]

View File

@ -1216,6 +1216,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollection
tstRslt.ConstMasterRaw = 1; /// Uncorrected master flowmeter coefficient
tstRslt.ConstMasterCorr = 1; /// Corrected master pulses per liter
tstRslt.ConstMaster = 1;
tstRslt.MassConstMaster = 1;
}
tstRslt.ErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.VolumeCTV);
tstRslt.MassErrorMaster = Formulas.ErrorFromVolumes(tstRslt.VolumeMaster, tstRslt.MassCTV);

View File

@ -1,14 +1,16 @@
///
using Common;
using Config.Entities;
using FluentNHibernate.Conventions;
using log4net;
///
/// Copyright (c) 2013-2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using log4net;
using Common;
using Config.Entities;
using FluentNHibernate.Conventions;
using System.Windows.Forms;
using System.Xml.Serialization;
using TBF.Boxes;
using TBF.Resources;
using TBF.Rig.Generic;
@ -16,6 +18,7 @@ using TBF.Rig.GenericDevices;
using TBF.Rig.Network.RestAPI;
using TBF.Rig.Operations;
using TBF.Rig.Sequences;
using TBF.Rig.Various.ErrorFlags;
using TBF.UiBridge;
namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
@ -115,6 +118,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state
processDataLoggingOp = new TBF.Rig.Operations.ProcessDataLoggingOp(processDataLogger, this, heatMetersTestParams != null);
int delay;
if (cBrd is ControlBoard.Uni.UniCB)
{
int[] filters = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };
@ -332,8 +337,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
State.Create(string.Format("{0}({1}) : Setting the flow", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(cBrd.SetFlowOp(test.QfromM3ph(), test.QtoM3ph(), RefFlow, FlowSettingTimeoutSec))
.AddOperation(heatMetersPromptOp)
.AddOperation(cBrd.SetFlowOp(test.QfromM3ph(), test.QtoM3ph(), RefFlow, FlowSettingTimeoutSec))//...develop: step 1
.AddOperation(heatMetersPromptOp)
.EnterState();
do {
e = StateMachine.WaitRunDevsRunOps();
@ -454,8 +459,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
State.Create(string.Format("{0}({1}) : Close the start/stop valve before measuring the start mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(cBrd.CloseStartValveOp())
.EnterState();
.AddOperation(cBrd.CloseStartValveOp())//...develop: step 2
.EnterState();
do {
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
@ -463,10 +468,39 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
}
while (!e.Contains(Event.ValvesSet));
///...MF
///-----------------
delay = test.TimeFlow2Mass;
if (delay > 0)
{
State.Create(string.Format("{0}({1}) : Delay for meters stabilization <T flow stab. - start = {2}s> ", test.Method, test.Name, delay))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(new Operations.TimerOp(delay)) //...develop: step 5
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
if (TestAndLogUiCmdStop(test, e)) { retVal = Event.UiCmdStop; goto stopTest; }
/// Show remaining time
if ((delay = Math.Max(delay, 0)) > 60)
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", "Delay", delay / 60, "min", delay % 60, Strings.sec));
else
Bridge.OnActivity(this, string.Format("{0} ... {1} s", "Delay", delay));
if (delay > 0)
delay--;
}
while (!e.Contains(Event.TimerExpired));
}
State.Create(string.Format("{0}({1}) : Start the standing start/stop test", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)
.AddOperation(testInProgress)//...develop: step 4 --> diverter switch to the mass
.EnterState();
for (int i = 0; i < 3; i++)
{
@ -492,6 +526,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
///
GenericDevices.IHasWMStatesForm dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IHasWMStatesForm;
IOperation readStartMassOp = scale.ReadStableMassOp(ref StartMass, test.TimeFlow2Mass, test.MassMethod, test.MassRepeats, test.MassSpread);
IOperation readStopMassOp = scale.ReadStableMassOp(ref StartMass, test.TimeStop2Mass, test.MassMethod, test.MassRepeats, test.MassSpread);
IOperation readEndMassOp = scale.ReadStableMassOp(ref EndMass, test.TimeStop2Mass, test.MassMethod, test.MassRepeats, test.MassSpread);
if (dataEntryCmpnt != null)
{
@ -510,7 +546,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
State state2 = State.Create(string.Format("{0}({1}) : Grab images", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(readStartMassOp)
//.AddOperation(readStartMassOp)
.AddOperation(testInProgress)
.AddOperation(processDataLoggingOp);
@ -565,12 +601,13 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
Bridge.OnActivity(this, Strings.Grabbing_images);//Strings.Enter_water_meter_data);
State.Create(string.Format("{0}({1}) : Enter start states of water meters", test.Method, test.Name))
State.Create(string.Format("{0}({1}) : Enter start states of water meters and Measuring the start mass after residual flow <T stop-mass msrmt time = {2}s>", test.Method, test.Name, test.TimeStop2Mass))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(readStartMassOp)
//.AddOperation(readStartMassOp)
.AddOperation(testInProgress)
//.AddOperation((dataEntryCmpnt as GenericDevices.IHasWMStatesForm).ShowTestStartFormOp(sensPath.RegisterReaders))
//.AddOperation((dataEntryCmpnt as GenericDevices.IHasWMStatesForm).ShowTestStartFormOp(sensPath.RegisterReaders))//...develop: half of step 6
.AddOperation(readStopMassOp) //...develop: half of step 6
.AddOperation(processDataLoggingOp)
.EnterState();
do {
@ -650,10 +687,31 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
}
}
}
State.Create(string.Format("{0}({1}) : Measure the start mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)//...nevhodne prepina diverter
.AddOperation(scale.ReadStableMassOp(ref StartMass, 0, test.MassMethod, test.MassRepeats, test.MassSpread))//...develop: step 8
.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));
}
else
{
State.Create(string.Format("{0}({1}) : Measure the start mass", test.Method, test.Name))
/*State.Create(string.Format("{0}({1}) : Measure the start mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)
@ -671,6 +729,27 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
goto stopTest;
}
}
while (!e.Contains(Event.ScaleDone) && !e.Contains(Event.Next));*/
State.Create(string.Format("{0}({1}) : Measure the start mass", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)//...nevhodne prepina diverter
//.AddOperation(readStartMassOp)
.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));
}
///
@ -698,10 +777,10 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
State.Create(string.Format("{0}({1}) : Start the test, open the start/stop valve", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(cBrd.OpenStartValveOp(timeStampStart, startSwitchTime))
.AddOperation(cBrd.OpenStartValveOp(timeStampStart, startSwitchTime)) //...develop: step 9
.AddOperation(testInProgress)
.AddOperation(controlFlowOp)
.AddOperation(processDataLoggingOp)
.AddOperation(processDataLoggingOp)//...develop: step 10, step 11
.EnterState();
do {
e = StateMachine.WaitRunDevsRunOps();
@ -759,7 +838,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)
.AddOperation(cBrd.CloseStartValveOp(timeStampEnd, stopSwitchTime))
.AddOperation(cBrd.CloseStartValveOp(timeStampEnd, stopSwitchTime))//...develop: step 12
.AddOperation(processDataLoggingOp)
.EnterState();
do {
@ -778,12 +857,15 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
//------------------------------------------------
Bridge.OnActivity(this, Strings.Measuring_the_weight);
//------------------------------------------------
State.Create(string.Format("{0}({1}) : Measuring the end mass", test.Method, test.Name))
delay = test.TimeStop2Mass;
State.Create(string.Format("{0}({1}) : Measuring the end mass after residual flow <T stop-mass msrmt time = {2}s>", test.Method, test.Name, delay))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperation(testInProgress)
.AddOperation(scale.ReadStableMassOp(ref EndMass, test.TimeStop2Mass, test.MassMethod, test.MassRepeats, test.MassSpread))
.AddOperation(new Operations.TimerOp(StableMassMsrmntTimeoutSec))
//.AddOperation(new Operations.TimerOp(StableMassMsrmntTimeoutSec))
.AddOperation(processDataLoggingOp)
.EnterState();
do {
@ -796,26 +878,20 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
retVal = Event.RecoverableError;
goto stopTest;
}
/// Show remaining time
if ((delay = Math.Max(delay, 0)) > 60)
Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", "Delay", delay / 60, "min", delay % 60, Strings.sec));
else
Bridge.OnActivity(this, string.Format("{0} ... {1} s", "Delay", delay));
if (delay > 0)
delay--;
}
while (!e.Contains(Event.ScaleDone) && !e.Contains(Event.Next));
///
tMass2 = StateMachine.Time;
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))
.EnterState();
do
{
e = StateMachine.WaitRunDevsRunOps();
if (e.Contains(Event.Error)) { retVal = Event.Error; goto stopTest; }
}
while (e.Contains(Event.ValvesBusy));
}
double massStart = MeasurementCorrection.CorrectedValue(StartMass.Val, scale.Corrections);
double massEnd = MeasurementCorrection.CorrectedValue(EndMass.Val, scale.Corrections);
double densityOut = Formulas.WaterDensityFromTempPress((TempUpStat.Average + TempDownStat.Average) / 2,
@ -823,7 +899,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
double buoyancy = Formulas.Buoyancy();
double massOfEvaporatedWater = (double)(tMass2 - tMass1) * outPath.Scale.EvaporationRate(TempDivStat.Average);
double volumeCTV = 1000.0 * buoyancy * (massEnd - massStart + massOfEvaporatedWater) / densityOut;
if (debugLevel == Common.DebugMode.Simulate) volumeCTV = test.Volume;
double massCTV = buoyancy * (massEnd - massStart + massOfEvaporatedWater);
if (debugLevel == Common.DebugMode.Simulate) volumeCTV = test.Volume;
double refEnergy = Energy.Sum * volumeCTV / VolumeForEnergy.Sum; /// [J]=[J]*[l]/[l]
@ -989,6 +1066,20 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
}
}
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))
.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);
//------------------------------------------------
@ -1026,6 +1117,8 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
/// Main results
tstRslt.VolumeCTV = volumeCTV; /// [l] 1000.0f is because density is in [kg/m3]
tstRslt.Flow = 3.6 * volumeCTV / tstRslt.TestTime; /// [m3/h]
tstRslt.MassCTV = massCTV; /// [kg] 1000.0f is because density is in [kg/m3]
tstRslt.MassFlow = 3.6 * massCTV / tstRslt.TestTime; /// [kg/h]
if (cBrd is ControlBoard.Uni.UniCB)
{
@ -1034,6 +1127,7 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
tstRslt.ConstMasterCorr = outPath.FlowMeter.LtrPerPulseCorrected(tstRslt.Flow, tstRslt.TempDownMean);
tstRslt.VolumeMaster = tstRslt.ConstMasterRaw * tstRslt.PulsesMaster; /// [l] volume from the master flow meter
tstRslt.ConstMaster = (tstRslt.VolumeMaster != 0) ? (tstRslt.ConstMasterRaw * tstRslt.VolumeCTV / tstRslt.VolumeMaster) : tstRslt.ConstMasterCorr;
tstRslt.MassConstMaster = (tstRslt.PulsesMaster != 0) ? (tstRslt.MassCTV / tstRslt.PulsesMaster) : tstRslt.ConstMasterCorr;
}
else
{
@ -1193,18 +1287,74 @@ namespace TBF.Rig.TestMethods.StandingStartMassCollectionAdvance
if (meterRslt != null && regReader != null)
{
meterRslt.RegReaderType = (int)regReader.RegisterReaderType;
ComponentProcedure procParamsEntity = test.Procedure.GetProcedureParamsEntity(regReader.Name);
try
{
if (regReader.RegisterReaderType == RegisterReaderType.Pulses)
{
XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TBF.Rig.RegisterReaders.PulsesFromUniCB.RRProcParams) })[0];
TBF.Rig.RegisterReaders.PulsesFromUniCB.RRProcParams tmp = Serializer.Deserialize(new StringReader(procParamsEntity.Parameters.ToString())) as TBF.Rig.RegisterReaders.PulsesFromUniCB.RRProcParams;
regReader.PulsesPerLtr = tmp.PulsesPerLtr;
regReader.QuantityUnits = tmp.Units;
}
else if (regReader.RegisterReaderType == RegisterReaderType.Manual)
{
XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(TBF.Rig.RegisterReaders.StandingStartStop.RRProcParams) })[0];
TBF.Rig.RegisterReaders.StandingStartStop.RRProcParams tmp = Serializer.Deserialize(new StringReader(procParamsEntity.Parameters.ToString())) as TBF.Rig.RegisterReaders.StandingStartStop.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.ErrorFormat(string.Format("Error during RegisterReader parameters deserialization. regReader.Name='{0}', regReader.ClassName='{1}', Exception: {2}",
regReader.Name,
regReader.ClassName,
ex));
}
meterRslt.PulsesPerLiter = regReader.PulsesPerLtr;
meterRslt.VolumeStart = 0.0d;//regReader.BeginWMState;
meterRslt.VolumeEnd = 0.0d;//regReader.EndWMState;
meterRslt.VolumeMeter = 0.0d;//Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart);
meterRslt.VolumeStart = regReader.BeginWMState;//0.0d;//regReader.BeginWMState;
meterRslt.VolumeEnd = regReader.EndWMState;//0.0d;//regReader.EndWMState;
meterRslt.VolumeMeter = Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart);//0.0d;//Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart);
meterRslt.MassMeter = Math.Abs(meterRslt.VolumeEnd - meterRslt.VolumeStart);
meterRslt.VolumeRef = tstRslt.VolumeCTV; /// liter
meterRslt.MassRef = tstRslt.MassCTV; /// kg
meterRslt.PulsesMeter = meterRslt.VolumeMeter;
meterRslt.PulsesMaster = tstRslt.PulsesMaster;
meterRslt.TestTime = tstRslt.TestTime;
meterRslt.Error = 100.0d;//Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef);
meterRslt.Passed = (meterRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty)
//meterRslt.Error = 100.0d;//Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef);
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.Passed = (meterRslt.Error >= test.GetErrLimLo(tstRslt.VolumeCTV, tstRslt.TestTime) + test.Uncertainty)
&& (meterRslt.Error <= test.GetErrLimHi(tstRslt.VolumeCTV, tstRslt.TestTime) - test.Uncertainty)
&& (tstRslt.ErrorFlags == 0);
&& (tstRslt.ErrorFlags == 0);*/
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);
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.TestDone = false;
tstRslt.TestDone = false;
tstRslt.TestMeasured = true;