Refactoring : TestBenchFramework --> TBF ver. 2.18.789

This commit is contained in:
Milan Hanajik
2018-01-29 09:48:01 +01:00
parent 06018303e7
commit 0d3ee53bd5
1300 changed files with 441 additions and 612 deletions
@@ -0,0 +1,78 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.GenericDevices;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
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 ControlBoardDev controlBoard;
readonly Elde.RegulValve.RegulValve regulValve;
readonly int regulValveNr;
readonly float 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(ControlBoardDev controlBoard, IRegulValve _regulValve, float timePulseSec)
{
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
this.controlBoard = controlBoard;
regulValve = _regulValve as Elde.RegulValve.RegulValve;
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()
{
float positionPct = controlBoard.RValvePosition(regulValveNr);
log.WarnFormat("RV#={0}, actPos={1}%", regulValveNr, positionPct.ToString("F1"));
controlBoard.ValveMove(regulValveNr,
RegulValveMode.PulseWidth,
new float[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,116 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
public class RegulValveTandem : ComponentBase, GenericDevices.IRegulValve
{
private static readonly ILog log = LogManager.GetLogger(typeof(RegulValveTandem));
public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); }
public readonly RegulValveTandemCfg RegulValveTandemCfg;
IDictionary<float, float> dict;
public IDictionary<float, float> Dict { get { return dict; } }
ControlBoardDev controlBoard { get { return regulValve.ControlBoard; } }
public ValveCategory Category { get { return RegulValveTandemCfg.Category; } }
readonly RegulValve.RegulValve regulValve;
readonly RegulValve.RegulValve fixedRV;
readonly float fixedPctLo; /// [%]
readonly float fixedPctHi; /// [%]
public int FlowStableSec { get { return RegulValveTandemCfg.FlowStableSec; } } /// 0..60 sec
///
public bool IsCoax { get { return false; } }
public float Position
{
get { return regulValve.Position; }
}
public RegulValveTandem()
{
}
public RegulValveTandem(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
RegulValveTandemCfg = cfg as RegulValveTandemCfg;
regulValve = (RegulValve.RegulValve)TbfComponents.FindComponent(RegulValveTandemCfg.RegulValveName, components);
if (regulValve == null) throw new Exception("Cannot find regulation valve");
fixedRV = (RegulValve.RegulValve)TbfComponents.FindComponent(RegulValveTandemCfg.FixedRVName, components);
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<float, float>();
log.Debug(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, float requiredFlowLo, float requiredFlowHi,
float pidCoef, DoubleBox measuredFlow, int timeout)
{
return new SetFlowOp(controlBoard, regulValve, fixedRV, fixedPctLo, fixedPctHi,
flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, 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, float requiredFlowLo, float requiredFlowHi,
float pidCoef, DoubleBox measuredFlow, int timeout, float filterConstant)
{
return new SetFlowOp(controlBoard, regulValve, fixedRV, fixedPctLo, fixedPctHi,
flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, 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(float pctLo, float pctHi, int timeoutMs)
{
return null;
}
public IOperation ChangeRegulValvePositionOp(float timePulseSec)
{
return null;
}
}
}
@@ -0,0 +1,59 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
public class RegulValveTandemCfg : ComponentCfgBase, IChildComponentCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RegulValveTandemCfg) })[0];
protected override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl() { return new RegulValveTandemCfgCtrl(); }
///
/// 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
RegulValveTandemCfg()
{
}
public RegulValveTandemCfg(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,190 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using System.Windows.Forms;
using log4net;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
public partial class RegulValveTandemCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(RegulValveTandemCfgCtrl));
ComponentParametersDlg parent;
public bool ShowMore { get { return true; } }
RegulValveTandemCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as RegulValveTandemCfg;
Redraw();
}
}
public RegulValveTandemCfgCtrl()
{
InitializeComponent();
}
private void RegulationValveCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
if (parent.TbfComponents != null)
{
foreach (var cmpnt in parent.TbfComponents)
{
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.RegulValve.RegulValveFactory)
{
regulValveNameComboBox.Items.Add(cmpnt.Name);
fixedRVNameComboBox.Items.Add(cmpnt.Name);
}
}
}
categoryComboBox.Items.Add(ValveCategory.All.ToString());
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.All.ToString()) &&
!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.All.ToString())) newCategory = ValveCategory.All;
else if (categoryComboBox.Text.Equals(ValveCategory.Feeding.ToString())) newCategory = ValveCategory.Feeding;
else if (categoryComboBox.Text.Equals(ValveCategory.Bench.ToString())) newCategory = ValveCategory.Bench;
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) 2013-2015 Sensus Metering Systems
///
namespace TBF.BenchControl.Elde.RegulValveTandem
{
partial class RegulValveTandemCfgCtrl
{
/// <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,26 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
public class RegulValveTandemFactory : IComponentFactory
{
public string ClassName { get { return "RegulationValveTandem"; } }
public void ResetStaticProperties() { RegulValveTandem.ResetStaticProperties(); }
public IComponent DummyComponent() { return new RegulValveTandem(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new RegulValveTandem(cfg, components); }
public IComponentCfg DefaultConfig() { return new RegulValveTandemCfg("RV", this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(RegulValveTandemCfg.Serializer, component, this);
}
}
}
@@ -0,0 +1,380 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.GenericDevices;
using TBF.Boxes;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
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}, PID={3})", regulValve.Name, finalReqFlowLo, finalReqFlowHi, pidCoef);
}
/// Set by the constructor
readonly ControlBoardDev controlBoard;
readonly Elde.RegulValve.RegulValve regulValve;
readonly int regulValveNr;
readonly Elde.RegulValve.RegulValve fixedRV;
readonly int fixedRVNr;
readonly float fixedPctLo;
readonly float fixedPctHi;
readonly int flowMeterNr;
readonly float finalReqFlowLo;
readonly float finalReqFlowHi;
readonly float reqFlowAve;
readonly float pidCoef;
readonly int timeout;
readonly bool leaveMeasurementRunning;
readonly float nominalFlow;
/// Process values
enum OpState
{
Idle = 0,
IssueSetPositionCommand,
SettingPosition,
IssueSetPositionCommand_FixedRV,
SettingPosition_FixedRV,
IssueSetFlowCommand,
SettingFlow,
FlowReached,
}
OpState opState;
float currentReqFlowLo;
float currentReqFlowHi;
float targetPositionLo;
float 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(ControlBoardDev controlBoard, IRegulValve regV, IRegulValve fxdRV, float fxdPctLo, float fxdPctHi,
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow,
int timeout, bool leaveMeasurementRunning)
{
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
this.controlBoard = controlBoard;
regulValve = regV as Elde.RegulValve.RegulValve;
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
regulValveNr = regulValve.Idx1;
fixedRV = fxdRV as Elde.RegulValve.RegulValve;
if (fixedRV == null) throw new ArgumentNullException("regValve is null or not Elde");
fixedRVNr = fixedRV.Idx1;
this.fixedPctLo = fxdPctLo;
this.fixedPctHi = fxdPctHi;
if (flowMeter is Elde.FlowMeter.FlowMeter)
{
this.flowMeterNr = (flowMeter as Elde.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;
this.finalReqFlowLo = requiredFlowLo;
this.finalReqFlowHi = requiredFlowHi;
this.reqFlowAve = (requiredFlowLo + requiredFlowHi) / 2.0f;
this.pidCoef = pidCoef;
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(ControlBoardDev controlBoard, IRegulValve regValve, IRegulValve fixedRV, float fixedPctLo, float fixedPctHi,
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow, int timeout)
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, requiredFlowHi, pidCoef, measuredFlow, timeout, false)
{
}
/// <summary>
/// Set required water flow - No timeout.
/// Events: FlowSet
/// </summary>
public SetFlowOp(ControlBoardDev controlBoard, IRegulValve regValve, IRegulValve fixedRV, float fixedPctLo, float fixedPctHi,
IFlowMeter flowMeter, float requiredFlowLo, float requiredFlowHi, float pidCoef, DoubleBox measuredFlow)
: this(controlBoard, regValve, fixedRV, fixedPctLo, fixedPctHi, flowMeter, requiredFlowLo, pidCoef, 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(float avgReqFlow, out float positionLo, out float positionHi)
{
float targetPosition;
if (regulValve.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(float avgReqFlow, float actPosition)
{
if (!regulValve.Dict.ContainsKey(reqFlowAve))
{
regulValve.Dict.Add(new KeyValuePair<float, float>(avgReqFlow, actPosition));
}
return;
}
/// <summary>Start this operation</summary>
public void Start()
{
double flowMtrFreq = controlBoard.ReferenceFreq;
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 (regulValve.RegulValveCfg.StoredPositionReuse && FetchTargetPosition(reqFlowAve, out targetPositionLo, out targetPositionHi))
{
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
opState = OpState.IssueSetPositionCommand;
}
else
{
log.InfoFormat("Start(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
opState = OpState.IssueSetPositionCommand_FixedRV;
}
expireTime = StateMachine.Time + timeout;
if (expireTime < 0) expireTime = int.MaxValue;
TestMethods tm = 0;
StopDevs sd = 0;
// '_regulValve.RegulValveTandemCfg.PidCoef' replaced by a casted operation parameter 'pidCoef'
controlBoard.SendCommand(Command.Start, flowMeterNr, controlBoard.Route,
int.MaxValue, int.MaxValue, tm,
0.0f, (int)pidCoef, 0, sd);
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None, Event.FlowReached, Event.RegulValveTimeOut, Event.OpArgumentError
/// </returns>
public Event Run()
{
float rvPosition = controlBoard.RValvePosition(regulValveNr);
float fixedRVPosition = controlBoard.RValvePosition(fixedRVNr);
double flowMtrFreq = controlBoard.ReferenceFreq;
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}",
regulValveNr, rvPosition.ToString("F1"), flowMtrFreq, flow, opState);
if (opState == OpState.IssueSetPositionCommand)
{
///
/// Done once, issues an appropriate ValveMove(...) command
///
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetPosition,
new float[2] { targetPositionLo, targetPositionHi },
regulValve.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(fixedRVNr, RegulValveMode.TargetPosition,
new float[2] { fixedPctLo, fixedPctHi },
regulValve.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 > nominalFlow || currentReqFlowHi <= 0)
{
return Event.OpArgumentError;
}
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
regulValveNr, flowMeterNr, currentReqFlowLo, currentReqFlowHi);
float freqLo = 2000.0f * currentReqFlowLo / nominalFlow;
float freqHi = 2000.0f * currentReqFlowHi / nominalFlow;
controlBoard.ValveMove(regulValveNr, RegulValveMode.TargetFrequency,
new float[2] { freqLo, freqHi },
regulValve.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++ >= regulValve.FlowStableSec)
{
if (regulValve.RegulValveCfg.StoredPositionReuse)
{
float storedPosition;
if (regulValve.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",
regulValveNr, 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",
regulValveNr, 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
TestMethods tm = 0;
StopDevs sd = StopDevs.RegValveRegulation;
controlBoard.SendCommand(Command.Stop, flowMeterNr, controlBoard.Route,
50000, 50000, tm,
0.0f, 20, 0, sd);
}
}
}
@@ -0,0 +1,134 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.GenericDevices;
namespace TBF.BenchControl.Elde.RegulValveTandem
{
public class SetRegulValvePositionOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegulValvePositionOp));
public override string ToString()
{
return string.Format("SetRegulValvePositionOp({0},{1},{2})", regulValve.Name, posLoPct, posHiPct);
}
/// Set by the constructor
readonly ControlBoardDev controlBoard;
readonly Elde.RegulValve.RegulValve regulValve;
readonly int regulValveNr;
readonly float posLoPct;
readonly float 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(ControlBoardDev controlBoard, IRegulValve regV, float posLoPct, float posHiPct, int timeout)
{
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
this.controlBoard = controlBoard;
regulValve = regV as Elde.RegulValve.RegulValve;
if (regulValve == null) throw new ArgumentNullException("regValve is null or not Elde");
regulValveNr = this.regulValve.Idx1;
this.posLoPct = posLoPct;
this.posHiPct = posHiPct;
this.timeout = timeout;
log.Debug(this.ToString());
}
/// <summary>
/// Set required water flow - no timeout.
/// Events: FlowSet
/// </summary>
public SetRegulValvePositionOp(ControlBoardDev controlBoard, RegulValveTandem 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}%", regulValveNr, 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;
controlBoard.ValveMove(regulValveNr,
RegulValveMode.TargetPosition,
new float[2] { posLoPct, posHiPct },
regulValve.StableTime);
return Event.None;
}
if (positionReached) return Event.PositionReached;
float positionPct = controlBoard.RValvePosition(regulValveNr);
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regulValveNr, 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()
{
controlBoard.ValveMove(regulValveNr,
RegulValveMode.Stop,
new float[2] { posLoPct, posHiPct },
regulValve.StableTime);
}
}
}