/// /// Copyright (c) 2021 Sensus Slovensko a.s. /// using System; 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()"); } /// 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 isProlonged; readonly int massPulsesCount; /// Number of reference pulses for mass collection readonly bool readDivTransition; readonly Statistics divStartPlotter; readonly Statistics divStopPlotter; readonly TBF.Rig.Uni.RegValve.RegValve regV; readonly TBF.Rig.Uni.FlowMeter.FlowMeter flowMeter; readonly TBF.Rig.Uni.Diverter.Diverter diverter; /// /// 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 /// /// Control board component /// Components used by the test /// Flow lower limit /// Flow upper limit /// Test duration - number of reference flow meter pulses /// true = Test with diverter /// true = Prolonged test with diverter /// Test part 1 duration - number of reference flow meter pulses< /// true = Read diverter transition public FlyingStartStopTestOp(UniCB cb, OutputPath devices, double qFrom, double qTo, int pulsesCount, bool withDiverter, 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.isProlonged = withDiverter && isProlonged; this.massPulsesCount = massPulsesCount; this.readDivTransition = withDiverter && readDivTransition; this.divStartPlotter = divStartPlotter; this.divStopPlotter = divStopPlotter; 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"); 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; /// /// Start this operation /// 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) uniCB.StartTest(false, flowMeter.Idx1, (diverter != null) ? diverter.DiverterNr : 0, (diverter != null) ? diverter.StartThreshold : 0, true, withDiverter, false, isProlonged, 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 .. 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 /// 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 (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 * reqFlowLo / flowMeter.NominalFlow, 2000 * 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; } } /// /// Stop this operation /// public void Stop() { log.Info("Op.Stop()"); uniCB.Stop(false); } } }