/// /// Copyright (c) 2017-2018 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using TBF.Rig.GenericDevices; using TBF.Resources; namespace TBF.Rig.MettlerToledo { public enum DrainState { None, OpeningDV_Start, OpeningDV_Run, OpeningDV_Stop, Draining, ClosingDV_Start, ClosingDV_Run, ClosingDV_Stop, TankClosed, } public class TankDraining : ComponentBase, ITankDraining, ISequenceCondition { private static readonly ILog log = LogManager.GetLogger(typeof(TankDraining)); readonly GenericDevices.ITankDrainingCfg tankDrainingCfg; bool hasDrainValve { get { return !string.IsNullOrEmpty(tankDrainingCfg.DrainValve); } } /// Available in UI (unlike 'drainValve') IValve drainValve; public IValve DrainValve { get { return drainValve; } } IEvaporation evaporationCmpnt; IOperation openTheDrainValveOp; IOperation closeTheDrainValveOp; IOperation waitTankIsEmptyOp; IOperation waitTankContainsMoreThenThld1Op; IOperation waitTankContainsMoreThenThld2Op; IOperation waitTankContainsMoreThenThld3Op; IOperation waitTankContainsMoreThenThld4Op; DrainState drainState; public TankDraining() : base() { openTheDrainValveOp = null; closeTheDrainValveOp = null; waitTankIsEmptyOp = null; waitTankContainsMoreThenThld1Op = null; waitTankContainsMoreThenThld2Op = null; waitTankContainsMoreThenThld3Op = null; waitTankContainsMoreThenThld4Op = null; } public TankDraining(Generic.IComponentCfg cfg) : base(cfg) { tankDrainingCfg = cfg as GenericDevices.ITankDrainingCfg; if (tankDrainingCfg == null) throw new Exception(string.Format("Cannot create component {0}", cfg.Name)); openTheDrainValveOp = null; closeTheDrainValveOp = null; waitTankIsEmptyOp = null; waitTankContainsMoreThenThld1Op = null; waitTankContainsMoreThenThld2Op = null; waitTankContainsMoreThenThld3Op = null; waitTankContainsMoreThenThld4Op = null; } public override void Initialize() { drainValve = TbfComponents.FindComponent(tankDrainingCfg.DrainValve) as IValve; evaporationCmpnt = TbfComponents.FindComponent(tankDrainingCfg.Evaporation) as IEvaporation; if (drainValve == null) throw new Exception(string.Format("{0} is missing a drain valve", Name)); openTheDrainValveOp = new BuiltIn.SetValvesOp(StateMachine.ControlBoard, drainValve, null); closeTheDrainValveOp = new BuiltIn.SetValvesOp(StateMachine.ControlBoard, null, drainValve); waitTankIsEmptyOp = new WaitTankEmptyOp(this); Various.TankWithLevelMsrmnt.TankCfg tankCfg = tankDrainingCfg as Various.TankWithLevelMsrmnt.TankCfg; if (tankCfg != null) { waitTankContainsMoreThenThld1Op = new WaitTankContainsMoreThenOp(this, tankCfg.ThldLevel1); waitTankContainsMoreThenThld2Op = new WaitTankContainsMoreThenOp(this, tankCfg.ThldLevel2); waitTankContainsMoreThenThld3Op = new WaitTankContainsMoreThenOp(this, tankCfg.ThldLevel3); waitTankContainsMoreThenThld4Op = new WaitTankContainsMoreThenOp(this, tankCfg.ThldLevel4); } } protected void RunBefore() { switch (drainState) { case DrainState.OpeningDV_Start: openTheDrainValveOp.Start(); drainState = DrainState.OpeningDV_Run; return; case DrainState.OpeningDV_Run: if (openTheDrainValveOp.Run() == Event.ValvesSet) drainState = DrainState.OpeningDV_Stop; return; case DrainState.OpeningDV_Stop: openTheDrainValveOp.Stop(); return; case DrainState.Draining: if (IsEmpty()) drainState = DrainState.ClosingDV_Start; return; case DrainState.ClosingDV_Start: closeTheDrainValveOp.Start(); drainState = DrainState.ClosingDV_Run; return; case DrainState.ClosingDV_Run: if (closeTheDrainValveOp.Run() == Event.ValvesSet) drainState = DrainState.ClosingDV_Stop; return; case DrainState.ClosingDV_Stop: closeTheDrainValveOp.Stop(); return; default: return; } } protected void RunAfter() { } /// Not used public virtual string GetName() { return string.Empty; } public virtual bool IsEmpty() { return false; } public virtual bool ContainsMoreThen(float thld) { return thld == 0; } /// /// For a given temperature in [°C] returns an evaporation rate in [kg/s] /// public double EvaporationRate(double temperature) { return (evaporationCmpnt != null) ? evaporationCmpnt.EvaporationRate(temperature) : 0; } public int ConditionsCount { get { return hasDrainValve ? 3 : ((tankDrainingCfg is Various.TankWithLevelMsrmnt.TankCfg) ? 4 : 0); } } /// Strings are added to the combo-box for transition sequence condition selection public string ConditionName(int i) { if (hasDrainValve) { switch (i) { case 0: return string.Format(Strings._0_open_the_drain_valve, Name); case 1: return string.Format(Strings._0_close_the_drain_valve, Name); case 2: return string.Format(Strings._0_wait_until_the_tank_is_empty, Name); } } else if (tankDrainingCfg is Various.TankWithLevelMsrmnt.TankCfg) { var tankCfg = tankDrainingCfg as Various.TankWithLevelMsrmnt.TankCfg; switch (i) { case 0: return string.Format(Strings._0_wait_until_tank_contains_more_then_1_l, Name, tankCfg.ThldLevel1); case 1: return string.Format(Strings._0_wait_until_tank_contains_more_then_1_l, Name, tankCfg.ThldLevel2); case 2: return string.Format(Strings._0_wait_until_tank_contains_more_then_1_l, Name, tankCfg.ThldLevel3); case 3: return string.Format(Strings._0_wait_until_tank_contains_more_then_1_l, Name, tankCfg.ThldLevel4); } } return string.Empty; // Default } /// Operation to be executed as a part of a transition sequence public IOperation ConditionOp(int i) { if (hasDrainValve) { switch (i) { case 0: return openTheDrainValveOp; case 1: return closeTheDrainValveOp; case 2: return waitTankIsEmptyOp; } } else if (tankDrainingCfg is Various.TankWithLevelMsrmnt.TankCfg) { switch (i) { case 0: return waitTankContainsMoreThenThld1Op; case 1: return waitTankContainsMoreThenThld2Op; case 2: return waitTankContainsMoreThenThld3Op; case 3: return waitTankContainsMoreThenThld4Op; } } return null; /// Default } } }