tbf/TBF/BenchControl/Elde/StartMeasurementOp.cs

237 lines
8.9 KiB
C#

///
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.BenchControl.GenericDevices;
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, totalRefPulses); }
/// Set by the constructor
readonly ControlBoardDev controlBoard;
readonly IRegulValve 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
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="method">Test method</param>
/// <param name="totalRefPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public StartMeasurementOp(ControlBoardDev controlBoard, OutputPath outputPath, TestMethods method,
double requiredFlowLo, double requiredFlowHi, int refPulses, int delayBeforeFlowRegulation = 0)
: this(controlBoard, outputPath, method, requiredFlowLo, requiredFlowHi, refPulses, refPulses, delayBeforeFlowRegulation)
{
}
/// <summary>
/// Starts the measurement.
/// Events: MeasurementStarted
/// </summary>
/// <param name="controlBoard">Control board component reference</param>
/// <param name="outputPath">Specifies used components</param>
/// <param name="method">Test method</param>
/// <param name="refPulses">Test duration in number of reference flowmeter pulses</param>
/// <param name="filterConstant">Specifies filter for watermeter pulses</param>
public StartMeasurementOp(ControlBoardDev 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.RegulValve;
if (regulValve is Elde.RegulValve.RegulValve)
{
Elde.RegulValve.RegulValve rv = outputPath.RegulValve as Elde.RegulValve.RegulValve;
regulValveNr = rv.Idx1;
regulValveStableTime = rv.StableTime;
}
else if (regulValve is Elde.RegulValveCoax.RegulValve)
{
Elde.RegulValveCoax.RegulValve rv = outputPath.RegulValve as Elde.RegulValveCoax.RegulValve;
regulValveNr = rv.Idx1;
regulValveStableTime = rv.StableTime;
}
else if (!(regulValve is Dummy.RegulValve.RegulValve))
{
throw new ArgumentNullException("Regulation valve is not compatible with Elde Control Board");
}
if (outputPath.Diverter is Elde.Diverter.Diverter)
{
diverterNr = (outputPath.Diverter as Elde.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()
{
#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);
}
/// <summary>Start this operation</summary>
public void Start()
{
SendStartCommand();
opState = OpState.StartingTest;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
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 float[2] { (float)((freqLo + freqHi) / 2), (float)((freqLo + freqHi) / 2) },
regulValveStableTime);
}
else
{
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
new float[2] { (float)freqLo, (float)freqHi },
regulValveStableTime);
}
opState = OpState.OpCompleted;
return Event.None;
}
else if (opState == OpState.OpCompleted)
{
return Event.MeasurementStarted;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}