/// /// Copyright (c) 2021-2022 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.RegValveLowRegulTimeSaturation { 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); } /// /// 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 uniCB; readonly RegValve regV; readonly int regValveNr; readonly double posLoPct; readonly double posHiPct; readonly int timeout; /// Process values int expireTime; bool positionReached; /// /// Set required water flow. /// Events: FlowSet, FlowTimeOut /// /// Control board device /// Regulation valve component /// Lower limit of the position to be achieved /// Upper limit of the position to be achieved /// Timeout in sec. for setting the flow /// Only Elde.Valve flow are used, other flow on the lists are ignored public SetRegValvePositionOp(UniCB uniCB, RegValve regV, double posLoPct, double posHiPct, int timeout) { this.uniCB = uniCB; if (this.uniCB == null) throw new ArgumentNullException("ctrlBoard"); this.regV = regV as RegValve; if (this.regV == null) throw new ArgumentNullException("regValve is null or not Uni"); this.regValveNr = this.regV.Idx1; this.posLoPct = posLoPct; this.posHiPct = posHiPct; this.timeout = timeout; log.Debug(this.ToString()); } /// /// Set required water flow - no timeout. /// Events: FlowSet /// public SetRegValvePositionOp(UniCB cBoard, RegValve regValve, float posLoPct, float posHiPct) : this(cBoard, regValve, posLoPct, posHiPct, int.MaxValue) { } /// Start this operation 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; } /// /// Run this operation /// /// /// Event.None . . . . . . . busy adjusting position /// Event.PositionReached . . position reached /// Event.OpArgumentError . . invalid required position /// public Event Run() { if (opState == OpState.MoveToPosition) { if (posLoPct >= posHiPct || posLoPct > 100.0 || posHiPct < 0) { return Event.OpArgumentError; } regV.MoveToPosition(false, posLoPct, posHiPct); opState = OpState.CheckState; log.WarnFormat("Run(): RV#={0}, state={1}, MoveToPosition(false, {2:D1}, {3:D1}) issued", regValveNr, opState, posLoPct, posHiPct); return Event.None; } if (positionReached) return Event.PositionReached; double positionPct = regV.Position; log.WarnFormat("Run(): RV#={0}, state={1}, pos={2}%", regValveNr, opState, positionPct.ToString("F1")); if (opState == OpState.CheckState) { 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; } /// Stop this operation public void Stop() { } } }