///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.ControlBoard.Uni
{
public class FlyingStartStopTestWithDivOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(FlyingStartStopTestWithDivOp));
public override string ToString() { return string.Format("FlyingStartStopTestWithDivOp()"); }
/// Arguments of the constructor
readonly UniCB uniCB;
readonly TBF.Rig.Uni.RegValve.RegValve regV;
readonly TBF.Rig.Uni.FlowMeter.FlowMeter flowMeter;
readonly TBF.Rig.Uni.Diverter.Diverter div;
readonly double qFrom;
readonly double qTo;
readonly int pulsesCount; /// Number of reference pulses for a complete test
readonly int massPulsesCount; /// Number of reference pulses for mass collection
readonly bool readDivTransition;
readonly bool isProlongedTest;
///
/// 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
/// TestPart2InProgress .. first part when water is diverted to a tank was successfully completed, part2 in progress,
/// prolonged method only: (massPulsesCount GT 0) and (massPulsesCount LT pulsesCount)
/// TestCompleted ........ test was successfully completed
/// Error ................ unspecified error while running a test
///
/// Control board component
/// Components used by the test
/// Flow lower limit
/// Flow upper limit
/// Test duration - number of reference flow meter pulses
/// Test part 1 duration - number of reference flow meter pulses<
public FlyingStartStopTestWithDivOp(UniCB cb, OutputPath devices, double qFrom, double qTo,
int pulsesCount, int massPulsesCount, bool readDivTransition)
{
this.uniCB = cb;
flowMeter = devices.FlowMeter as TBF.Rig.Uni.FlowMeter.FlowMeter;
if (flowMeter == null) throw new ArgumentNullException("Invalid flow meter");
regV = devices.RegValve as TBF.Rig.Uni.RegValve.RegValve;
if (regV == null) throw new ArgumentNullException("Invalid regulation valve");
div = devices.Diverter as TBF.Rig.Uni.Diverter.Diverter;
if (div == null) throw new ArgumentNullException("Invalid diverter");
this.qFrom = qFrom;
this.qTo = qTo;
this.pulsesCount = pulsesCount;
this.massPulsesCount = massPulsesCount;
this.readDivTransition = readDivTransition;
this.isProlongedTest = (0 < massPulsesCount) && (massPulsesCount < pulsesCount);
log.Debug(this.ToString());
}
/// Internal states of this operation
enum OpState
{
StartingTest,
ReadingDivTransition,
TestInProgress,
TestPart1InProgress, /// prolonged test only
TestPart2InProgress, /// prolonged test only
TestCompleted,
}
OpState opState;
///
/// Start this operation
///
public void Start()
{
log.InfoFormat("Op.Start() RV#={0} Et#={1} Div#={2} Qfrom={3} Qto={4}", regV.Idx1, flowMeter.Idx1, div.DiverterNr, qFrom, qTo);
/// Start the test (and the flow measurement)
uniCB.StartTest(false, flowMeter.Idx1, div.DiverterNr, 40, true, true, false, pulsesCount, massPulsesCount);
opState = OpState.StartingTest;
}
///
/// Run this operation
///
///
/// Event.OpArgumentError ...... invalid arguments, test cannot be started
/// Event.StartingTest ......... starting a test
/// Event.TestInProgress ....... test was successfully started, test is running
/// Event.TestPart1InProgress .. first part when water is diverted to a tank was successfully completed, part2 in progress,
/// Event.TestPart2InProgress .. first part when water is diverted to a tank was successfully completed, part2 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
///
public Event Run()
{
log.DebugFormat("Op.Run() opState={0}", opState);
switch (opState)
{
case OpState.StartingTest:
if (qFrom < 0 || qFrom >= qTo || qTo > 1.25 * flowMeter.NominalFlow)
{
return Event.OpArgumentError; /// Invalid qFrom, qTo
}
if (!flowMeter.MsrmntAvailable || /// Flow measurement not started yet
(uniCB.State & (ulong)StatusP.TestInProgress) == 0 || /// Test was not started yet
(flowMeter.ReadFlow()) == 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 * reqFlowLo / flowMeter.NominalFlow,
2000 * reqFlowHi / flowMeter.NominalFlow);
opState = readDivTransition ? OpState.ReadingDivTransition
: (isProlongedTest ? OpState.TestPart1InProgress : OpState.TestInProgress);
return isProlongedTest ? Event.TestPart1InProgress : Event.TestInProgress;
case OpState.ReadingDivTransition:
/// Read diverter transition data
uniCB.ReadDiverterTransition(false, div.DiverterNr);
opState = isProlongedTest ? OpState.TestPart1InProgress : OpState.TestInProgress;
return isProlongedTest ? Event.TestPart1InProgress : Event.TestInProgress;
case OpState.TestInProgress:
if ((uniCB.State & (ulong)StatusP.TestCompleted) == 0)
{
return Event.TestInProgress; /// Test was not completed yet
}
opState = OpState.TestCompleted;
return Event.TestCompleted;
case OpState.TestPart1InProgress:
if ((uniCB.State & (ulong)StatusP.TestCompleted) == 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)
{
/// Test was not completed yet
return Event.TestPart2InProgress;
}
opState = OpState.TestCompleted;
return Event.TestCompleted;
case OpState.TestCompleted:
default:
return Event.TestCompleted;
}
}
///
/// Stop this operation
///
public void Stop()
{
log.Info("Op.Stop()");
uniCB.Stop(false);
}
}
}