Uni.RegValveAnalog and Uni.RegValveTandem added, several Elde components removed.
This commit is contained in:
@@ -32,6 +32,7 @@ namespace TBF.Rig.Uni.RegValve
|
||||
public int DacValueOpen { get { return regValveCfg.AdcValueOpen; } } /// 0 .. 1023
|
||||
public int StableTime { get { return regValveCfg.StableTime; } } /// 0=200ms, step=50ms, max. 1500ms (max.26)
|
||||
public int FlowStableSec { get { return regValveCfg.FlowStableSec; } } /// 0 .. 60 sec
|
||||
public bool StoredPositionReuse { get { return regValveCfg.StoredPositionReuse; } }
|
||||
///
|
||||
public bool IsCoax { get { return false; } }
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Metering Systems
|
||||
///
|
||||
using System;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValve
|
||||
{
|
||||
public class RegulValveCfgChangeArgs : EventArgs
|
||||
{
|
||||
public CfgChangeCmd Command;
|
||||
public Generic.IComponentCfg Cfg;
|
||||
|
||||
public RegulValveCfgChangeArgs(CfgChangeCmd command, Generic.IComponentCfg cfg)
|
||||
{
|
||||
Command = command;
|
||||
Cfg = cfg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
///
|
||||
/// 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.RegValveAnalog
|
||||
{
|
||||
public class ChangeRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ChangeRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("ChangeRegulValvePositionOp({0},{1}s)", regValve.Name, timePulseSec.ToString("F2"));
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly UniCB uniCB;
|
||||
readonly RegValve regValve;
|
||||
readonly double timePulseSec;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="uniCB">Control board device</param>
|
||||
/// <param name="regValve">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 ChangeRegulValvePositionOp(UniCB uniCB, RegValve regValve, double timePulseSec)
|
||||
{
|
||||
if (uniCB == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.uniCB = uniCB;
|
||||
|
||||
this.regValve = regValve as RegValve;
|
||||
if (this.regValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
|
||||
this.timePulseSec = timePulseSec;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
double positionPct = regValve.Position;
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regValve.Idx1, positionPct.ToString("F1"));
|
||||
|
||||
uniCB.RegVlvIncrMove(false, regValve.Idx1, timePulseSec);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.SetFlowDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
double positionPct = regValve.Position;
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regValve.Idx1, positionPct.ToString("F1"));
|
||||
|
||||
return Event.PositionReached;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "RegValveAnalog"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { RegValve.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new RegValve(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new RegValve(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new RegValveCfg("RV", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(RegValveCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.ControlBoard.Uni;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
public class RegValve : ComponentBase, GenericDevices.IRegValve, IDrawingItCmpntWithSetpoint
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RegValve));
|
||||
public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); }
|
||||
|
||||
|
||||
readonly RegValveCfg regValveCfg;
|
||||
public ValveCategory Category { get { return regValveCfg.Category; } }
|
||||
public int Idx1 { get { return regValveCfg.Idx1; } } /// 1..7
|
||||
public int StableTime { get { return regValveCfg.StableTime; } } /// 0=200ms, step=50ms, max. 1500ms (max.26)
|
||||
public int FlowStableSec { get { return regValveCfg.FlowStableSec; } } /// 0..60 sec
|
||||
public bool StoredPositionReuse { get { return regValveCfg.StoredPositionReuse; } }
|
||||
|
||||
public IDrawingItem DrawingItem { get { return regValveCfg as IDrawingItem; } }
|
||||
|
||||
IDictionary<double, double> dict;
|
||||
public IDictionary<double, double> Dict { get { return dict; } }
|
||||
|
||||
readonly UniCB uniCB;
|
||||
|
||||
///
|
||||
public bool IsCoax { get { return true; } }
|
||||
///
|
||||
public double Position
|
||||
{
|
||||
get {
|
||||
return 50.0; // TODO: was return uniCB.RValvePosition(Idx1);
|
||||
}
|
||||
}
|
||||
///
|
||||
public double SetpointVal
|
||||
{
|
||||
get { return Position; }
|
||||
set { } // TODO
|
||||
}
|
||||
///
|
||||
public void IncreaseSetpoint()
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
///
|
||||
public void DecreaseSetpoint()
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
|
||||
|
||||
public RegValve()
|
||||
{
|
||||
}
|
||||
|
||||
public RegValve(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
regValveCfg = cfg as RegValveCfg;
|
||||
|
||||
uniCB = TbfComponents.FindComponent(cfg.ParentName, components) as UniCB;
|
||||
if (uniCB == null) throw new Exception("Cannot find " + Name + " parent");
|
||||
|
||||
this.dict = new Dictionary<double, double>();
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="qFrom">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="qTo">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowOp(GenericDevices.IFlowMeter flowMeter, double qFrom, double qTo, DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
return new SetFlowOp(uniCB, this, flowMeter, qFrom, qTo, measuredFlow, regValveCfg.ReTryCommands, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances. Leave the measurement running.
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="qFrom">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="qTo">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowAndMeasureOp(GenericDevices.IFlowMeter flowMeter, double qFrom, double qTo,
|
||||
DoubleBox measuredFlow, int timeout, float filterConstant)
|
||||
{
|
||||
return new SetFlowOp(uniCB, this, flowMeter, qFrom, qTo, measuredFlow, regValveCfg.ReTryCommands, timeout, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the regulation valve to a required position
|
||||
/// Events: Event.None
|
||||
/// </summary>
|
||||
/// <param name="flowLo">Lower limit of the required valve position in [%]</param>
|
||||
/// <param name="flowLo">Higher limit of the required valve position in [%]</param>
|
||||
/// <returns>SetPositionOp instance</returns>
|
||||
public IOperation SetRegulValvePositionOp(double pctLo, double pctHi, int timeoutMs)
|
||||
{
|
||||
return new SetRegulValvePositionOp(uniCB, this, pctLo, pctHi, timeoutMs);
|
||||
}
|
||||
|
||||
public IOperation ChangeRegulValvePositionOp(double timePulseSec)
|
||||
{
|
||||
return new ChangeRegulValvePositionOp(uniCB, this, timePulseSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using SchematicDrawing;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
public class RegValveCfg : ComponentCfgBase, IChildComponentCfg, IDrawingItemWithSetpoint
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RegValveCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new RegValveCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public int Idx1; /// 1..8
|
||||
public ValveCategory Category; /// Feeding, Output or All
|
||||
public int StableTimeMs; /// 200..1500 ms
|
||||
public int FlowStableSec; /// 0..60 sec
|
||||
public bool StoredPositionReuse; /// true = store and re-use previous regulation valve positions
|
||||
public bool ReTryCommands;
|
||||
|
||||
/// Schematic drawing info
|
||||
public Shape Shape { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
public Sz Sz { get; set; }
|
||||
public Orient Orient { get; set; }
|
||||
public bool Flip { get; set; }
|
||||
public int LblX { get; set; }
|
||||
public int LblY { get; set; }
|
||||
public Orient LblOrient { get; set; }
|
||||
public int SetpX { get; set; }
|
||||
public int SetpY { get; set; }
|
||||
public Orient SetpOrient { get; set; }
|
||||
public string SetpFormat { get; set; }
|
||||
public Config.Unit SetpUnit { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
public IList<GNode> GNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec.
|
||||
/// </summary>
|
||||
public int StableTime { get { return (StableTimeMs - 200) / 50; } }
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
RegValveCfg()
|
||||
{
|
||||
GNodes = new List<GNode>();
|
||||
}
|
||||
|
||||
public RegValveCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Shape = Shape.RegV;
|
||||
Sz = Sz.M;
|
||||
SetpFormat = "{0:F0} %";
|
||||
SetpUnit = Config.Unit.Pct;
|
||||
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = "CB";
|
||||
Category = ValveCategory.Output;
|
||||
Idx1 = 1;
|
||||
StableTimeMs = 500;
|
||||
FlowStableSec = 5;
|
||||
StoredPositionReuse = false;
|
||||
ReTryCommands = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0} ({1}), Idx1={2}, Cat.={3}, StabTm={4}ms, FlowStable={5}s, PosReuse={6}, ReTryCmds={7}",
|
||||
Name,
|
||||
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
|
||||
Idx1,
|
||||
Category,
|
||||
StableTimeMs,
|
||||
FlowStableSec,
|
||||
StoredPositionReuse,
|
||||
ReTryCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
public partial class RegValveCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return true; } }
|
||||
|
||||
RegValveCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as RegValveCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public RegValveCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void RegulationValveCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is ControlBoard.Legacy.Factory)
|
||||
{
|
||||
parentNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
categoryComboBox.Items.Add(ValveCategory.Feeding.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Output.ToString());
|
||||
|
||||
for (Config.Unit units = 0; units < global::Config.Unit.Count; units++)
|
||||
{
|
||||
if (global::Config.Units.IsQuantity(units, global::Config.Quantity.Error))
|
||||
{
|
||||
unitsComboBox.Items.Add(units.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
}
|
||||
|
||||
void Redraw()
|
||||
{
|
||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
|
||||
categoryComboBox.Text = config.Category.ToString();
|
||||
positionTextBox.Text = config.Idx1.ToString();
|
||||
stableTimeTextBox.Text = config.StableTimeMs.ToString();
|
||||
flowStableSecTextBox.Text = config.FlowStableSec.ToString();
|
||||
storedPosReuseCheckBox.Checked = config.StoredPositionReuse;
|
||||
reTryCommandsCheckBox.Checked = config.ReTryCommands;
|
||||
formatTextBox.Text = config.SetpFormat;
|
||||
unitsComboBox.Text = config.SetpUnit.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
parentNameComboBox.Enabled = true;
|
||||
categoryComboBox.Enabled = true;
|
||||
positionTextBox.Enabled = true;
|
||||
stableTimeTextBox.Enabled = true;
|
||||
flowStableSecTextBox.Enabled = true;
|
||||
storedPosReuseCheckBox.Enabled = true;
|
||||
reTryCommandsCheckBox.Enabled = true;
|
||||
formatTextBox.Enabled = true;
|
||||
unitsComboBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
int dummy;
|
||||
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Parent Name'";
|
||||
}
|
||||
if (!categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString()) &&
|
||||
!categoryComboBox.Text.Equals(ValveCategory.Output.ToString()))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Category'";
|
||||
}
|
||||
if (!int.TryParse(positionTextBox.Text, out dummy) || dummy < 1 || dummy > 8)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Position' should be between 1 and 8";
|
||||
}
|
||||
if (!int.TryParse(stableTimeTextBox.Text, out dummy) || dummy < 200 || dummy > 1500 || (dummy % 50) != 0)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Stable time' should be between 200 and 1500 ms in 50 ms steps";
|
||||
}
|
||||
if (!int.TryParse(flowStableSecTextBox.Text, out dummy) || dummy < 0 || dummy > 60)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Flow stable' should be between 0 and 60 sec";
|
||||
}
|
||||
if (!unitsComboBox.Items.Contains(unitsComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Units'";
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
///
|
||||
if (!config.Name.Equals(nameTextBox.Text))
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
string parentname = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
|
||||
if (!config.ParentName.Equals(parentname))
|
||||
{
|
||||
config.ParentName = parentname;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
ValveCategory newCategory;
|
||||
if (categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString())) newCategory = ValveCategory.Feeding;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Output.ToString())) newCategory = ValveCategory.Output;
|
||||
else newCategory = ValveCategory.None;
|
||||
if (newCategory != config.Category)
|
||||
{
|
||||
config.Category = newCategory;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
int tmp = int.Parse(positionTextBox.Text);
|
||||
if (config.Idx1 != tmp)
|
||||
{
|
||||
config.Idx1 = tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
tmp = int.Parse(stableTimeTextBox.Text);
|
||||
if (config.StableTimeMs != tmp)
|
||||
{
|
||||
config.StableTimeMs = tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
tmp = int.Parse(flowStableSecTextBox.Text);
|
||||
if (config.FlowStableSec != tmp)
|
||||
{
|
||||
config.FlowStableSec = tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
bool btmp = storedPosReuseCheckBox.Checked;
|
||||
if (config.StoredPositionReuse != btmp)
|
||||
{
|
||||
config.StoredPositionReuse = btmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
btmp = reTryCommandsCheckBox.Checked;
|
||||
if (config.ReTryCommands != btmp)
|
||||
{
|
||||
config.ReTryCommands = btmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
config.SetpUnit = global::Config.Unit.None;
|
||||
for (Config.Unit units = 0; units < global::Config.Unit.Count; units++)
|
||||
{
|
||||
if (unitsComboBox.Text == units.ToString())
|
||||
{
|
||||
config.SetpUnit = units;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private void openButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
|
||||
private void closeButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
/// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
partial class RegValveCfgCtrl
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.positionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.positionLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.storedPosReuseCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.stableTimeTextBox = new System.Windows.Forms.TextBox();
|
||||
this.stableTimeLabel = new System.Windows.Forms.Label();
|
||||
this.flowStableSecTextBox = new System.Windows.Forms.TextBox();
|
||||
this.flowStableSecLabel = new System.Windows.Forms.Label();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.closeButton = new System.Windows.Forms.Button();
|
||||
this.openButton = new System.Windows.Forms.Button();
|
||||
this.categoryComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.categoryLabel = new System.Windows.Forms.Label();
|
||||
this.reTryCommandsCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.unitsComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.unitsLabel = new System.Windows.Forms.Label();
|
||||
this.formatTextBox = new System.Windows.Forms.TextBox();
|
||||
this.formatLabel = new System.Windows.Forms.Label();
|
||||
this.groupBox3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// positionTextBox
|
||||
//
|
||||
this.positionTextBox.Enabled = false;
|
||||
this.positionTextBox.Location = new System.Drawing.Point(138, 115);
|
||||
this.positionTextBox.Name = "positionTextBox";
|
||||
this.positionTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.positionTextBox.TabIndex = 8;
|
||||
//
|
||||
// positionLabel
|
||||
//
|
||||
this.positionLabel.AutoSize = true;
|
||||
this.positionLabel.Location = new System.Drawing.Point(28, 118);
|
||||
this.positionLabel.Name = "positionLabel";
|
||||
this.positionLabel.Size = new System.Drawing.Size(18, 13);
|
||||
this.positionLabel.TabIndex = 7;
|
||||
this.positionLabel.Text = "ID";
|
||||
//
|
||||
// parentNameLabel
|
||||
//
|
||||
this.parentNameLabel.AutoSize = true;
|
||||
this.parentNameLabel.Location = new System.Drawing.Point(28, 68);
|
||||
this.parentNameLabel.Name = "parentNameLabel";
|
||||
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
|
||||
this.parentNameLabel.TabIndex = 3;
|
||||
this.parentNameLabel.Text = "Parent Name";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(138, 41);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(28, 44);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 1;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(135, 14);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentName";
|
||||
//
|
||||
// parentNameComboBox
|
||||
//
|
||||
this.parentNameComboBox.Enabled = false;
|
||||
this.parentNameComboBox.FormattingEnabled = true;
|
||||
this.parentNameComboBox.Location = new System.Drawing.Point(138, 65);
|
||||
this.parentNameComboBox.Name = "parentNameComboBox";
|
||||
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.parentNameComboBox.TabIndex = 4;
|
||||
//
|
||||
// storedPosReuseCheckBox
|
||||
//
|
||||
this.storedPosReuseCheckBox.AutoSize = true;
|
||||
this.storedPosReuseCheckBox.Enabled = false;
|
||||
this.storedPosReuseCheckBox.Location = new System.Drawing.Point(31, 192);
|
||||
this.storedPosReuseCheckBox.Name = "storedPosReuseCheckBox";
|
||||
this.storedPosReuseCheckBox.Size = new System.Drawing.Size(162, 17);
|
||||
this.storedPosReuseCheckBox.TabIndex = 17;
|
||||
this.storedPosReuseCheckBox.Text = "Enable stored position re-use";
|
||||
this.storedPosReuseCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// stableTimeTextBox
|
||||
//
|
||||
this.stableTimeTextBox.Enabled = false;
|
||||
this.stableTimeTextBox.Location = new System.Drawing.Point(138, 139);
|
||||
this.stableTimeTextBox.Name = "stableTimeTextBox";
|
||||
this.stableTimeTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.stableTimeTextBox.TabIndex = 14;
|
||||
//
|
||||
// stableTimeLabel
|
||||
//
|
||||
this.stableTimeLabel.AutoSize = true;
|
||||
this.stableTimeLabel.Location = new System.Drawing.Point(28, 142);
|
||||
this.stableTimeLabel.Name = "stableTimeLabel";
|
||||
this.stableTimeLabel.Size = new System.Drawing.Size(81, 13);
|
||||
this.stableTimeLabel.TabIndex = 13;
|
||||
this.stableTimeLabel.Text = "Stable time [ms]";
|
||||
//
|
||||
// flowStableSecTextBox
|
||||
//
|
||||
this.flowStableSecTextBox.Enabled = false;
|
||||
this.flowStableSecTextBox.Location = new System.Drawing.Point(138, 163);
|
||||
this.flowStableSecTextBox.Name = "flowStableSecTextBox";
|
||||
this.flowStableSecTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.flowStableSecTextBox.TabIndex = 16;
|
||||
//
|
||||
// flowStableSecLabel
|
||||
//
|
||||
this.flowStableSecLabel.AutoSize = true;
|
||||
this.flowStableSecLabel.Location = new System.Drawing.Point(28, 166);
|
||||
this.flowStableSecLabel.Name = "flowStableSecLabel";
|
||||
this.flowStableSecLabel.Size = new System.Drawing.Size(74, 13);
|
||||
this.flowStableSecLabel.TabIndex = 15;
|
||||
this.flowStableSecLabel.Text = "Flow stable [s]";
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.closeButton);
|
||||
this.groupBox3.Controls.Add(this.openButton);
|
||||
this.groupBox3.Location = new System.Drawing.Point(10, 527);
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.Size = new System.Drawing.Size(280, 60);
|
||||
this.groupBox3.TabIndex = 21;
|
||||
this.groupBox3.TabStop = false;
|
||||
this.groupBox3.Text = "Regulation valve";
|
||||
//
|
||||
// closeButton
|
||||
//
|
||||
this.closeButton.Location = new System.Drawing.Point(14, 19);
|
||||
this.closeButton.Name = "closeButton";
|
||||
this.closeButton.Size = new System.Drawing.Size(107, 28);
|
||||
this.closeButton.TabIndex = 1;
|
||||
this.closeButton.Text = "Close";
|
||||
this.closeButton.UseVisualStyleBackColor = true;
|
||||
this.closeButton.Click += new System.EventHandler(this.closeButton_Click);
|
||||
//
|
||||
// openButton
|
||||
//
|
||||
this.openButton.Location = new System.Drawing.Point(160, 19);
|
||||
this.openButton.Name = "openButton";
|
||||
this.openButton.Size = new System.Drawing.Size(107, 28);
|
||||
this.openButton.TabIndex = 0;
|
||||
this.openButton.Text = "Open";
|
||||
this.openButton.UseVisualStyleBackColor = true;
|
||||
this.openButton.Click += new System.EventHandler(this.openButton_Click);
|
||||
//
|
||||
// categoryComboBox
|
||||
//
|
||||
this.categoryComboBox.Enabled = false;
|
||||
this.categoryComboBox.FormattingEnabled = true;
|
||||
this.categoryComboBox.Location = new System.Drawing.Point(138, 90);
|
||||
this.categoryComboBox.Name = "categoryComboBox";
|
||||
this.categoryComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.categoryComboBox.TabIndex = 6;
|
||||
//
|
||||
// categoryLabel
|
||||
//
|
||||
this.categoryLabel.AutoSize = true;
|
||||
this.categoryLabel.Location = new System.Drawing.Point(28, 93);
|
||||
this.categoryLabel.Name = "categoryLabel";
|
||||
this.categoryLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.categoryLabel.TabIndex = 5;
|
||||
this.categoryLabel.Text = "Category";
|
||||
//
|
||||
// reTryCommandsCheckBox
|
||||
//
|
||||
this.reTryCommandsCheckBox.AutoSize = true;
|
||||
this.reTryCommandsCheckBox.Enabled = false;
|
||||
this.reTryCommandsCheckBox.Location = new System.Drawing.Point(31, 215);
|
||||
this.reTryCommandsCheckBox.Name = "reTryCommandsCheckBox";
|
||||
this.reTryCommandsCheckBox.Size = new System.Drawing.Size(108, 17);
|
||||
this.reTryCommandsCheckBox.TabIndex = 18;
|
||||
this.reTryCommandsCheckBox.Text = "Re-try commands";
|
||||
this.reTryCommandsCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// unitsComboBox
|
||||
//
|
||||
this.unitsComboBox.Enabled = false;
|
||||
this.unitsComboBox.FormattingEnabled = true;
|
||||
this.unitsComboBox.Location = new System.Drawing.Point(138, 264);
|
||||
this.unitsComboBox.Name = "unitsComboBox";
|
||||
this.unitsComboBox.Size = new System.Drawing.Size(80, 21);
|
||||
this.unitsComboBox.TabIndex = 32;
|
||||
//
|
||||
// unitsLabel
|
||||
//
|
||||
this.unitsLabel.AutoSize = true;
|
||||
this.unitsLabel.Location = new System.Drawing.Point(28, 267);
|
||||
this.unitsLabel.Name = "unitsLabel";
|
||||
this.unitsLabel.Size = new System.Drawing.Size(71, 13);
|
||||
this.unitsLabel.TabIndex = 31;
|
||||
this.unitsLabel.Text = "Setpoint units";
|
||||
//
|
||||
// formatTextBox
|
||||
//
|
||||
this.formatTextBox.Enabled = false;
|
||||
this.formatTextBox.Location = new System.Drawing.Point(138, 240);
|
||||
this.formatTextBox.Name = "formatTextBox";
|
||||
this.formatTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.formatTextBox.TabIndex = 30;
|
||||
//
|
||||
// formatLabel
|
||||
//
|
||||
this.formatLabel.AutoSize = true;
|
||||
this.formatLabel.Location = new System.Drawing.Point(28, 243);
|
||||
this.formatLabel.Name = "formatLabel";
|
||||
this.formatLabel.Size = new System.Drawing.Size(78, 13);
|
||||
this.formatLabel.TabIndex = 29;
|
||||
this.formatLabel.Text = "Setpoint format";
|
||||
//
|
||||
// RegulValveCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.unitsComboBox);
|
||||
this.Controls.Add(this.unitsLabel);
|
||||
this.Controls.Add(this.formatTextBox);
|
||||
this.Controls.Add(this.formatLabel);
|
||||
this.Controls.Add(this.reTryCommandsCheckBox);
|
||||
this.Controls.Add(this.categoryComboBox);
|
||||
this.Controls.Add(this.categoryLabel);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.flowStableSecTextBox);
|
||||
this.Controls.Add(this.flowStableSecLabel);
|
||||
this.Controls.Add(this.stableTimeTextBox);
|
||||
this.Controls.Add(this.stableTimeLabel);
|
||||
this.Controls.Add(this.storedPosReuseCheckBox);
|
||||
this.Controls.Add(this.parentNameComboBox);
|
||||
this.Controls.Add(this.positionTextBox);
|
||||
this.Controls.Add(this.positionLabel);
|
||||
this.Controls.Add(this.parentNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "RegulValveCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 700);
|
||||
this.Load += new System.EventHandler(this.RegulationValveCfgCtrl_Load);
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox positionTextBox;
|
||||
private System.Windows.Forms.Label positionLabel;
|
||||
private System.Windows.Forms.Label parentNameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.ComboBox parentNameComboBox;
|
||||
private System.Windows.Forms.CheckBox storedPosReuseCheckBox;
|
||||
private System.Windows.Forms.TextBox stableTimeTextBox;
|
||||
private System.Windows.Forms.Label stableTimeLabel;
|
||||
private System.Windows.Forms.TextBox flowStableSecTextBox;
|
||||
private System.Windows.Forms.Label flowStableSecLabel;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.Button closeButton;
|
||||
private System.Windows.Forms.Button openButton;
|
||||
private System.Windows.Forms.ComboBox categoryComboBox;
|
||||
private System.Windows.Forms.Label categoryLabel;
|
||||
private System.Windows.Forms.CheckBox reTryCommandsCheckBox;
|
||||
private System.Windows.Forms.ComboBox unitsComboBox;
|
||||
private System.Windows.Forms.Label unitsLabel;
|
||||
private System.Windows.Forms.TextBox formatTextBox;
|
||||
private System.Windows.Forms.Label formatLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,479 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard.Uni;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveAnalog
|
||||
{
|
||||
public class SetFlowOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetFlowOp({0}, Qfrom={1}, Qto={2})", regValve.Name, finalReqFlowLo, finalReqFlowHi);
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly UniCB uniCB;
|
||||
readonly RegValve regValve;
|
||||
readonly int flowMeterId;
|
||||
readonly double finalReqFlowLo;
|
||||
readonly double finalReqFlowHi;
|
||||
readonly double reqFlowAve;
|
||||
readonly int timeout;
|
||||
readonly bool leaveMeasurementRunning;
|
||||
readonly bool reTryCommands;
|
||||
|
||||
readonly double nominalFlow;
|
||||
readonly double maximalFlow;
|
||||
|
||||
///
|
||||
/// Internal states of this operation
|
||||
///
|
||||
enum OpState
|
||||
{
|
||||
Idle = 0,
|
||||
ValveMoveToPosition1, /// Wait 1 takt
|
||||
ValveMoveToPosition2, /// This is actual move to position
|
||||
ValveMoveToPosition3, /// Wait 1 takt
|
||||
CheckStatePosition, /// Verify
|
||||
SettingPosition,
|
||||
ValveMoveToFlow1, /// Wait 1 takt
|
||||
ValveMoveToFlow2, /// This is actual move to flow
|
||||
ValveMoveToFlow3, /// Wait 1 takt
|
||||
CheckStateFlow, /// Verify
|
||||
SettingFlow,
|
||||
FlowReached,
|
||||
SendCommandAgain,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
double currentReqFlowLo;
|
||||
double currentReqFlowHi;
|
||||
double targetPositionLo;
|
||||
double targetPositionHi;
|
||||
|
||||
int expireTime;
|
||||
DoubleBox measuredFlow;
|
||||
int flowWithinBoundsTime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow. Conditionally leave the measurement running.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="controlBoard">Control board device</param>
|
||||
/// <param name="_regulValve">Regulation valve component</param>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Upper limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="timeout">Timeout for the flow setting in [s]</param>
|
||||
/// <param name="leaveMeasurementRunning">true = Leave the measurement running after op. stop</param>
|
||||
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
|
||||
public SetFlowOp(TBF.Rig.ControlBoard.IControlBoard cb, IRegValve _regulValve, IFlowMeter flowMeter,
|
||||
double requiredFlowLo, double requiredFlowHi, DoubleBox measuredFlow,
|
||||
bool reTryCmds, int timeout, bool leaveMeasurementRunning)
|
||||
{
|
||||
uniCB = cb as UniCB;
|
||||
if (uniCB == null) throw new ArgumentNullException("ctrlBoard");
|
||||
|
||||
regValve = _regulValve as TBF.Rig.Uni.RegValveAnalog.RegValve;
|
||||
if (regValve == null) throw new ArgumentNullException(string.Format("{0} is not Elde.RegulValveCoax.", _regulValve.Name));
|
||||
|
||||
if (flowMeter is Uni.FlowMeter.FlowMeter)
|
||||
{
|
||||
this.flowMeterId = (flowMeter as Uni.FlowMeter.FlowMeter).Idx1;
|
||||
}
|
||||
else if (flowMeter is Elde.FlowMeterTwins.FlowMeter)
|
||||
{
|
||||
this.flowMeterId = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentNullException("flowMeter is null or not Elde");
|
||||
}
|
||||
|
||||
nominalFlow = flowMeter.NominalFlow;
|
||||
maximalFlow = nominalFlow * 1.25;
|
||||
|
||||
this.reqFlowAve = (requiredFlowLo + requiredFlowHi) / 2;
|
||||
this.finalReqFlowLo = (0.7 * requiredFlowLo) + (0.3 * this.reqFlowAve); /// Move the lower limit 15% of the range up
|
||||
this.finalReqFlowHi = (0.7 * requiredFlowHi) + (0.3 * this.reqFlowAve); /// Move the upper limit 15% of the range down
|
||||
this.measuredFlow = measuredFlow;
|
||||
this.reTryCommands = reTryCmds;
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
this.leaveMeasurementRunning = leaveMeasurementRunning;
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - Do not leave the measurement running.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo,
|
||||
DoubleBox measuredFlow, bool reTryCmds, int timeout)
|
||||
: this(uniCB, regValve, flowMeter, qFrom, qTo, measuredFlow, reTryCmds, timeout, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - No timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(UniCB uniCB, IRegValve regValve, IFlowMeter flowMeter, double qFrom, double qTo,
|
||||
DoubleBox measuredFlow, bool reTryCmds)
|
||||
: this(uniCB, regValve, flowMeter, qFrom, qTo, measuredFlow, reTryCmds, int.MaxValue, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch target position limits from the dictionary or return false
|
||||
/// </summary>
|
||||
/// <param name="avgReqFlow">Average of the flow targer range (input)</param>
|
||||
/// <param name="positionLo">Target valve position low limit (output)</param>
|
||||
/// <param name="positionHi">Target valve position high limit (output)</param>
|
||||
/// <returns>true when positions for the target flow are stored in the memory, otherwise return false</returns>
|
||||
bool FetchTargetPosition(double avgReqFlow, out double positionLo, out double positionHi)
|
||||
{
|
||||
double targetPosition;
|
||||
if (regValve.Dict.TryGetValue(avgReqFlow, out targetPosition))
|
||||
{
|
||||
positionLo = Math.Max(targetPosition * 0.95f, 0.0f);
|
||||
positionHi = Math.Min(targetPosition * 1.05f, 100.0f);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
positionLo = 0.0f;
|
||||
positionHi = 0.0f;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StoreTargetPosition(double avgReqFlow, double actPosition)
|
||||
{
|
||||
if (!regValve.Dict.ContainsKey(reqFlowAve))
|
||||
{
|
||||
regValve.Dict.Add(new KeyValuePair<double, double>(avgReqFlow, actPosition));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
double flowMtrFreq = uniCB.RefFrequency;
|
||||
currentReqFlowLo = reqFlowAve;
|
||||
currentReqFlowHi = reqFlowAve;
|
||||
///
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentReqFlowLo = finalReqFlowLo; /// Unexpected case when flowMtrFreq==0
|
||||
currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
flowWithinBoundsTime = 0;
|
||||
|
||||
if (regValve.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi))
|
||||
{
|
||||
log.WarnFormat("Start() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
|
||||
regValve.Idx1, flowMeterId, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
|
||||
|
||||
opState = OpState.ValveMoveToPosition1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.WarnFormat("Start() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regValve.Idx1, flowMeterId, currentReqFlowLo, currentReqFlowHi);
|
||||
|
||||
opState = OpState.ValveMoveToFlow1;
|
||||
}
|
||||
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
if (expireTime < 0) expireTime = int.MaxValue;
|
||||
|
||||
/// Start the flow measurement
|
||||
uniCB.MeasureFlow(false, flowMeterId);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.None, Event.FlowReached, Event.RegulValveTimeOut, Event.OpArgumentError
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
double rvPosition = regValve.Position;
|
||||
double flowMtrFreq = uniCB.RefFrequency;
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run() rv#={0} pos={1}% freq={2} flow={3} curFlLo={4} curFlHi={5} state={6}",
|
||||
regValve.Idx1, rvPosition.ToString("F1"), flowMtrFreq.ToString("F1"), flow.ToString("F3"), currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"), opState);
|
||||
|
||||
|
||||
if (opState == OpState.SendCommandAgain)
|
||||
{
|
||||
flowWithinBoundsTime = 0;
|
||||
|
||||
if (regValve.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi))
|
||||
{
|
||||
log.InfoFormat(" Run() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
|
||||
regValve.Idx1, flowMeterId, currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"), targetPositionLo, targetPositionHi);
|
||||
|
||||
opState = OpState.ValveMoveToPosition1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.InfoFormat(" Run() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regValve.Idx1, flowMeterId, currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"));
|
||||
|
||||
opState = OpState.ValveMoveToFlow1;
|
||||
}
|
||||
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
if (expireTime < 0) expireTime = int.MaxValue;
|
||||
|
||||
|
||||
/// Start the flow measurement
|
||||
uniCB.MeasureFlow(false, flowMeterId);
|
||||
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToPosition1)
|
||||
{
|
||||
opState = OpState.ValveMoveToPosition2;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToPosition2) /// Move to position
|
||||
{
|
||||
/// Issues the appropriate ValveMove(...) command
|
||||
// TODO: Reimplement
|
||||
//uniCB.ValveMove(regValve.Idx1, RegulValveMode.TargetPosition,
|
||||
// new double[2] { (targetPositionLo + targetPositionHi) / 2, (targetPositionLo + targetPositionHi) / 2 },
|
||||
// regValve.StableTime);
|
||||
|
||||
opState = OpState.SettingPosition;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToPosition3)
|
||||
{
|
||||
if (reTryCommands)
|
||||
{
|
||||
opState = OpState.CheckStatePosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.SettingPosition;
|
||||
}
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.CheckStatePosition) /// Verify
|
||||
{
|
||||
if (((ulong)uniCB.State & (ulong)StatusP.TestWithRefFlowmtr) == 0)
|
||||
{
|
||||
opState = OpState.SendCommandAgain;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (((ulong)uniCB.State & (ulong)StatusP.CoaxRegValveBusy) == 0)
|
||||
{
|
||||
// TODO: Reimplement
|
||||
///// Repeat appropriate ValveMove(...) command
|
||||
//uniCB.ValveMove(regValve.Idx1, RegulValveMode.TargetPosition,
|
||||
// new double[2] { (targetPositionLo + targetPositionHi) / 2, (targetPositionLo + targetPositionHi) / 2 },
|
||||
// regValve.StableTime);
|
||||
|
||||
log.InfoFormat(" Run() ValveMove({0}, Position, {1}, {2}, {3})",
|
||||
regValve.Idx1, (targetPositionLo + targetPositionHi) / 2, (targetPositionLo + targetPositionHi) / 2, regValve.StableTime);
|
||||
|
||||
opState = OpState.ValveMoveToPosition3;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.SettingPosition;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (opState == OpState.SettingPosition)
|
||||
{
|
||||
/// Repeated untill position is reached
|
||||
if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi))
|
||||
{
|
||||
opState = OpState.ValveMoveToFlow1;
|
||||
}
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToFlow1)
|
||||
{
|
||||
opState = OpState.ValveMoveToFlow2;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToFlow2) /// Move to flow
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
if ((currentReqFlowLo >= currentReqFlowHi) || (currentReqFlowLo > maximalFlow) || (currentReqFlowHi <= 0))
|
||||
{
|
||||
log.DebugFormat(" return Event.OpArgumentError");
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
double freqLo = 2000.0 * currentReqFlowLo / nominalFlow;
|
||||
double freqHi = 2000.0 * currentReqFlowHi / nominalFlow;
|
||||
// TODO: Reimplement
|
||||
//uniCB.ValveMove(regValve.Idx1, RegulValveMode.TargetFrequency,
|
||||
// new double[2] { (freqLo + freqHi) / 2, (freqLo + freqHi) / 2 },
|
||||
// regValve.StableTime);
|
||||
log.WarnFormat(" Run() ValveMove({0}, Freq., {1}, {2}, {3}) flowMtr#={4} TARGET: flowLo={5} flowHi={6}",
|
||||
regValve.Idx1, (freqLo + freqHi) / 2, (freqLo + freqHi) / 2,
|
||||
regValve.StableTime,
|
||||
flowMeterId, currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"));
|
||||
|
||||
opState = OpState.ValveMoveToFlow3;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.ValveMoveToFlow3)
|
||||
{
|
||||
if (reTryCommands)
|
||||
{
|
||||
opState = OpState.CheckStateFlow;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.SettingFlow;
|
||||
}
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.CheckStateFlow) /// Verify the flow setting
|
||||
{
|
||||
if (((ulong)uniCB.State & (ulong)StatusP.CoaxRegValveBusy) == 0)
|
||||
{
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
double freqLo = 2000.0 * currentReqFlowLo / nominalFlow;
|
||||
double freqHi = 2000.0 * currentReqFlowHi / nominalFlow;
|
||||
// TODO: Reimplement
|
||||
//uniCB.ValveMove(regValve.Idx1, RegulValveMode.TargetFrequency,
|
||||
// new double[2] { (freqLo + freqHi) / 2, (freqLo + freqHi) / 2 },
|
||||
// regValve.StableTime);
|
||||
|
||||
log.WarnFormat(" Run() ValveMove({0}, Frequency, {1}, {2}, {3}) flowMtr#={4} TARGET: flowLo={5} flowHi={6}",
|
||||
regValve.Idx1, (freqLo + freqHi) / 2, (freqLo + freqHi) / 2,
|
||||
regValve.StableTime,
|
||||
flowMeterId, currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"));
|
||||
|
||||
opState = OpState.ValveMoveToFlow3;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
opState = OpState.SettingFlow;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (opState == OpState.SettingFlow)
|
||||
{
|
||||
///
|
||||
/// Repeated untill the required flow is reached
|
||||
///
|
||||
if ((currentReqFlowLo <= flow) && (flow <= currentReqFlowHi))
|
||||
{
|
||||
if (flowWithinBoundsTime++ >= regValve.FlowStableSec)
|
||||
{
|
||||
if (regValve.StoredPositionReuse)
|
||||
{
|
||||
double storedPosition;
|
||||
if (regValve.Dict.TryGetValue(reqFlowAve, out storedPosition))
|
||||
{
|
||||
/// update the stored valve position
|
||||
StoreTargetPosition(reqFlowAve, (rvPosition + storedPosition) / 2.0f);
|
||||
log.InfoFormat(" Run() rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position",
|
||||
regValve.Idx1, reqFlowAve, rvPosition.ToString("F1"), storedPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// store the valve position
|
||||
StoreTargetPosition(reqFlowAve, rvPosition);
|
||||
log.InfoFormat(" Run() rv#={0} reqFlow={1} pos={2}% <--- Storing a new position",
|
||||
regValve.Idx1, reqFlowAve, rvPosition.ToString("F1"));
|
||||
}
|
||||
}
|
||||
|
||||
log.InfoFormat(" flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow.ToString("F3"), currentReqFlowLo.ToString("F3"), currentReqFlowHi.ToString("F3"));
|
||||
|
||||
opState = OpState.FlowReached;
|
||||
log.DebugFormat(" return Event.FlowReached");
|
||||
return Event.FlowReached;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.InfoFormat(" flow = {0} m3/h (lo={1}, hi={2}, FLOW_OK_TIMER={3}s)", flow.ToString("F3"), currentReqFlowLo, currentReqFlowHi, flowWithinBoundsTime);
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (StateMachine.Time > expireTime)
|
||||
{
|
||||
log.DebugFormat(" return Event.RegulValveTimeOut");
|
||||
return Event.RegulValveTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.InfoFormat(" flow = {0} m3/h (lo={1}, hi={2})", flow.ToString("F3"), currentReqFlowLo, currentReqFlowHi);
|
||||
flowWithinBoundsTime = 0;
|
||||
log.DebugFormat(" return Event.None");
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else /// opState == OpState.FlowReached
|
||||
{
|
||||
log.InfoFormat(" flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow.ToString("F3"), currentReqFlowLo, currentReqFlowHi);
|
||||
log.DebugFormat(" return Event.FlowReached");
|
||||
return Event.FlowReached;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
opState = OpState.Idle;
|
||||
if (leaveMeasurementRunning) return;
|
||||
uniCB.Stop(false); /// Stop measurement
|
||||
log.WarnFormat("Stop() SendCommand(Stop, {0}, ...)", flowMeterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
///
|
||||
/// 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.RegValveAnalog
|
||||
{
|
||||
public class SetRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetRegulValvePositionOp({0},{1},{2})", regValve.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 regValve;
|
||||
readonly double posLoPct;
|
||||
readonly double posHiPct;
|
||||
readonly int timeout;
|
||||
|
||||
/// Process values
|
||||
bool firstRun;
|
||||
int expireTime;
|
||||
bool positionReached;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="uniCB">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 SetRegulValvePositionOp(UniCB uniCB, RegValve regV, double posLoPct, double posHiPct, int timeout)
|
||||
{
|
||||
if (uniCB == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.uniCB = uniCB;
|
||||
|
||||
this.regValve = regV as RegValve;
|
||||
if (regV == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
|
||||
this.posLoPct = posLoPct;
|
||||
this.posHiPct = posHiPct;
|
||||
this.timeout = timeout;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - no timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetRegulValvePositionOp(UniCB uniCB, RegValve regValve, double posLoPct, double posHiPct)
|
||||
: this(uniCB, regValve, posLoPct, posHiPct, int.MaxValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
firstRun = true;
|
||||
positionReached = false;
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
log.InfoFormat("Start(): RV#={0}, reqPosLo={1}%, reqPosHi={2}%", regValve.Idx1, 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;
|
||||
}
|
||||
|
||||
firstRun = false;
|
||||
|
||||
uniCB.RegVlvMoveToPos(false, regValve.Idx1, posLoPct, posHiPct);
|
||||
opState = OpState.CheckState;
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
if (positionReached) return Event.PositionReached;
|
||||
|
||||
double positionPct = regValve.Position;
|
||||
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regValve.Idx1, positionPct.ToString("F1"));
|
||||
|
||||
if (opState == OpState.CheckState)
|
||||
{
|
||||
if ((uniCB.State & (ulong)StatusP.CoaxRegValveBusy) == 0)
|
||||
{
|
||||
opState = OpState.MoveToPosition;
|
||||
return Event.None;
|
||||
}
|
||||
else if (posLoPct <= positionPct && positionPct <= posHiPct)
|
||||
{
|
||||
positionReached = true;
|
||||
return Event.PositionReached;
|
||||
}
|
||||
else if (regValve.Idx1 < 6
|
||||
/// && uniCB.RegulValveState(regValve.Idx1) != RegulValveState.DacValueRegul // TODO: Reimplement
|
||||
)
|
||||
{
|
||||
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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard.Legacy;
|
||||
using TBF.Rig.GenericDevices;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class ChangeRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(ChangeRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("ChangeRegulValvePositionOp({0},{1}s)", regulValve.Name, timePulseSec.ToString("F2"));
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly TBF.Rig.Uni.RegValve.RegValve regulValve;
|
||||
readonly int regulValveNr;
|
||||
readonly double timePulseSec;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">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 ChangeRegulValvePositionOp(CBoard controlBoard, IRegValve _regulValve, float timePulseSec)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
regulValve = _regulValve as TBF.Rig.Uni.RegValve.RegValve;
|
||||
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
regulValveNr = this.regulValve.Idx1;
|
||||
|
||||
this.timePulseSec = timePulseSec;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
double positionPct = controlBoard.RValvePosition(regulValveNr);
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
|
||||
|
||||
controlBoard.ValveMove(regulValveNr,
|
||||
RegulValveMode.PulseWidth,
|
||||
new double[2] { timePulseSec, timePulseSec },
|
||||
regulValve.StableTime);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.SetFlowDone
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
float positionPct = controlBoard.RValvePosition(regulValveNr);
|
||||
log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
|
||||
|
||||
return Event.PositionReached;
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System.Collections.Generic;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class Factory : IComponentFactory
|
||||
{
|
||||
public string ClassName { get { return "RegValveTandem"; } }
|
||||
public override string ToString() { return ClassName; }
|
||||
|
||||
public void ResetStaticProperties() { RegValveTandem.ResetStaticProperties(); }
|
||||
|
||||
public IComponent DummyComponent() { return new RegValveTandem(); }
|
||||
|
||||
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new RegValveTandem(cfg, components); }
|
||||
|
||||
public IComponentCfg DefaultConfig() { return new RegValveTandemCfg("RV", this); }
|
||||
|
||||
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
|
||||
{
|
||||
return ComponentCfgBase.CreateFromDbEntity(RegValveTandemCfg.Serializer, component, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard.Legacy;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class RegValveTandem : ComponentBase, GenericDevices.IRegValve
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(RegValveTandem));
|
||||
public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); }
|
||||
|
||||
public readonly RegValveTandemCfg RegulValveTandemCfg;
|
||||
|
||||
IDictionary<double, double> dict;
|
||||
public IDictionary<double, double> Dict { get { return dict; } }
|
||||
|
||||
CBoard controlBoard { get { return regValve.ControlBoard; } }
|
||||
public ValveCategory Category { get { return RegulValveTandemCfg.Category; } }
|
||||
|
||||
readonly TBF.Rig.Uni.RegValve.RegValve regValve;
|
||||
readonly TBF.Rig.Uni.RegValve.RegValve fixedRV;
|
||||
|
||||
readonly float fixedPctLo; /// [%]
|
||||
readonly float fixedPctHi; /// [%]
|
||||
|
||||
public int FlowStableSec { get { return RegulValveTandemCfg.FlowStableSec; } } /// 0..60 sec
|
||||
///
|
||||
public bool IsCoax { get { return false; } }
|
||||
|
||||
public double Position
|
||||
{
|
||||
get { return regValve.Position; }
|
||||
}
|
||||
|
||||
|
||||
public RegValveTandem()
|
||||
{
|
||||
}
|
||||
|
||||
public RegValveTandem(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
|
||||
: base(cfg)
|
||||
{
|
||||
RegulValveTandemCfg = cfg as RegValveTandemCfg;
|
||||
|
||||
regValve = TbfComponents.FindComponent(RegulValveTandemCfg.RegulValveName, components) as TBF.Rig.Uni.RegValve.RegValve;
|
||||
if (regValve == null) throw new Exception("Cannot find regulation valve");
|
||||
|
||||
fixedRV = TbfComponents.FindComponent(RegulValveTandemCfg.FixedRVName, components) as TBF.Rig.Uni.RegValve.RegValve;
|
||||
if (fixedRV == null) throw new Exception("Cannot find fixed RV");
|
||||
|
||||
fixedPctLo = Math.Max(0.0f, RegulValveTandemCfg.FixedRVPosition - 3.0f);
|
||||
fixedPctHi = Math.Min(100.0f, RegulValveTandemCfg.FixedRVPosition + 3.0f);
|
||||
|
||||
this.dict = new Dictionary<double, double>();
|
||||
|
||||
log.Warn(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowOp(GenericDevices.IFlowMeter flowMeter, double requiredFlowLo, double requiredFlowHi, DoubleBox measuredFlow, int timeout)
|
||||
{
|
||||
return new SetFlowOp(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi,
|
||||
flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the water flow within tolerances. Leave the measurement running.
|
||||
/// Events: Event.None, Event.FlowReached, Event.FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the required flow [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Higher limit of the required flow [m3/h]</param>
|
||||
/// <param name="measuredFlow">Measured flow [m3/h]</param>
|
||||
/// <param name="timeout">Timeout in [s]</param>
|
||||
/// <returns>SetFlowOp instance</returns>
|
||||
public IOperation SetFlowAndMeasureOp(GenericDevices.IFlowMeter flowMeter, double requiredFlowLo, double requiredFlowHi,
|
||||
DoubleBox measuredFlow, int timeout, float filterConstant)
|
||||
{
|
||||
return new SetFlowOp(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi,
|
||||
flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Operation to set the regulation valve to a required position
|
||||
/// Events: Event.None
|
||||
/// </summary>
|
||||
/// <param name="flowLo">Lower limit of the required valve position in [%]</param>
|
||||
/// <param name="flowLo">Higher limit of the required valve position in [%]</param>
|
||||
/// <returns>SetPositionOp instance</returns>
|
||||
public IOperation SetRegulValvePositionOp(double pctLo, double pctHi, int timeoutMs)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IOperation ChangeRegulValvePositionOp(double timePulseSec)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class RegValveTandemCfg : ComponentCfgBase, IChildComponentCfg
|
||||
{
|
||||
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RegValveTandemCfg) })[0];
|
||||
public override XmlSerializer GetSerializer() { return Serializer; }
|
||||
|
||||
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new RegValveTandemCfgCtrl(); }
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
///
|
||||
public ValveCategory Category; /// Feeding, Output or All
|
||||
public string RegulValveName; /// Name of the regulation valve used to control the flow
|
||||
public string FixedRVName; /// Name of the regulation valve with a fixed position
|
||||
public float FixedRVPosition; /// Fixed RV position 0 .. 100 in [%]
|
||||
public bool StoredPositionReuse; /// true = store and re-use previous regulation valve positions
|
||||
public int FlowStableSec; /// 0..60 sec
|
||||
|
||||
/// Private parameterless constructor invoked by all other (public) constructors
|
||||
RegValveTandemCfg()
|
||||
{
|
||||
}
|
||||
|
||||
public RegValveTandemCfg(string name, IComponentFactory factory)
|
||||
: this()
|
||||
{
|
||||
Name = name;
|
||||
Factory = factory;
|
||||
ParentName = string.Empty;
|
||||
Category = ValveCategory.Output;
|
||||
RegulValveName = "RV1";
|
||||
FixedRVName = "RV2";
|
||||
FixedRVPosition = 50.0f;
|
||||
StoredPositionReuse = false;
|
||||
FlowStableSec = 5;
|
||||
}
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return string.Format("Name={0}, RegulVName={1}, FixedRVName={2}, FixedRVPos={3}%, PosReuse={4}, FlowStable={5}s",
|
||||
Name,
|
||||
RegulValveName,
|
||||
FixedRVName,
|
||||
FixedRVPosition.ToString("F0"),
|
||||
StoredPositionReuse,
|
||||
FlowStableSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.UI.Bench.Components;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public partial class RegValveTandemCfgCtrl : UserControl, IComponentCfgCtrl
|
||||
{
|
||||
ComponentParametersDlg parent;
|
||||
|
||||
public bool ShowMore { get { return true; } }
|
||||
|
||||
RegValveTandemCfg config;
|
||||
public IComponentCfg Config
|
||||
{
|
||||
get { return config as IComponentCfg; }
|
||||
set
|
||||
{
|
||||
config = value as RegValveTandemCfg;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public RegValveTandemCfgCtrl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void RegulationValveCfgCtrl_Load(object sender, EventArgs e)
|
||||
{
|
||||
parent = ParentForm as ComponentParametersDlg;
|
||||
if (parent == null) return;
|
||||
|
||||
if (parent.CmpntEntities != null)
|
||||
{
|
||||
foreach (var cmpnt in parent.CmpntEntities)
|
||||
{
|
||||
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.RegulValve.RegulValveFactory)
|
||||
{
|
||||
regulValveNameComboBox.Items.Add(cmpnt.Name);
|
||||
fixedRVNameComboBox.Items.Add(cmpnt.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
categoryComboBox.Items.Add(ValveCategory.Feeding.ToString());
|
||||
categoryComboBox.Items.Add(ValveCategory.Output.ToString());
|
||||
|
||||
Redraw();
|
||||
}
|
||||
|
||||
public void Closing()
|
||||
{
|
||||
}
|
||||
|
||||
void Redraw()
|
||||
{
|
||||
if (config == null) return; /// Control was not loaded, settings were not changed
|
||||
|
||||
classNameLabel.Text = config.Factory.ClassName;
|
||||
nameTextBox.Text = config.Name;
|
||||
categoryComboBox.Text = config.Category.ToString();
|
||||
regulValveNameComboBox.Text = string.IsNullOrEmpty(config.RegulValveName) ? "---" : config.RegulValveName;
|
||||
fixedRVNameComboBox.Text = string.IsNullOrEmpty(config.FixedRVName) ? "---" : config.FixedRVName;
|
||||
fixedRVPositionTextBox.Text = config.FixedRVPosition.ToString("F0");
|
||||
storedPosReuseCheckBox.Checked = config.StoredPositionReuse;
|
||||
flowStableSecTextBox.Text = config.FlowStableSec.ToString();
|
||||
}
|
||||
|
||||
public void Unlock()
|
||||
{
|
||||
nameTextBox.Enabled = true;
|
||||
categoryComboBox.Enabled = true;
|
||||
regulValveNameComboBox.Enabled = true;
|
||||
fixedRVNameComboBox.Enabled = true;
|
||||
fixedRVPositionTextBox.Enabled = true;
|
||||
storedPosReuseCheckBox.Enabled = true;
|
||||
flowStableSecTextBox.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (!categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString()) &&
|
||||
!categoryComboBox.Text.Equals(ValveCategory.Output.ToString()))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Category'";
|
||||
}
|
||||
|
||||
if (!regulValveNameComboBox.Items.Contains(regulValveNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Regulation valve'";
|
||||
}
|
||||
|
||||
if (!fixedRVNameComboBox.Items.Contains(fixedRVNameComboBox.Text))
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "Invalid 'Fixed reg. valve'";
|
||||
}
|
||||
|
||||
int dummy;
|
||||
if (!int.TryParse(fixedRVPositionTextBox.Text, out dummy) || dummy < 0 || dummy > 100)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Stable time' should be between 200 and 1500 ms in 50 ms steps";
|
||||
}
|
||||
|
||||
if (!int.TryParse(flowStableSecTextBox.Text, out dummy) || dummy < 0 || dummy > 60)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + "'Flow stable' should be between 0 and 60 sec";
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags UpdateCfg()
|
||||
{
|
||||
CfgUpdateFlags flags = CfgUpdateFlags.None;
|
||||
|
||||
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
|
||||
///
|
||||
if (!config.Name.Equals(nameTextBox.Text))
|
||||
{
|
||||
config.Name = nameTextBox.Text;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
ValveCategory newCategory;
|
||||
if (categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString())) newCategory = ValveCategory.Feeding;
|
||||
else if (categoryComboBox.Text.Equals(ValveCategory.Output.ToString())) newCategory = ValveCategory.Output;
|
||||
else newCategory = ValveCategory.None;
|
||||
if (newCategory != config.Category)
|
||||
{
|
||||
config.Category = newCategory;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
string str = regulValveNameComboBox.Text.Equals("---") ? string.Empty : regulValveNameComboBox.Text;
|
||||
if (!config.RegulValveName.Equals(str))
|
||||
{
|
||||
config.RegulValveName = str;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
str = fixedRVNameComboBox.Text.Equals("---") ? string.Empty : fixedRVNameComboBox.Text;
|
||||
if (!config.FixedRVName.Equals(str))
|
||||
{
|
||||
config.FixedRVName = str;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
int tmp = int.Parse(fixedRVPositionTextBox.Text);
|
||||
if (config.FixedRVPosition != (float)tmp)
|
||||
{
|
||||
config.FixedRVPosition = (float)tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
bool btmp = storedPosReuseCheckBox.Checked;
|
||||
if (config.StoredPositionReuse != btmp)
|
||||
{
|
||||
config.StoredPositionReuse = btmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
tmp = int.Parse(flowStableSecTextBox.Text);
|
||||
if (config.FlowStableSec != tmp)
|
||||
{
|
||||
config.FlowStableSec = tmp;
|
||||
flags |= CfgUpdateFlags.RestartRqrd;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
partial class RegValveTandemCfgCtrl
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.regulValveNameLabel = new System.Windows.Forms.Label();
|
||||
this.nameTextBox = new System.Windows.Forms.TextBox();
|
||||
this.nameLabel = new System.Windows.Forms.Label();
|
||||
this.classNameLabel = new System.Windows.Forms.Label();
|
||||
this.regulValveNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.storedPosReuseCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.flowStableSecTextBox = new System.Windows.Forms.TextBox();
|
||||
this.flowStableSecLabel = new System.Windows.Forms.Label();
|
||||
this.fixedRVNameComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.fixedRVNameLabel = new System.Windows.Forms.Label();
|
||||
this.fixedRVPositionTextBox = new System.Windows.Forms.TextBox();
|
||||
this.fixedRVPositionLabel = new System.Windows.Forms.Label();
|
||||
this.categoryComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.categoryLabel = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// regulValveNameLabel
|
||||
//
|
||||
this.regulValveNameLabel.AutoSize = true;
|
||||
this.regulValveNameLabel.Location = new System.Drawing.Point(28, 93);
|
||||
this.regulValveNameLabel.Name = "regulValveNameLabel";
|
||||
this.regulValveNameLabel.Size = new System.Drawing.Size(87, 13);
|
||||
this.regulValveNameLabel.TabIndex = 5;
|
||||
this.regulValveNameLabel.Text = "Regulation valve";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(138, 41);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
|
||||
this.nameTextBox.TabIndex = 2;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(28, 44);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(35, 13);
|
||||
this.nameLabel.TabIndex = 1;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(135, 14);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.classNameLabel.TabIndex = 0;
|
||||
this.classNameLabel.Text = "ComponentName";
|
||||
//
|
||||
// regulValveNameComboBox
|
||||
//
|
||||
this.regulValveNameComboBox.Enabled = false;
|
||||
this.regulValveNameComboBox.FormattingEnabled = true;
|
||||
this.regulValveNameComboBox.Location = new System.Drawing.Point(138, 90);
|
||||
this.regulValveNameComboBox.Name = "regulValveNameComboBox";
|
||||
this.regulValveNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.regulValveNameComboBox.TabIndex = 6;
|
||||
//
|
||||
// storedPosReuseCheckBox
|
||||
//
|
||||
this.storedPosReuseCheckBox.AutoSize = true;
|
||||
this.storedPosReuseCheckBox.Enabled = false;
|
||||
this.storedPosReuseCheckBox.Location = new System.Drawing.Point(31, 171);
|
||||
this.storedPosReuseCheckBox.Name = "storedPosReuseCheckBox";
|
||||
this.storedPosReuseCheckBox.Size = new System.Drawing.Size(162, 17);
|
||||
this.storedPosReuseCheckBox.TabIndex = 11;
|
||||
this.storedPosReuseCheckBox.Text = "Enable stored position re-use";
|
||||
this.storedPosReuseCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// flowStableSecTextBox
|
||||
//
|
||||
this.flowStableSecTextBox.Enabled = false;
|
||||
this.flowStableSecTextBox.Location = new System.Drawing.Point(138, 194);
|
||||
this.flowStableSecTextBox.Name = "flowStableSecTextBox";
|
||||
this.flowStableSecTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.flowStableSecTextBox.TabIndex = 13;
|
||||
//
|
||||
// flowStableSecLabel
|
||||
//
|
||||
this.flowStableSecLabel.AutoSize = true;
|
||||
this.flowStableSecLabel.Location = new System.Drawing.Point(28, 197);
|
||||
this.flowStableSecLabel.Name = "flowStableSecLabel";
|
||||
this.flowStableSecLabel.Size = new System.Drawing.Size(74, 13);
|
||||
this.flowStableSecLabel.TabIndex = 12;
|
||||
this.flowStableSecLabel.Text = "Flow stable [s]";
|
||||
//
|
||||
// fixedRVNameComboBox
|
||||
//
|
||||
this.fixedRVNameComboBox.Enabled = false;
|
||||
this.fixedRVNameComboBox.FormattingEnabled = true;
|
||||
this.fixedRVNameComboBox.Location = new System.Drawing.Point(138, 115);
|
||||
this.fixedRVNameComboBox.Name = "fixedRVNameComboBox";
|
||||
this.fixedRVNameComboBox.Size = new System.Drawing.Size(130, 21);
|
||||
this.fixedRVNameComboBox.TabIndex = 8;
|
||||
//
|
||||
// fixedRVNameLabel
|
||||
//
|
||||
this.fixedRVNameLabel.AutoSize = true;
|
||||
this.fixedRVNameLabel.Location = new System.Drawing.Point(28, 118);
|
||||
this.fixedRVNameLabel.Name = "fixedRVNameLabel";
|
||||
this.fixedRVNameLabel.Size = new System.Drawing.Size(82, 13);
|
||||
this.fixedRVNameLabel.TabIndex = 7;
|
||||
this.fixedRVNameLabel.Text = "Fixed reg. valve";
|
||||
//
|
||||
// fixedRVPositionTextBox
|
||||
//
|
||||
this.fixedRVPositionTextBox.Enabled = false;
|
||||
this.fixedRVPositionTextBox.Location = new System.Drawing.Point(138, 140);
|
||||
this.fixedRVPositionTextBox.Name = "fixedRVPositionTextBox";
|
||||
this.fixedRVPositionTextBox.Size = new System.Drawing.Size(46, 20);
|
||||
this.fixedRVPositionTextBox.TabIndex = 10;
|
||||
//
|
||||
// fixedRVPositionLabel
|
||||
//
|
||||
this.fixedRVPositionLabel.AutoSize = true;
|
||||
this.fixedRVPositionLabel.Location = new System.Drawing.Point(28, 143);
|
||||
this.fixedRVPositionLabel.Name = "fixedRVPositionLabel";
|
||||
this.fixedRVPositionLabel.Size = new System.Drawing.Size(89, 13);
|
||||
this.fixedRVPositionLabel.TabIndex = 9;
|
||||
this.fixedRVPositionLabel.Text = "Fixed RV position";
|
||||
//
|
||||
// categoryComboBox
|
||||
//
|
||||
this.categoryComboBox.Enabled = false;
|
||||
this.categoryComboBox.FormattingEnabled = true;
|
||||
this.categoryComboBox.Location = new System.Drawing.Point(138, 65);
|
||||
this.categoryComboBox.Name = "categoryComboBox";
|
||||
this.categoryComboBox.Size = new System.Drawing.Size(81, 21);
|
||||
this.categoryComboBox.TabIndex = 4;
|
||||
//
|
||||
// categoryLabel
|
||||
//
|
||||
this.categoryLabel.AutoSize = true;
|
||||
this.categoryLabel.Location = new System.Drawing.Point(28, 68);
|
||||
this.categoryLabel.Name = "categoryLabel";
|
||||
this.categoryLabel.Size = new System.Drawing.Size(49, 13);
|
||||
this.categoryLabel.TabIndex = 3;
|
||||
this.categoryLabel.Text = "Category";
|
||||
//
|
||||
// RegulValveTandemCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.categoryComboBox);
|
||||
this.Controls.Add(this.categoryLabel);
|
||||
this.Controls.Add(this.fixedRVPositionTextBox);
|
||||
this.Controls.Add(this.fixedRVPositionLabel);
|
||||
this.Controls.Add(this.fixedRVNameComboBox);
|
||||
this.Controls.Add(this.fixedRVNameLabel);
|
||||
this.Controls.Add(this.flowStableSecTextBox);
|
||||
this.Controls.Add(this.flowStableSecLabel);
|
||||
this.Controls.Add(this.storedPosReuseCheckBox);
|
||||
this.Controls.Add(this.regulValveNameComboBox);
|
||||
this.Controls.Add(this.regulValveNameLabel);
|
||||
this.Controls.Add(this.nameTextBox);
|
||||
this.Controls.Add(this.nameLabel);
|
||||
this.Controls.Add(this.classNameLabel);
|
||||
this.Name = "RegulValveTandemCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(300, 700);
|
||||
this.Load += new System.EventHandler(this.RegulationValveCfgCtrl_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label regulValveNameLabel;
|
||||
private System.Windows.Forms.TextBox nameTextBox;
|
||||
private System.Windows.Forms.Label nameLabel;
|
||||
private System.Windows.Forms.Label classNameLabel;
|
||||
private System.Windows.Forms.ComboBox regulValveNameComboBox;
|
||||
private System.Windows.Forms.CheckBox storedPosReuseCheckBox;
|
||||
private System.Windows.Forms.TextBox flowStableSecTextBox;
|
||||
private System.Windows.Forms.Label flowStableSecLabel;
|
||||
private System.Windows.Forms.ComboBox fixedRVNameComboBox;
|
||||
private System.Windows.Forms.Label fixedRVNameLabel;
|
||||
private System.Windows.Forms.TextBox fixedRVPositionTextBox;
|
||||
private System.Windows.Forms.Label fixedRVPositionLabel;
|
||||
private System.Windows.Forms.ComboBox categoryComboBox;
|
||||
private System.Windows.Forms.Label categoryLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
@@ -0,0 +1,373 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.ControlBoard.Legacy;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Boxes;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class SetFlowOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetFlowOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetFlowOp({0}, Qfrom={1}, Qto={2})", regValve.Name, finalReqFlowLo, finalReqFlowHi);
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly CBoard controlBoard;
|
||||
readonly TBF.Rig.Uni.RegValve.RegValve regValve;
|
||||
readonly TBF.Rig.Uni.RegValve.RegValve fixedRV;
|
||||
readonly double fixedPctLo;
|
||||
readonly double fixedPctHi;
|
||||
readonly int flowMeterNr;
|
||||
readonly double finalReqFlowLo;
|
||||
readonly double finalReqFlowHi;
|
||||
readonly double reqFlowAve;
|
||||
readonly int timeout;
|
||||
readonly bool leaveMeasurementRunning;
|
||||
|
||||
readonly double nominalFlow;
|
||||
readonly double maximalFlow;
|
||||
|
||||
/// Process values
|
||||
enum OpState
|
||||
{
|
||||
Idle = 0,
|
||||
IssueSetPositionCommand,
|
||||
SettingPosition,
|
||||
IssueSetPositionCommand_FixedRV,
|
||||
SettingPosition_FixedRV,
|
||||
IssueSetFlowCommand,
|
||||
SettingFlow,
|
||||
FlowReached,
|
||||
}
|
||||
OpState opState;
|
||||
|
||||
double currentReqFlowLo;
|
||||
double currentReqFlowHi;
|
||||
double targetPositionLo;
|
||||
double targetPositionHi;
|
||||
|
||||
int expireTime;
|
||||
DoubleBox measuredFlow;
|
||||
int flowWithinBoundsTime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow. Conditionally leave the measurement running.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">Control board device</param>
|
||||
/// <param name="_regulValve">Regulation valve component</param>
|
||||
/// <param name="fxdRV">Regulation valve set to a fixed position</param>
|
||||
/// <param name="fixedPctLo">Lower limit of the fixed position of the fixed reg.v.</param>
|
||||
/// <param name="fixedPctHi">Upper limit of the fixed position of the fixed reg.v.</param>
|
||||
/// <param name="flowMeter">Flowmeter component</param>
|
||||
/// <param name="requiredFlowLo">Lower limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="requiredFlowHi">Upper limit of the flow to be achieved in [m3/h]</param>
|
||||
/// <param name="pidCoef">PID coefficient (float)</param>
|
||||
/// <param name="timeout">Timeout for the flow setting in [s]</param>
|
||||
/// <param name="leaveMeasurementRunning">true = Leave the measurement running after op. stop</param>
|
||||
/// <remarks>Only Elde.Valve flow are used, other flow on the lists are ignored</remarks>
|
||||
public SetFlowOp(CBoard controlBoard, IRegValve regV, IRegValve fxdRV, float fxdPctLo, float fxdPctHi,
|
||||
IFlowMeter flowMeter, double requiredFlowLo, double requiredFlowHi, DoubleBox measuredFlow,
|
||||
int timeout, bool leaveMeasurementRunning)
|
||||
{
|
||||
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
|
||||
this.controlBoard = controlBoard;
|
||||
|
||||
regValve = regV as TBF.Rig.Uni.RegValve.RegValve;
|
||||
if (regValve == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
|
||||
fixedRV = fxdRV as TBF.Rig.Uni.RegValve.RegValve;
|
||||
if (fixedRV == null) throw new ArgumentNullException("regValve is null or not Elde");
|
||||
|
||||
this.fixedPctLo = fxdPctLo;
|
||||
this.fixedPctHi = fxdPctHi;
|
||||
|
||||
if (flowMeter is Uni.FlowMeter.FlowMeter)
|
||||
{
|
||||
this.flowMeterNr = (flowMeter as Uni.FlowMeter.FlowMeter).Idx1;
|
||||
}
|
||||
else if (flowMeter is Elde.FlowMeterTwins.FlowMeter)
|
||||
{
|
||||
this.flowMeterNr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentNullException("flowMeter is null or not Elde");
|
||||
}
|
||||
|
||||
nominalFlow = flowMeter.NominalFlow;
|
||||
maximalFlow = nominalFlow * 1.25;
|
||||
|
||||
this.reqFlowAve = (requiredFlowLo + requiredFlowHi) / 2;
|
||||
this.finalReqFlowLo = (0.7 * requiredFlowLo) + (0.3 * this.reqFlowAve); /// Move the lower limit 15% of the range up
|
||||
this.finalReqFlowHi = (0.7 * requiredFlowHi) + (0.3 * this.reqFlowAve); /// Move the upper limit 15% of the range down
|
||||
this.measuredFlow = measuredFlow;
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
this.leaveMeasurementRunning = leaveMeasurementRunning;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - Do not leave the measurement running.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(CBoard controlBoard, IRegValve regValve, IRegValve fixedRV, float fixedPctLo, float fixedPctHi,
|
||||
IFlowMeter flowMeter, double requiredFlowLo, double requiredFlowHi, DoubleBox measuredFlow, int timeout)
|
||||
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, timeout, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - No timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetFlowOp(CBoard controlBoard, IRegValve regValve, IRegValve fixedRV, float fixedPctLo, float fixedPctHi,
|
||||
IFlowMeter flowMeter, double requiredFlowLo, double requiredFlowHi, DoubleBox measuredFlow)
|
||||
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, requiredFlowHi, measuredFlow, int.MaxValue, false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch target position limits from the dictionary or return false
|
||||
/// </summary>
|
||||
/// <param name="avgReqFlow">Average of the flow targer range (input)</param>
|
||||
/// <param name="positionLo">Target valve position low limit (output)</param>
|
||||
/// <param name="positionHi">Target valve position high limit (output)</param>
|
||||
/// <returns>true when positions for the target flow are stored in the memory, otherwise return false</returns>
|
||||
bool FetchTargetPosition(double avgReqFlow, out double positionLo, out double positionHi)
|
||||
{
|
||||
double targetPosition;
|
||||
if (regValve.Dict.TryGetValue(avgReqFlow, out targetPosition))
|
||||
{
|
||||
positionLo = Math.Max(targetPosition * 0.95, 0.0);
|
||||
positionHi = Math.Min(targetPosition * 1.05, 100.0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
positionLo = 0.0;
|
||||
positionHi = 0.0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StoreTargetPosition(double avgReqFlow, double actPosition)
|
||||
{
|
||||
if (!regValve.Dict.ContainsKey(reqFlowAve))
|
||||
{
|
||||
regValve.Dict.Add(new KeyValuePair<double, double>(avgReqFlow, actPosition));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
double flowMtrFreq = controlBoard.RefFrequency;
|
||||
currentReqFlowLo = reqFlowAve;
|
||||
currentReqFlowHi = reqFlowAve;
|
||||
///
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentReqFlowLo = finalReqFlowLo; /// Unexpected case when flowMtrFreq==0
|
||||
currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
flowWithinBoundsTime = 0;
|
||||
|
||||
if (regValve.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi))
|
||||
{
|
||||
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
|
||||
regValve.Idx1, flowMeterNr, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
|
||||
|
||||
opState = OpState.IssueSetPositionCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regValve.Idx1, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
|
||||
|
||||
opState = OpState.IssueSetPositionCommand_FixedRV;
|
||||
}
|
||||
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
if (expireTime < 0) expireTime = int.MaxValue;
|
||||
|
||||
ControlBoard.Legacy.TestMethods tm = 0;
|
||||
StopDevs sd = 0;
|
||||
// '_regulValve.RegulValveTandemCfg.PidCoef' replaced by a casted operation parameter 'pidCoef'
|
||||
controlBoard.SendCommand(Command.Start, flowMeterNr, int.MaxValue, int.MaxValue, tm, sd);
|
||||
}
|
||||
|
||||
/// <summary>Run this operation</summary>
|
||||
/// <returns>
|
||||
/// Event.None, Event.FlowReached, Event.RegulValveTimeOut, Event.OpArgumentError
|
||||
/// </returns>
|
||||
public Event Run()
|
||||
{
|
||||
float rvPosition = controlBoard.RValvePosition(regValve.Idx1);
|
||||
float fixedRVPosition = controlBoard.RValvePosition(fixedRV.Idx1);
|
||||
double flowMtrFreq = controlBoard.RefFrequency;
|
||||
double flow = flowMtrFreq * nominalFlow / 2000.0;
|
||||
|
||||
if (flowMtrFreq != 0)
|
||||
{
|
||||
if (measuredFlow != null) measuredFlow.Val = flow;
|
||||
if (flow >= reqFlowAve) currentReqFlowLo = finalReqFlowLo;
|
||||
if (flow <= reqFlowAve) currentReqFlowHi = finalReqFlowHi;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run(): rv#={0} pos={1}% freq={2} flow={3} opState={4}",
|
||||
regValve.Idx1, rvPosition.ToString("F1"), flowMtrFreq, flow, opState);
|
||||
|
||||
if (opState == OpState.IssueSetPositionCommand)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
controlBoard.ValveMove(regValve.Idx1, RegulValveMode.TargetPosition,
|
||||
new double[2] { targetPositionLo, targetPositionHi },
|
||||
regValve.StableTime);
|
||||
|
||||
opState = OpState.SettingPosition;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingPosition)
|
||||
{
|
||||
///
|
||||
/// Repeated untill position is reached
|
||||
///
|
||||
if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi))
|
||||
{
|
||||
opState = OpState.IssueSetPositionCommand_FixedRV;
|
||||
}
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.IssueSetPositionCommand_FixedRV)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
controlBoard.ValveMove(fixedRV.Idx1, RegulValveMode.TargetPosition,
|
||||
new double[2] { fixedPctLo, fixedPctHi },
|
||||
regValve.StableTime);
|
||||
|
||||
opState = OpState.SettingPosition_FixedRV;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingPosition_FixedRV)
|
||||
{
|
||||
///
|
||||
/// Repeated untill position is reached
|
||||
///
|
||||
if ((fixedPctLo <= fixedRVPosition) && (fixedRVPosition <= fixedPctHi))
|
||||
{
|
||||
opState = OpState.IssueSetFlowCommand;
|
||||
}
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.IssueSetFlowCommand)
|
||||
{
|
||||
///
|
||||
/// Done once, issues an appropriate ValveMove(...) command
|
||||
///
|
||||
if ((currentReqFlowLo >= currentReqFlowHi) || (currentReqFlowLo > maximalFlow) || (currentReqFlowHi <= 0))
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
|
||||
regValve.Idx1, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
|
||||
|
||||
double freqLo = 2000.0 * currentReqFlowLo / nominalFlow;
|
||||
double freqHi = 2000.0 * currentReqFlowHi / nominalFlow;
|
||||
controlBoard.ValveMove(regValve.Idx1, RegulValveMode.TargetFrequency,
|
||||
new double[2] { freqLo, freqHi },
|
||||
regValve.StableTime);
|
||||
|
||||
opState = OpState.SettingFlow;
|
||||
return Event.None;
|
||||
}
|
||||
else if (opState == OpState.SettingFlow)
|
||||
{
|
||||
///
|
||||
/// Repeated untill the required flow is reached
|
||||
///
|
||||
if ((currentReqFlowLo <= flow) && (flow <= currentReqFlowHi))
|
||||
{
|
||||
if (flowWithinBoundsTime++ >= regValve.FlowStableSec)
|
||||
{
|
||||
if (regValve.StoredPositionReuse)
|
||||
{
|
||||
double storedPosition;
|
||||
if (regValve.Dict.TryGetValue(reqFlowAve, out storedPosition))
|
||||
{
|
||||
/// update the stored valve position
|
||||
StoreTargetPosition(reqFlowAve, (rvPosition + storedPosition) / 2.0f);
|
||||
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position",
|
||||
regValve.Idx1, reqFlowAve, rvPosition.ToString("F1"), storedPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// store the valve position
|
||||
StoreTargetPosition(reqFlowAve, rvPosition);
|
||||
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position",
|
||||
regValve.Idx1, reqFlowAve, rvPosition.ToString("F1"));
|
||||
}
|
||||
}
|
||||
opState = OpState.FlowReached;
|
||||
return Event.FlowReached;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else if (StateMachine.Time > expireTime)
|
||||
{
|
||||
return Event.RegulValveTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
flowWithinBoundsTime = 0;
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
else /// opState == OpState.FlowReached
|
||||
{
|
||||
return Event.FlowReached;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
opState = OpState.Idle;
|
||||
|
||||
if (leaveMeasurementRunning) return;
|
||||
|
||||
/// Stop measurement
|
||||
ControlBoard.Legacy.TestMethods tm = 0;
|
||||
StopDevs sd = StopDevs.RegValveRegulation;
|
||||
controlBoard.SendCommand(Command.Stop, flowMeterNr, 50000, 50000, tm, sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
///
|
||||
/// Copyright (c) 2021 Sensus Slovensko a.s.
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using log4net;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Rig.Uni;
|
||||
|
||||
namespace TBF.Rig.Uni.RegValveTandem
|
||||
{
|
||||
public class SetRegulValvePositionOp : IOperation
|
||||
{
|
||||
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegulValvePositionOp));
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("SetRegulValvePositionOp({0},{1},{2})", regValve.Name, posLoPct, posHiPct);
|
||||
}
|
||||
|
||||
/// Set by the constructor
|
||||
readonly TBF.Rig.ControlBoard.Uni.UniCB uniCB;
|
||||
readonly RegValve.RegValve regValve;
|
||||
readonly double posLoPct;
|
||||
readonly double posHiPct;
|
||||
readonly int timeout;
|
||||
|
||||
/// Process values
|
||||
bool firstRun;
|
||||
int expireTime;
|
||||
bool positionReached;
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow.
|
||||
/// Events: FlowSet, FlowTimeOut
|
||||
/// </summary>
|
||||
/// <param name="ControlBoard">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 SetRegulValvePositionOp(TBF.Rig.ControlBoard.IControlBoard cb, IRegValve regV, double posLoPct, double posHiPct, int timeout)
|
||||
{
|
||||
uniCB = cb as TBF.Rig.ControlBoard.Uni.UniCB;
|
||||
if (uniCB == null) throw new ArgumentNullException("ctrlBoard");
|
||||
|
||||
regValve = regV as RegValve.RegValve;
|
||||
if (regValve == null) throw new ArgumentNullException("regValve is null or not Uni");
|
||||
|
||||
this.posLoPct = posLoPct;
|
||||
this.posHiPct = posHiPct;
|
||||
this.timeout = timeout;
|
||||
|
||||
log.Debug(this.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set required water flow - no timeout.
|
||||
/// Events: FlowSet
|
||||
/// </summary>
|
||||
public SetRegulValvePositionOp(TBF.Rig.ControlBoard.IControlBoard controlBoard, RegValveTandem regValve, float posLoPct, float posHiPct)
|
||||
: this(controlBoard, regValve, posLoPct, posHiPct, int.MaxValue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Start this operation</summary>
|
||||
public void Start()
|
||||
{
|
||||
firstRun = true;
|
||||
positionReached = false;
|
||||
expireTime = StateMachine.Time + timeout;
|
||||
log.InfoFormat("Start(): RV#={0}, reqPosLo={1}%, reqPosHi={2}%", regValve.Idx1, posLoPct.ToString("F1"), posHiPct.ToString("F1"));
|
||||
}
|
||||
|
||||
/// <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 (firstRun)
|
||||
{
|
||||
if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0)
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
|
||||
firstRun = false;
|
||||
|
||||
uniCB.RegVlvMoveToPos(false, regValve.Idx1, posLoPct, posHiPct);
|
||||
return Event.None;
|
||||
}
|
||||
|
||||
if (positionReached) return Event.PositionReached;
|
||||
|
||||
double positionPct = regValve.Position;
|
||||
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regValve.Idx1, positionPct.ToString("F1"));
|
||||
|
||||
if (posLoPct >= posHiPct || posLoPct >= 100.0f || posHiPct <= 0)
|
||||
{
|
||||
return Event.OpArgumentError;
|
||||
}
|
||||
else if (posLoPct <= positionPct && positionPct <= posHiPct)
|
||||
{
|
||||
positionReached = true;
|
||||
return Event.PositionReached;
|
||||
}
|
||||
else if (StateMachine.Time > expireTime)
|
||||
{
|
||||
return Event.RegulValveTimeOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Event.None;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Stop this operation</summary>
|
||||
public void Stop()
|
||||
{
|
||||
uniCB.Stop(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user