tbf/TBF/Rig/MettlerToledo/TankDraining.cs
2021-10-26 19:38:09 +02:00

198 lines
6.7 KiB
C#

///
/// 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 abstract 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 GenericDevices.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() { }
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));
}
public override void Initialize()
{
drainValve = TbfComponents.FindComponent(tankDrainingCfg.DrainValve) as IValve;
if (drainValve == null) throw new Exception(string.Format("{0} is missing a drain valve", Name));
evaporationCmpnt = TbfComponents.FindComponent(tankDrainingCfg.Evaporation) as IEvaporation;
openTheDrainValveOp = new Elde.SetValvesOp(StateMachine.ControlBoard, drainValve, null);
closeTheDrainValveOp = new Elde.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);
}
else
{
waitTankContainsMoreThenThld1Op = null;
waitTankContainsMoreThenThld2Op = null;
waitTankContainsMoreThenThld3Op = null;
waitTankContainsMoreThenThld4Op = null;
}
}
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; }
/// <summary>
/// For a given temperature in [°C] returns an evaporation rate in [kg/s]
/// </summary>
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
}
}
}