/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using log4net; namespace TBF.BenchControl.Elde { 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, refPulses); } /// Set by the constructor readonly ControlBoardDev controlBoard; readonly Elde.RegulValve.RegulValve regulValve; readonly int regulValveNr; readonly int flowMeterNr; readonly float nominalFlow; readonly float reqFlowLo; readonly float reqFlowHi; readonly float reqFlowAve; readonly float pidCoef; readonly int refPulses; /// Number of reference pulses for a complete test readonly TestMethods testMethod; readonly float filterConstant; readonly int diverterNr; bool started = false; /// /// Internal states of this operation /// enum OpState { StartingTest, TestStarted, ValveMoveToFlow, OpCompleted, } OpState opState; /// /// 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(ControlBoardDev controlBoard, OutputPath outputPath, TestMethods method, float requiredFlowLo, float requiredFlowHi, int refPulses, float filterConstant) { if (controlBoard == null) throw new ArgumentNullException("controlBoardDev"); this.controlBoard = controlBoard; if (outputPath.FlowMeter is Elde.FlowMeter.FlowMeter) { flowMeterNr = (outputPath.FlowMeter as Elde.FlowMeter.FlowMeter).Idx1; } else if (outputPath.FlowMeter is Elde.FlowMeterTwins.FlowMeter) { flowMeterNr = 0; } else { throw new ArgumentException("flowMeter is null or is not Elde"); } regulValve = outputPath.RegulValve as Elde.RegulValve.RegulValve; if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde"); regulValveNr = this.regulValve.Idx1; if (outputPath.Diverter is Elde.Diverter.Diverter) { diverterNr = (outputPath.Diverter as Elde.Diverter.Diverter).AdcNr - 4; } nominalFlow = outputPath.FlowMeter.NominalFlow; this.reqFlowLo = requiredFlowLo; this.reqFlowHi = requiredFlowHi; this.reqFlowAve = (reqFlowLo + reqFlowHi) / 2.0f; this.pidCoef = outputPath.PidCoef; this.refPulses = refPulses; this.testMethod = method; this.filterConstant = filterConstant; log.Debug(this.ToString()); } /// Start this operation public void Start() { controlBoard.SyncRoute(); #if IPERLST || BADGER_VELKA_TRAT int flowMeterIdxAndDiv = flowMeterNr + 16 * diverterNr; #else int flowMeterIdxAndDiv = flowMeterNr; #endif controlBoard.SendCommand(Command.Start, flowMeterIdxAndDiv, controlBoard.Route, refPulses, refPulses, testMethod, filterConstant, 20, 0, StopDevs.None); 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 (0 != (statusP & StatusP.TestInProgress)) { log.Info("Test started"); opState = OpState.TestStarted; } return Event.None; } else if (opState == OpState.TestStarted) { /// /// Done once, issues an appropriate ValveMove(...) command /// if (reqFlowLo >= reqFlowHi || reqFlowLo > nominalFlow || reqFlowHi <= 0) { return Event.OpArgumentError; } log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}", regulValveNr, flowMeterNr, reqFlowLo, reqFlowHi); float freqLo = 2000.0f * reqFlowLo / nominalFlow; float freqHi = 2000.0f * reqFlowHi / nominalFlow; controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency, new float[2] { freqLo, freqHi }, regulValve.StableTime); opState = OpState.OpCompleted; return Event.None; } else if (opState == OpState.OpCompleted) { return Event.MeasurementStarted; } return Event.None; } /// Stop this operation public void Stop() { } } }