/// /// Copyright (c) 2013-2020 Sensus Slovensko a.s. /// using System; using log4net; using TBF.Rig.GenericDevices; namespace TBF.Rig.ControlBoard.Legacy { public class StartMeasurementOp : IOperation { private static readonly ILog log = LogManager.GetLogger(typeof(StartMeasurementOp)); public override string ToString() { return string.Format("StartMeasurementOp(ref={0},pulses={1})", flowMeterNr, totalRefPulses); } /// Set by the constructor readonly CBoard controlBoard; readonly IRegValve regulValve; readonly int regulValveNr; readonly int regulValveStableTime; readonly int flowMeterNr; readonly double nominalFlow; readonly double maximalFlow; readonly double reqFlowLo; readonly double reqFlowHi; readonly int totalRefPulses; /// Number of reference pulses for a complete test readonly int massRefPulses; /// Number of reference pulses for mass collection readonly int delayBeforeFlowRegulation; /// Delay before flow control starts in seconds readonly TestMethods testMethod; readonly int diverterNr; /// /// Internal states of this operation /// enum OpState { StartingTest, ResendCommand, WaitingBeforeValveMove, StartingFlowRegulation, OpCompleted, } OpState opState; int delayStartTime; /// StateMachine.Time snapshot when delay before flow regulation starts /// /// Starts the measurement. /// Events: MeasurementStarted /// /// Control board component reference /// Specifies used components /// Test method /// Test duration in number of reference flowmeter pulses /// Specifies filter for watermeter pulses public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method, double requiredFlowLo, double requiredFlowHi, int refPulses, int delayBeforeFlowRegulation = 0) : this(controlBoard, outputPath, method, requiredFlowLo, requiredFlowHi, refPulses, refPulses, delayBeforeFlowRegulation) { } /// /// Starts the measurement. /// Events: MeasurementStarted /// /// Control board component reference /// Specifies used components /// Test method /// Test duration in number of reference flowmeter pulses /// Specifies filter for watermeter pulses public StartMeasurementOp(CBoard controlBoard, OutputPath outputPath, TestMethods method, double requiredFlowLo, double requiredFlowHi, int totalRefPulses, int massRefPulses, int delayBeforeFlowRegulation = 0) { if (controlBoard == null) throw new ArgumentNullException("controlBoardDev"); this.controlBoard = controlBoard; if (outputPath.FlowMeter == null) throw new ArgumentNullException("Flow meter is missing"); flowMeterNr = outputPath.FlowMeter.Idx1; this.regulValve = outputPath.RegValve; regulValveNr = 0; regulValveStableTime = 0; if (outputPath.Diverter is TBF.Rig.Uni.Diverter.Diverter) { diverterNr = (outputPath.Diverter as TBF.Rig.Uni.Diverter.Diverter).DiverterNr; } nominalFlow = outputPath.FlowMeter.NominalFlow; maximalFlow = 1.25 * nominalFlow; this.testMethod = method; this.reqFlowLo = requiredFlowLo; this.reqFlowHi = requiredFlowHi; this.totalRefPulses = totalRefPulses; this.massRefPulses = massRefPulses; this.delayBeforeFlowRegulation = delayBeforeFlowRegulation; log.Debug(this.ToString()); } void SendStartCommand() { controlBoard.SyncRoute(); #if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || BADGER_VELKA_TRAT || SLM_50 int flowMeterIdxAndDiv = flowMeterNr + 16 * diverterNr; #elif BADGER_STREDNA_TRAT int flowMeterIdxAndDiv = flowMeterNr + 8 * (diverterNr - 1); #elif FILIPINY_50 int flowMeterIdxAndDiv = flowMeterNr + ((flowMeterNr == 3) ? (4 * (diverterNr - 1)) : 0); #elif GELSENWASSER int flowMeterIdxAndDiv = flowMeterNr + ((diverterNr == 2) ? 16 : 0); #else int flowMeterIdxAndDiv = flowMeterNr; #endif log.InfoFormat("Start() : SendCommand(Cmd.Start, {0}, route, {1}, {1}, {2}, Stop.None)", flowMeterIdxAndDiv, totalRefPulses, testMethod); controlBoard.SendCommand(Command.Start, flowMeterIdxAndDiv, totalRefPulses, massRefPulses, testMethod, StopDevs.None); } /// Start this operation public void Start() { SendStartCommand(); opState = OpState.StartingTest; } /// Run this operation /// /// Event.FlowInDone or Event.FlowOutDone /// public Event Run() { if (opState == OpState.StartingTest) { StatusP statusP = controlBoard.StatusP; log.DebugFormat("statusP = {0} {1} {2} {3}", (((ulong)statusP >> 48) & 0xFFFF).ToString("X4"), (((ulong)statusP >> 32) & 0xFFFF).ToString("X4"), (((ulong)statusP >> 16) & 0xFFFF).ToString("X4"), ((ulong)statusP & 0xFFFF).ToString("X4")); if ((statusP & StatusP.TestInProgress) != 0) { log.Info("Test started"); if (delayBeforeFlowRegulation > 0) { delayStartTime = StateMachine.Time; opState = OpState.WaitingBeforeValveMove; } else { opState = OpState.StartingFlowRegulation; } } else { //opState = OpState.ResendCommand; } return Event.None; } else if (opState == OpState.ResendCommand) { SendStartCommand(); opState = OpState.StartingTest; return Event.None; } else if (opState == OpState.WaitingBeforeValveMove) { if (StateMachine.Time - delayStartTime >= delayBeforeFlowRegulation) { opState = OpState.StartingFlowRegulation; } return Event.None; } else if (opState == OpState.StartingFlowRegulation) { /// /// Done once, issues an appropriate ValveMove(...) command /// if ((reqFlowLo >= reqFlowHi) || (reqFlowLo > maximalFlow) || (reqFlowHi <= 0)) { return Event.OpArgumentError; } log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}", regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi); double freqLo = 2000.0 * reqFlowLo / nominalFlow; double freqHi = 2000.0 * reqFlowHi / nominalFlow; if (regulValve.IsCoax) { controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency, new double[2] { (freqLo + freqHi) / 2, (freqLo + freqHi) / 2 }, regulValveStableTime); } else { controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency, new double[2] { freqLo, freqHi }, regulValveStableTime); } opState = OpState.OpCompleted; return Event.None; } else if (opState == OpState.OpCompleted) { return Event.TestInProgress; } return Event.None; } /// Stop this operation public void Stop() { } } }