tbf/TBF/Rig/Uni/RegValve/SetRegValvePositionOp.cs
2021-04-03 00:54:18 +02:00

159 lines
4.7 KiB
C#

///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.Rig.ControlBoard.Uni;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.Uni.RegValve
{
public class SetRegValvePositionOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegValvePositionOp));
public override string ToString()
{
return string.Format("SetRegValvePositionOp({0},{1},{2})", regV.Name, posLoPct, posHiPct);
}
const int CoaxValveNr = 7; /// Coax. valve has number 7
///
/// Internal states of this operation
///
enum OpState
{
Idle = 0,
MoveToPosition, /// Send commend to move to position
CheckState, /// Check RV state by reading statos word
MovingToPosition, /// Command passed OK, RV is moving to a position
}
OpState opState;
/// Set by the constructor
readonly UniCB cBoard;
readonly RegValve regV;
readonly int regValveNr;
readonly double posLoPct;
readonly double posHiPct;
readonly int timeout;
/// Process values
int expireTime;
bool positionReached;
/// <summary>
/// Set required water flow.
/// Events: FlowSet, FlowTimeOut
/// </summary>
/// <param name="cBoard">Control board device</param>
/// <param name="_regulValve">Regulation valve component</param>
/// <param name="posLoPct">Lower limit of the position to be achieved</param>
/// <param name="posHiPct">Upper limit of the position to be achieved</param>
/// <param name="timeout">Timeout in sec. for setting the flow</param>
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
public SetRegValvePositionOp(UniCB cBoard, RegValve regValve, double posLoPct, double posHiPct, int timeout)
{
this.cBoard = cBoard;
if (this.cBoard == null) throw new ArgumentNullException("ctrlBoard");
this.regV = regValve as RegValve;
if (this.regV == null) throw new ArgumentNullException("regValve is null or not Elde");
this.regValveNr = this.regV.Idx1;
this.posLoPct = posLoPct;
this.posHiPct = posHiPct;
this.timeout = timeout;
log.Debug(this.ToString());
}
/// <summary>
/// Set required water flow - no timeout.
/// Events: FlowSet
/// </summary>
public SetRegValvePositionOp(UniCB cBoard, RegValve regValve, float posLoPct, float posHiPct)
: this(cBoard, regValve, posLoPct, posHiPct, int.MaxValue)
{
}
/// <summary>Start this operation</summary>
public void Start()
{
positionReached = false;
expireTime = StateMachine.Time + timeout;
log.InfoFormat("Start(): {0} reqPosLo={1}%, reqPosHi={2}%", regV.Name, posLoPct.ToString("F1"), posHiPct.ToString("F1"));
opState = OpState.MoveToPosition;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None . . . . . . . busy adjusting position
/// Event.PositionReached . . position reached
/// Event.OpArgumentError . . invalid required position
/// </returns>
public Event Run()
{
if (opState == OpState.MoveToPosition)
{
if (posLoPct >= posHiPct || posLoPct > 100.0f || posHiPct < 0)
{
return Event.OpArgumentError;
}
regV.MoveToPosition(false, posLoPct, posHiPct);
opState = OpState.CheckState;
return Event.None;
}
if (positionReached) return Event.PositionReached;
double positionPct = regV.Position;
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regValveNr, positionPct.ToString("F1"));
if (opState == OpState.CheckState)
{
if (regValveNr == CoaxValveNr && (cBoard.State & (ulong)StatusP.CoaxRegValveBusy) == 0)
{
opState = OpState.MoveToPosition;
return Event.None;
}
else if (posLoPct <= positionPct && positionPct <= posHiPct)
{
positionReached = true;
return Event.PositionReached;
}
else if (regV.RegValveState != RegValveState.DacValueRegul)
{
opState = OpState.MoveToPosition; /// Resend move command again in the next run
return Event.None;
}
else
{
opState = OpState.MovingToPosition;
return Event.None;
}
}
else if (StateMachine.Time > expireTime)
{
return Event.RegulValveTimeOut;
}
else if (opState == OpState.MovingToPosition)
{
if (posLoPct <= positionPct && positionPct <= posHiPct)
{
positionReached = true;
return Event.PositionReached;
}
return Event.None;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}