- Introduced simulation timers in `FlyingStartStopTestOp`. - Added `Simulate` methods in `WaterMetrologyData`, `WaterMetrologyDataC7`, and `WaterMetrologyDataC2`. - Enhanced `SmartCommunicationForm` with textbox resizing logic and initialization code. - Implemented flow rate and volume calculation from optohead telemetry in `SmartReader`. - Added unit tests for Poseidon correction parsing.
251 lines
11 KiB
C#
251 lines
11 KiB
C#
///
|
|
/// Copyright (c) 2021-2023 Sensus Slovensko a.s.
|
|
///
|
|
using System;
|
|
using Common;
|
|
using log4net;
|
|
using TBF.Rig.Sequences;
|
|
|
|
namespace TBF.Rig.ControlBoard.Uni
|
|
{
|
|
public class FlyingStartStopTestOp : IOperation
|
|
{
|
|
private static readonly ILog log = LogManager.GetLogger(typeof(FlyingStartStopTestOp));
|
|
public override string ToString() { return string.Format("FlyingStartStopTestOp()"); }
|
|
|
|
private DateTime startTimeForSimulation;
|
|
private bool simulationTimerStarted = false;
|
|
|
|
|
|
/// Arguments of the constructor
|
|
readonly UniCB uniCB;
|
|
readonly double qFrom;
|
|
readonly double qTo;
|
|
readonly int pulsesCount; /// Number of reference pulses for a complete test
|
|
readonly bool withDiverter;
|
|
readonly bool isDelayedStart;
|
|
readonly bool isProlonged;
|
|
readonly int massPulsesCount; /// Number of reference pulses for mass collection
|
|
readonly bool readDivTransition;
|
|
readonly Statistics divStartPlotter;
|
|
readonly Statistics divStopPlotter;
|
|
readonly GenericDevices.IRegValve regV;
|
|
readonly TBF.Rig.GenericDevices.IFlowMeter flowMeter;
|
|
readonly TBF.Rig.Uni.Diverter.Diverter diverter;
|
|
|
|
/// <summary>
|
|
/// Operation for a Flying start-stop test with a diverter (constructor)
|
|
///
|
|
/// Events: OpArgumentError ...... invalid arguments, test cannot be started
|
|
/// StartingTest ......... starting a test
|
|
/// TestInProgress ....... test was successfully started, test is running
|
|
/// TestPart1InProgress .. test was successfully started, part1 of a prolonged test (collecting water) is running
|
|
/// TestPart2InProgress .. first part of a prolonged test was successfully completed, part2 is in progress.
|
|
/// Prolonged method only: (massPulsesCount GT 0) and (massPulsesCount LT pulsesCount)
|
|
/// TestCompleted ........ test was successfully completed
|
|
/// Error ................ unspecified error while running a test
|
|
/// </summary>
|
|
/// <param name="cb">Control board component</param>
|
|
/// <param name="devices">Components used by the test</param>
|
|
/// <param name="qFrom">Flow lower limit</param>
|
|
/// <param name="qTo">Flow upper limit</param>
|
|
/// <param name="pulsesCount">Test duration - number of reference flow meter pulses</param>
|
|
/// <param name="withDiverter">true = Test with diverter</param>
|
|
/// <param name="isProlonged">true = Prolonged test with diverter</param>
|
|
/// <param name="massPulsesCount">Test part 1 duration - number of reference flow meter pulses<</param>
|
|
/// <param name="readDivTransition">true = Read diverter transition</param>
|
|
public FlyingStartStopTestOp(UniCB cb, OutputPath devices, double qFrom, double qTo, int pulsesCount,
|
|
bool withDiverter, bool isDelayedStart, bool isProlonged, int massPulsesCount,
|
|
bool readDivTransition, Statistics divStartPlotter, Statistics divStopPlotter)
|
|
{
|
|
this.uniCB = cb;
|
|
this.qFrom = qFrom;
|
|
this.qTo = qTo;
|
|
this.pulsesCount = pulsesCount;
|
|
this.withDiverter = withDiverter;
|
|
this.isDelayedStart = isDelayedStart;
|
|
this.isProlonged = withDiverter && isProlonged;
|
|
this.massPulsesCount = massPulsesCount;
|
|
this.readDivTransition = withDiverter && readDivTransition;
|
|
this.divStartPlotter = divStartPlotter;
|
|
this.divStopPlotter = divStopPlotter;
|
|
|
|
flowMeter = devices.FlowMeter;
|
|
if (flowMeter == null) throw new ArgumentNullException("Invalid flow meter");
|
|
|
|
regV = devices.RegValve as GenericDevices.IRegValve;
|
|
if (regV == null) throw new ArgumentNullException("Invalid regulation valve");
|
|
|
|
diverter = (withDiverter && devices.Diverter is TBF.Rig.Uni.Diverter.Diverter)
|
|
? devices.Diverter as TBF.Rig.Uni.Diverter.Diverter : null;
|
|
|
|
log.Debug(this.ToString());
|
|
}
|
|
|
|
/// Internal states of this operation
|
|
enum OpState
|
|
{
|
|
StartingTest,
|
|
TestInProgress,
|
|
TestPart1InProgress, /// prolonged test only
|
|
TestPart2InProgress, /// prolonged test only
|
|
TestCompleted,
|
|
}
|
|
|
|
OpState opState;
|
|
|
|
/// <summary>
|
|
/// Start this operation
|
|
/// </summary>
|
|
public void Start()
|
|
{
|
|
log.InfoFormat("Op.Start() RV#={0} Et#={1} Div#={2} Qfrom={3} Qto={4}",
|
|
regV.Idx1, flowMeter.Idx1, (diverter != null) ? diverter.DiverterNr : 0, qFrom, qTo);
|
|
|
|
/// Start the test (and the flow measurement)
|
|
if (withDiverter) { uniCB.DivResolution = diverter.Resolution; }
|
|
uniCB.SetActivity((diverter != null) ? Activity.FlyingStartStopTestWithDiverter : Activity.FlyingStartStopTest);
|
|
uniCB.StartTest(false, flowMeter.Idx1, (diverter != null) ? diverter.DiverterNr : 0, (diverter != null) ? diverter.StartThreshold : 0,
|
|
true, withDiverter, isDelayedStart, false, isProlonged, pulsesCount, massPulsesCount);
|
|
|
|
opState = OpState.StartingTest;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Run this operation
|
|
/// </summary>
|
|
/// <returns>
|
|
/// Event.OpArgumentError ...... invalid arguments, test cannot be started
|
|
/// Event.StartingTest ......... starting a test
|
|
/// Event.TestInProgress ....... test was successfully started, test is running
|
|
/// Event.TestPart1InProgress .. test was successfully started, part1 of a prolonged test (collecting water) is running
|
|
/// Event.TestPart2InProgress .. first part of a prolonged test was successfully completed, part2 is in progress.
|
|
/// Prolonged method only: (massPulsesCount GT 0) and (massPulsesCount LT pulsesCount)
|
|
/// Event.TestCompleted ........ test was successfully completed
|
|
/// Event.Error ................ unspecified error while running a test
|
|
/// </returns>
|
|
public Event Run()
|
|
{
|
|
log.DebugFormat("Op.Run() opState={0}", opState);
|
|
|
|
//Simulation of processing time 25 seconds
|
|
if (uniCB.DebugLevel == DebugMode.Simulate)
|
|
{
|
|
if (opState == OpState.StartingTest)
|
|
{
|
|
startTimeForSimulation = DateTime.Now;
|
|
simulationTimerStarted = false;
|
|
}
|
|
if (opState == OpState.TestInProgress)
|
|
{
|
|
if (!simulationTimerStarted)
|
|
{
|
|
startTimeForSimulation = DateTime.Now;
|
|
simulationTimerStarted = true;
|
|
}
|
|
else if (DateTime.Now - startTimeForSimulation > TimeSpan.FromSeconds(25))
|
|
{
|
|
return Event.TestCompleted;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (opState)
|
|
{
|
|
case OpState.StartingTest:
|
|
|
|
if (qFrom < 0 || qFrom >= qTo || qTo > 1.25 * flowMeter.NominalFlow)
|
|
{
|
|
return Event.OpArgumentError; /// Invalid qFrom, qTo
|
|
}
|
|
if (isProlonged && (massPulsesCount <= 0 || massPulsesCount >= pulsesCount))
|
|
{
|
|
return Event.OpArgumentError; /// Invalid qFrom, qTo
|
|
}
|
|
|
|
//if (!flowMeter.MsrmntAvailable || /// Flow measurement not started yet
|
|
// (uniCB.State & (ulong)StatusP.ReadingCounters) == 0 || /// Test was not started yet
|
|
// uniCB.RefFrequency == 0) /// Measured flow is 0
|
|
//{
|
|
// return Event.StartingTest; /// Flow regulation cannot be started
|
|
//}
|
|
|
|
/// Start flow regulation
|
|
double reqFlowAve = (qFrom + qTo) / 2;
|
|
double reqFlowLo = (0.7 * qFrom) + (0.3 * reqFlowAve); /// Move the lower limit 15% of the range up
|
|
double reqFlowHi = (0.7 * qTo) + (0.3 * reqFlowAve); /// Move the upper limit 15% of the range down
|
|
///
|
|
uniCB.SetFlow(false, regV.Idx1, 2000.0 * reqFlowLo / flowMeter.NominalFlow,
|
|
2000.0 * reqFlowHi / flowMeter.NominalFlow);
|
|
if (readDivTransition)
|
|
{
|
|
/// Schedule reading diverter transition data
|
|
uniCB.DelayStartOrStop(false);
|
|
uniCB.GetDiverterTransitionData(false, diverter, true, divStartPlotter);
|
|
}
|
|
|
|
opState = isProlonged ? OpState.TestPart1InProgress : OpState.TestInProgress;
|
|
return isProlonged ? Event.TestPart1InProgress : Event.TestInProgress;
|
|
|
|
case OpState.TestInProgress:
|
|
|
|
if ((uniCB.State & (ulong)StatusP.TestCompleted) == 0)
|
|
{
|
|
/// Test is running
|
|
return Event.TestInProgress;
|
|
}
|
|
|
|
/// Test was completed now
|
|
if (readDivTransition)
|
|
{
|
|
uniCB.DelayStartOrStop(false);
|
|
uniCB.GetDiverterTransitionData(false, diverter, false, divStopPlotter);
|
|
}
|
|
opState = OpState.TestCompleted;
|
|
return Event.TestCompleted;
|
|
|
|
case OpState.TestPart1InProgress:
|
|
|
|
if ((uniCB.State & (ulong)StatusP.DirectionOfDiverter) != 0)
|
|
{
|
|
return Event.TestPart1InProgress; /// Test was not completed yet
|
|
}
|
|
|
|
opState = OpState.TestPart2InProgress;
|
|
return Event.TestPart2InProgress;
|
|
|
|
case OpState.TestPart2InProgress:
|
|
|
|
if ((uniCB.State & (ulong)StatusP.TestCompleted) == 0)
|
|
{
|
|
/// 2nd part of test with diverter is running
|
|
return Event.TestPart2InProgress;
|
|
}
|
|
|
|
/// 2nd part of test with diverter was completed now
|
|
if (readDivTransition)
|
|
{
|
|
uniCB.DelayStartOrStop(false);
|
|
uniCB.GetDiverterTransitionData(false, diverter, false, divStopPlotter);
|
|
}
|
|
opState = OpState.TestCompleted;
|
|
return Event.TestCompleted;
|
|
|
|
case OpState.TestCompleted:
|
|
default:
|
|
return Event.TestCompleted;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stop this operation
|
|
/// </summary>
|
|
public void Stop()
|
|
{
|
|
log.Info("Op.Stop()");
|
|
uniCB.SetActivity((opState == OpState.TestCompleted) ? Activity.TestCompleted : Activity.Idle);
|
|
uniCB.StopAll(false);
|
|
}
|
|
}
|
|
}
|