Refactorization : BenchControl -> Rig

This commit is contained in:
Milan Hanajik
2021-03-05 16:12:24 +01:00
parent 84c8ec26b6
commit 6cf3bd6160
1461 changed files with 6330 additions and 6330 deletions
+215
View File
@@ -0,0 +1,215 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using Dirichlet.Numerics;
using TBF.Rig.ControlBoard.Uni;
using TBF.Rig.Generic;
using TBF.Boxes;
using TBF.Resources;
namespace TBF.Rig.Uni.Diverter
{
public class Diverter : ComponentBase, IDevice, GenericDevices.IDiverter, GenericDevices.ISequenceCondition, GenericDevices.IHasCalendarEvents, SchematicDrawing.IDrawingItCmpnt
{
private static readonly ILog log = LogManager.GetLogger(typeof(Diverter));
public override string ToString() { return string.Format("Diverter({0})", Cfg.ToString(1)); }
/// <summary>
/// Enumeration of balances via static fields and methods
/// </summary>
static int nextIdx = 0;
public static new void ResetStaticProperties()
{
nextIdx = 0;
}
public static int DivertersCount { get { return nextIdx; } }
public static GenericDevices.IDiverter[] Diverters;
readonly DiverterCfg diverterCfg;
public SchematicDrawing.IDrawingItem DrawingItem { get { return diverterCfg as SchematicDrawing.IDrawingItem; } }
readonly UniCB cBoard;
readonly UInt128 mask; /// derived from bitPosition in the constructor
public int DiverterNr { get { return diverterCfg.DivNr1; } } /// 1-based public diverter number
public int AdcNr { get { return diverterCfg.AdcNr; } }
readonly IOperation diverterToTankOp;
readonly IOperation diverterToSinkOp;
public bool State { get { return (cBoard.Route & mask) != 0; } }
public int ThresholdGate { get { return diverterCfg.StartingLevel; } }
public int ThresholdLo { get { return diverterCfg.ThresholdLo; } }
public int ThresholdHi { get { return diverterCfg.ThresholdHi; } }
FloatBox switchTimeStart;
FloatBox switchTimeEnd;
public FloatBox SwitchTimeStart { get { return switchTimeStart; } }
public FloatBox SwitchTimeEnd { get { return switchTimeEnd; } }
/// <summary>
/// For a given flow in [m3/h] returns a test time correction in [s]
/// </summary>
public double TestTimeCorrection(double flow)
{
return Config.Formulas.GetCorrection(flow, Corrections);
}
public Diverter()
{
}
public Diverter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
diverterCfg = cfg as DiverterCfg;
cBoard = TbfComponents.FindComponent(cfg.ParentName, components) as UniCB;
if (cBoard == null) throw new Exception("Cannot find " + Name + " parent");
if (cfg.DebugLevel != Config.Entities.DebugMode.Off)
{
if (diverterCfg.BitNr < 0 || diverterCfg.BitNr >= 64) throw new ArgumentOutOfRangeException("position");
this.mask = (((UInt128)1) << diverterCfg.BitNr);
switchTimeStart = new FloatBox(diverterCfg.DfltSwithTimeStartMs / 1000.0f);
switchTimeEnd = new FloatBox(diverterCfg.DfltSwithTimeEndMs / 1000.0f);
///// Prepare arguments of SendCalibData()
//if (diverterCfg.AdcNr >= 0 && diverterCfg.AdcNr < cBoard.RegValveCalib.GetLength(0))
//{
// cBoard.RegValveCalib[diverterCfg.AdcNr, 0] = (uint)diverterCfg.AdcValueToSink;
// cBoard.RegValveCalib[diverterCfg.AdcNr, 1] = (uint)diverterCfg.AdcValueToTank;
//}
//else
//{
// log.ErrorFormat("Unable to set {0} ADC levels: RegValveCalib array size={1}, diverter AdcNr={2}",
// Name, cBoard.RegValveCalib.GetLength(0), diverterCfg.AdcNr);
//}
diverterToTankOp = new SwitchDiverterOp(cBoard, true, DiverterNr);
diverterToSinkOp = new SwitchDiverterOp(cBoard, false, DiverterNr);
log.Warn(this.ToString());
}
}
///
/// Calendar support
///
public IList<Config.CalendarEvent.ICalendarEvent> GetCalendarEvents()
{
DateTime calibrationDue = diverterCfg.CalibValidDate;
IList<Config.CalendarEvent.ICalendarEvent> calendarEvents = new List<Config.CalendarEvent.ICalendarEvent>();
if (calibrationDue > TBF.UI.Constants.MinDate)
{
/// Calibration due date calendar event
calendarEvents.Add(new TBF.UI.Calendar.CalibrationDueDateEvent(calibrationDue.Date, Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat))));
if (DateTime.Now.Date <= calibrationDue.AddDays(-7))
{
/// Weekly reminders (last 5 weeks)
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.Date.AddDays(-35), Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
false));
}
if (DateTime.Now.Date <= calibrationDue.Date)
{
/// Daily reminders (last 5 days)
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.AddDays(-5), Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
true));
}
}
return calendarEvents;
}
///
/// IDevice interface implementation
///
public void Initialize() { }
public void RunDeviceBefore()
{
Int16 adcValue = cBoard.Data.AnalogInput[diverterCfg.AdcNr];
Handlers.OnAdcChanged(this, new CmdResponseArgs(CfgChangeCmd.GetAdc, diverterCfg.BitNr, adcValue));
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
///
/// ISequenceCondition interface implementation
///
public int ConditionsCount { get { return 2; } }
/// Returned strings are added to the combo-box
public string ConditionName(int i)
{
if (i == 0) return string.Format("{0} {1}", Name, Strings.Start);
else return string.Format("{0} {1}", Name, Strings.End);
}
public IOperation ConditionOp(int i)
{
if (i == 0) return diverterToTankOp;
else return diverterToSinkOp;
}
#region Configuration Change Handling
public static void OnCfgChange(object sender, CfgChangeArgs args)
{
if (CfgChangeHandler == null) return;
try { CfgChangeHandler(sender, args); }
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
}
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
public override void StartChangeHandler()
{
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
{
DiverterCfg tmpcfg = args.Cfg as DiverterCfg;
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
{
if (args.Command == CfgChangeCmd.CfgChange)
{
}
else if (args.Command == CfgChangeCmd.GetAdc1 || args.Command == CfgChangeCmd.GetAdc2)
{
Int16 adcValue = cBoard.Data.AnalogInput[diverterCfg.AdcNr];
DiverterCfgCtrl.OnCmdResponse(this, new CmdResponseArgs(args.Command, diverterCfg.BitNr, adcValue));
}
else if (args.Command == CfgChangeCmd.DivToTank)
{
cBoard.DiverterToTank(diverterCfg.DivNr1);
}
else if (args.Command == CfgChangeCmd.DivToSink)
{
cBoard.DiverterToSink(diverterCfg.DivNr1);
}
else if (args.Command == CfgChangeCmd.ReadDivTransition)
{
cBoard.ReadDiverterTransition(diverterCfg.DivNr1);
}
}
};
}
#endregion Configuration Change Handling
}
}
+105
View File
@@ -0,0 +1,105 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using Config.Entities;
using SchematicDrawing;
using TBF.Rig.Generic;
namespace TBF.Rig.Uni.Diverter
{
public class DiverterCfg : ComponentCfgBase, IChildComponentCfg, GenericDevices.ICalibInfoCfg, IRouteBasedDrawingItem
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(DiverterCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Component> cmpntEntities)
{
return new DiverterCfgCtrl();
}
///
/// Serialized parameters
///
public int DivNr1 { get; set; } /// 1..5
public int BitNr { get; set; } /// 0..127
public bool Inverted { get; set; } /// When true the diverter function is inverted: 0 = to the tank, 1 = off
public int AdcNr; /// 0..15(?), number of the analog input
public int AdcValueToSink; /// 0..1023
public int AdcValueToTank; /// 0..1023
public int StartingLevel; /// 0..100 in %, threshold for the ADC value to start the test
public int ThresholdLo; /// 0..100 in %, threshold for low level when diverter transition time is measured
public int ThresholdHi; /// 0..100 in %, threshold for high level when diverter transition time is measured
public int DfltSwithTimeStartMs; /// Default diverter transition time 'start' or 'to tank' in ms
public int DfltSwithTimeEndMs; /// Default diverter transition time 'end' or 'to sink' in ms
/// Calibration info serialized parameters displayed in Metrology tab page
public string CalibCertificateNr { get; set; }
public DateTime CalibDate { get; set; }
public DateTime CalibValidDate { get; set; }
/// 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; }
[XmlIgnore]
public IList<GNode> GNodes { get; set; }
[XmlIgnore]
public IList<GEdge> EdgesToSet { get; set; }
/// Private parameterless constructor invoked by all other (public) constructors
DiverterCfg()
{
GNodes = new List<GNode>();
EdgesToSet = new List<GEdge>();
}
public DiverterCfg(IComponentFactory factory)
: this()
{
Shape = Shape.Div;
Sz = Sz.M;
Factory = factory;
Name = "Div";
ParentName = "UniCB";
DivNr1 = 1;
BitNr = 0;
AdcNr = 5; /// Div1: AdcNr=5 , Div2: AdcNr=6
AdcValueToSink = 100;
AdcValueToTank = 500;
StartingLevel = 50;
ThresholdLo = 10;
ThresholdHi = 90;
DfltSwithTimeStartMs = 1;
DfltSwithTimeEndMs = 1;
CalibCertificateNr = string.Empty;
}
public string ToString(int i)
{
return string.Format("Name={0}, Parent={1}, Nr={2}, Bit={3}, ADC#={4}, ADC2Sink={5}, ADC2Tank={6}, Gate={7}%, Lo={8}%, Lo={9}%",
Name,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
DivNr1,
BitNr,
AdcNr,
AdcValueToSink,
AdcValueToTank,
StartingLevel,
ThresholdLo,
ThresholdHi);
}
}
}
+646
View File
@@ -0,0 +1,646 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
namespace TBF.Rig.Uni.Diverter
{
partial class DiverterCfgCtrl
{
/// <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.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.parentNameLabel = new System.Windows.Forms.Label();
this.bitPositionLabel = new System.Windows.Forms.Label();
this.bitPositionTextBox = new System.Windows.Forms.TextBox();
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
this.startingEdgeTextBox = new System.Windows.Forms.TextBox();
this.startingEdgeLabel = new System.Windows.Forms.Label();
this.thresholdLoTextBox = new System.Windows.Forms.TextBox();
this.thresholdLoLabel = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.startButton = new System.Windows.Forms.Button();
this.stopButton = new System.Windows.Forms.Button();
this.updateButton = new System.Windows.Forms.Button();
this.adcToTankTextBox = new System.Windows.Forms.TextBox();
this.adcTankLabel = new System.Windows.Forms.Label();
this.adcToSinkTextBox = new System.Windows.Forms.TextBox();
this.adcSinkLabel = new System.Windows.Forms.Label();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.label4 = new System.Windows.Forms.Label();
this.adcTextBox = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.setButton2 = new System.Windows.Forms.Button();
this.label3 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.getButton2 = new System.Windows.Forms.Button();
this.pctTextBox2 = new System.Windows.Forms.TextBox();
this.adcTextBox2 = new System.Windows.Forms.TextBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.setButton1 = new System.Windows.Forms.Button();
this.label6 = new System.Windows.Forms.Label();
this.ADC = new System.Windows.Forms.Label();
this.getButton1 = new System.Windows.Forms.Button();
this.pctTextBox1 = new System.Windows.Forms.TextBox();
this.adcTextBox1 = new System.Windows.Forms.TextBox();
this.adcNrTextBox = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.thresholdHiTextBox = new System.Windows.Forms.TextBox();
this.thresholdHiLabel = new System.Windows.Forms.Label();
this.dfltSwitchTimeEndTextBox = new System.Windows.Forms.TextBox();
this.dfltSwitchTimeEndLabel = new System.Windows.Forms.Label();
this.dfltSwitchTimeStartTextBox = new System.Windows.Forms.TextBox();
this.dfltSwitchTimeStartLabel = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
this.divNr1TextBox = new System.Windows.Forms.TextBox();
this.divIx1Label = new System.Windows.Forms.Label();
this.groupBox4.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(144, 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(21, 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(141, 17);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComonentName";
//
// parentNameLabel
//
this.parentNameLabel.AutoSize = true;
this.parentNameLabel.Location = new System.Drawing.Point(21, 67);
this.parentNameLabel.Name = "parentNameLabel";
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
this.parentNameLabel.TabIndex = 3;
this.parentNameLabel.Text = "Parent Name";
//
// bitPositionLabel
//
this.bitPositionLabel.AutoSize = true;
this.bitPositionLabel.Location = new System.Drawing.Point(21, 114);
this.bitPositionLabel.Name = "bitPositionLabel";
this.bitPositionLabel.Size = new System.Drawing.Size(103, 13);
this.bitPositionLabel.TabIndex = 5;
this.bitPositionLabel.Text = "Bit position (0 .. 127)";
//
// bitPositionTextBox
//
this.bitPositionTextBox.Enabled = false;
this.bitPositionTextBox.Location = new System.Drawing.Point(144, 111);
this.bitPositionTextBox.Name = "bitPositionTextBox";
this.bitPositionTextBox.Size = new System.Drawing.Size(46, 20);
this.bitPositionTextBox.TabIndex = 6;
//
// parentNameComboBox
//
this.parentNameComboBox.Enabled = false;
this.parentNameComboBox.FormattingEnabled = true;
this.parentNameComboBox.Location = new System.Drawing.Point(144, 64);
this.parentNameComboBox.Name = "parentNameComboBox";
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
this.parentNameComboBox.TabIndex = 4;
//
// startingEdgeTextBox
//
this.startingEdgeTextBox.Enabled = false;
this.startingEdgeTextBox.Location = new System.Drawing.Point(144, 203);
this.startingEdgeTextBox.Name = "startingEdgeTextBox";
this.startingEdgeTextBox.Size = new System.Drawing.Size(46, 20);
this.startingEdgeTextBox.TabIndex = 14;
//
// startingEdgeLabel
//
this.startingEdgeLabel.AutoSize = true;
this.startingEdgeLabel.Location = new System.Drawing.Point(21, 206);
this.startingEdgeLabel.Name = "startingEdgeLabel";
this.startingEdgeLabel.Size = new System.Drawing.Size(68, 13);
this.startingEdgeLabel.TabIndex = 13;
this.startingEdgeLabel.Text = "Starting level";
//
// thresholdLoTextBox
//
this.thresholdLoTextBox.Enabled = false;
this.thresholdLoTextBox.Location = new System.Drawing.Point(144, 226);
this.thresholdLoTextBox.Name = "thresholdLoTextBox";
this.thresholdLoTextBox.Size = new System.Drawing.Size(46, 20);
this.thresholdLoTextBox.TabIndex = 17;
//
// thresholdLoLabel
//
this.thresholdLoLabel.AutoSize = true;
this.thresholdLoLabel.Location = new System.Drawing.Point(21, 229);
this.thresholdLoLabel.Name = "thresholdLoLabel";
this.thresholdLoLabel.Size = new System.Drawing.Size(69, 13);
this.thresholdLoLabel.TabIndex = 16;
this.thresholdLoLabel.Text = "Threshold Lo";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(197, 228);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(15, 13);
this.label2.TabIndex = 18;
this.label2.Text = "%";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(197, 206);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(15, 13);
this.label1.TabIndex = 15;
this.label1.Text = "%";
//
// startButton
//
this.startButton.Location = new System.Drawing.Point(10, 557);
this.startButton.Name = "startButton";
this.startButton.Size = new System.Drawing.Size(55, 31);
this.startButton.TabIndex = 22;
this.startButton.Text = "Start";
this.startButton.UseVisualStyleBackColor = true;
this.startButton.Click += new System.EventHandler(this.startButton_Click);
//
// stopButton
//
this.stopButton.Location = new System.Drawing.Point(71, 557);
this.stopButton.Name = "stopButton";
this.stopButton.Size = new System.Drawing.Size(55, 31);
this.stopButton.TabIndex = 23;
this.stopButton.Text = "Stop";
this.stopButton.UseVisualStyleBackColor = true;
this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
//
// updateButton
//
this.updateButton.Enabled = false;
this.updateButton.Location = new System.Drawing.Point(206, 557);
this.updateButton.Name = "updateButton";
this.updateButton.Size = new System.Drawing.Size(85, 31);
this.updateButton.TabIndex = 26;
this.updateButton.Text = "Update Edge";
this.updateButton.UseVisualStyleBackColor = true;
this.updateButton.Click += new System.EventHandler(this.updateButton_Click);
//
// adcToTankTextBox
//
this.adcToTankTextBox.Enabled = false;
this.adcToTankTextBox.Location = new System.Drawing.Point(144, 180);
this.adcToTankTextBox.Name = "adcToTankTextBox";
this.adcToTankTextBox.Size = new System.Drawing.Size(46, 20);
this.adcToTankTextBox.TabIndex = 12;
//
// adcTankLabel
//
this.adcTankLabel.AutoSize = true;
this.adcTankLabel.Location = new System.Drawing.Point(21, 183);
this.adcTankLabel.Name = "adcTankLabel";
this.adcTankLabel.Size = new System.Drawing.Size(94, 13);
this.adcTankLabel.TabIndex = 11;
this.adcTankLabel.Text = "ADC when to tank";
//
// adcToSinkTextBox
//
this.adcToSinkTextBox.Enabled = false;
this.adcToSinkTextBox.Location = new System.Drawing.Point(144, 157);
this.adcToSinkTextBox.Name = "adcToSinkTextBox";
this.adcToSinkTextBox.Size = new System.Drawing.Size(46, 20);
this.adcToSinkTextBox.TabIndex = 10;
//
// adcSinkLabel
//
this.adcSinkLabel.AutoSize = true;
this.adcSinkLabel.Location = new System.Drawing.Point(21, 160);
this.adcSinkLabel.Name = "adcSinkLabel";
this.adcSinkLabel.Size = new System.Drawing.Size(92, 13);
this.adcSinkLabel.TabIndex = 9;
this.adcSinkLabel.Text = "ADC when to sink";
//
// groupBox4
//
this.groupBox4.Controls.Add(this.label4);
this.groupBox4.Controls.Add(this.adcTextBox);
this.groupBox4.Location = new System.Drawing.Point(10, 352);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(279, 40);
this.groupBox4.TabIndex = 19;
this.groupBox4.TabStop = false;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(11, 17);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(32, 13);
this.label4.TabIndex = 22;
this.label4.Text = "ADC:";
//
// adcTextBox
//
this.adcTextBox.Location = new System.Drawing.Point(47, 14);
this.adcTextBox.Name = "adcTextBox";
this.adcTextBox.Size = new System.Drawing.Size(44, 20);
this.adcTextBox.TabIndex = 21;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.setButton2);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Controls.Add(this.getButton2);
this.groupBox2.Controls.Add(this.pctTextBox2);
this.groupBox2.Controls.Add(this.adcTextBox2);
this.groupBox2.Location = new System.Drawing.Point(10, 462);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(280, 59);
this.groupBox2.TabIndex = 21;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Measured value 2";
//
// setButton2
//
this.setButton2.Location = new System.Drawing.Point(229, 17);
this.setButton2.Name = "setButton2";
this.setButton2.Size = new System.Drawing.Size(38, 33);
this.setButton2.TabIndex = 5;
this.setButton2.Text = "Set";
this.setButton2.UseVisualStyleBackColor = true;
this.setButton2.Click += new System.EventHandler(this.setButton_Click);
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(209, 28);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(15, 13);
this.label3.TabIndex = 4;
this.label3.Text = "%";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(11, 27);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(32, 13);
this.label5.TabIndex = 3;
this.label5.Text = "ADC:";
//
// getButton2
//
this.getButton2.Location = new System.Drawing.Point(101, 18);
this.getButton2.Name = "getButton2";
this.getButton2.Size = new System.Drawing.Size(38, 33);
this.getButton2.TabIndex = 2;
this.getButton2.Text = "Get";
this.getButton2.UseVisualStyleBackColor = true;
this.getButton2.Click += new System.EventHandler(this.getButton2_Click);
//
// pctTextBox2
//
this.pctTextBox2.Location = new System.Drawing.Point(160, 24);
this.pctTextBox2.Name = "pctTextBox2";
this.pctTextBox2.Size = new System.Drawing.Size(46, 20);
this.pctTextBox2.TabIndex = 1;
//
// adcTextBox2
//
this.adcTextBox2.Location = new System.Drawing.Point(47, 24);
this.adcTextBox2.Name = "adcTextBox2";
this.adcTextBox2.Size = new System.Drawing.Size(44, 20);
this.adcTextBox2.TabIndex = 0;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.setButton1);
this.groupBox1.Controls.Add(this.label6);
this.groupBox1.Controls.Add(this.ADC);
this.groupBox1.Controls.Add(this.getButton1);
this.groupBox1.Controls.Add(this.pctTextBox1);
this.groupBox1.Controls.Add(this.adcTextBox1);
this.groupBox1.Location = new System.Drawing.Point(10, 398);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(280, 59);
this.groupBox1.TabIndex = 20;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Measured value 1";
//
// setButton1
//
this.setButton1.Location = new System.Drawing.Point(229, 17);
this.setButton1.Name = "setButton1";
this.setButton1.Size = new System.Drawing.Size(38, 33);
this.setButton1.TabIndex = 5;
this.setButton1.Text = "Set";
this.setButton1.UseVisualStyleBackColor = true;
this.setButton1.Click += new System.EventHandler(this.setButton_Click);
//
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(209, 28);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(15, 13);
this.label6.TabIndex = 4;
this.label6.Text = "%";
//
// ADC
//
this.ADC.AutoSize = true;
this.ADC.Location = new System.Drawing.Point(11, 28);
this.ADC.Name = "ADC";
this.ADC.Size = new System.Drawing.Size(32, 13);
this.ADC.TabIndex = 3;
this.ADC.Text = "ADC:";
//
// getButton1
//
this.getButton1.Location = new System.Drawing.Point(101, 18);
this.getButton1.Name = "getButton1";
this.getButton1.Size = new System.Drawing.Size(38, 33);
this.getButton1.TabIndex = 2;
this.getButton1.Text = "Get";
this.getButton1.UseVisualStyleBackColor = true;
this.getButton1.Click += new System.EventHandler(this.getButton1_Click);
//
// pctTextBox1
//
this.pctTextBox1.Location = new System.Drawing.Point(160, 24);
this.pctTextBox1.Name = "pctTextBox1";
this.pctTextBox1.Size = new System.Drawing.Size(46, 20);
this.pctTextBox1.TabIndex = 1;
//
// adcTextBox1
//
this.adcTextBox1.Location = new System.Drawing.Point(47, 24);
this.adcTextBox1.Name = "adcTextBox1";
this.adcTextBox1.Size = new System.Drawing.Size(44, 20);
this.adcTextBox1.TabIndex = 0;
//
// adcNrTextBox
//
this.adcNrTextBox.Enabled = false;
this.adcNrTextBox.Location = new System.Drawing.Point(144, 134);
this.adcNrTextBox.Name = "adcNrTextBox";
this.adcNrTextBox.Size = new System.Drawing.Size(46, 20);
this.adcNrTextBox.TabIndex = 8;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(21, 137);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(120, 13);
this.label7.TabIndex = 7;
this.label7.Text = "Analog input nr. (0 .. 15)";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(197, 251);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(15, 13);
this.label8.TabIndex = 29;
this.label8.Text = "%";
//
// thresholdHiTextBox
//
this.thresholdHiTextBox.Enabled = false;
this.thresholdHiTextBox.Location = new System.Drawing.Point(144, 249);
this.thresholdHiTextBox.Name = "thresholdHiTextBox";
this.thresholdHiTextBox.Size = new System.Drawing.Size(46, 20);
this.thresholdHiTextBox.TabIndex = 28;
//
// thresholdHiLabel
//
this.thresholdHiLabel.AutoSize = true;
this.thresholdHiLabel.Location = new System.Drawing.Point(21, 252);
this.thresholdHiLabel.Name = "thresholdHiLabel";
this.thresholdHiLabel.Size = new System.Drawing.Size(67, 13);
this.thresholdHiLabel.TabIndex = 27;
this.thresholdHiLabel.Text = "Threshold Hi";
//
// dfltSwitchTimeEndTextBox
//
this.dfltSwitchTimeEndTextBox.Enabled = false;
this.dfltSwitchTimeEndTextBox.Location = new System.Drawing.Point(144, 295);
this.dfltSwitchTimeEndTextBox.Name = "dfltSwitchTimeEndTextBox";
this.dfltSwitchTimeEndTextBox.Size = new System.Drawing.Size(46, 20);
this.dfltSwitchTimeEndTextBox.TabIndex = 33;
//
// dfltSwitchTimeEndLabel
//
this.dfltSwitchTimeEndLabel.AutoSize = true;
this.dfltSwitchTimeEndLabel.Location = new System.Drawing.Point(21, 298);
this.dfltSwitchTimeEndLabel.Name = "dfltSwitchTimeEndLabel";
this.dfltSwitchTimeEndLabel.Size = new System.Drawing.Size(117, 13);
this.dfltSwitchTimeEndLabel.TabIndex = 32;
this.dfltSwitchTimeEndLabel.Text = "Default switch time end";
//
// dfltSwitchTimeStartTextBox
//
this.dfltSwitchTimeStartTextBox.Enabled = false;
this.dfltSwitchTimeStartTextBox.Location = new System.Drawing.Point(144, 272);
this.dfltSwitchTimeStartTextBox.Name = "dfltSwitchTimeStartTextBox";
this.dfltSwitchTimeStartTextBox.Size = new System.Drawing.Size(46, 20);
this.dfltSwitchTimeStartTextBox.TabIndex = 31;
//
// dfltSwitchTimeStartLabel
//
this.dfltSwitchTimeStartLabel.AutoSize = true;
this.dfltSwitchTimeStartLabel.Location = new System.Drawing.Point(21, 275);
this.dfltSwitchTimeStartLabel.Name = "dfltSwitchTimeStartLabel";
this.dfltSwitchTimeStartLabel.Size = new System.Drawing.Size(119, 13);
this.dfltSwitchTimeStartLabel.TabIndex = 30;
this.dfltSwitchTimeStartLabel.Text = "Default switch time start";
//
// label9
//
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(197, 275);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(20, 13);
this.label9.TabIndex = 34;
this.label9.Text = "ms";
//
// label10
//
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(197, 298);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(20, 13);
this.label10.TabIndex = 35;
this.label10.Text = "ms";
//
// divNr1TextBox
//
this.divNr1TextBox.Enabled = false;
this.divNr1TextBox.Location = new System.Drawing.Point(144, 88);
this.divNr1TextBox.Name = "divNr1TextBox";
this.divNr1TextBox.Size = new System.Drawing.Size(46, 20);
this.divNr1TextBox.TabIndex = 37;
//
// divIx1Label
//
this.divIx1Label.AutoSize = true;
this.divIx1Label.Location = new System.Drawing.Point(21, 91);
this.divIx1Label.Name = "divIx1Label";
this.divIx1Label.Size = new System.Drawing.Size(92, 13);
this.divIx1Label.TabIndex = 36;
this.divIx1Label.Text = "Diverter nr. (1 .. 5)";
//
// DiverterCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.divNr1TextBox);
this.Controls.Add(this.divIx1Label);
this.Controls.Add(this.label10);
this.Controls.Add(this.label9);
this.Controls.Add(this.dfltSwitchTimeEndTextBox);
this.Controls.Add(this.dfltSwitchTimeEndLabel);
this.Controls.Add(this.dfltSwitchTimeStartTextBox);
this.Controls.Add(this.dfltSwitchTimeStartLabel);
this.Controls.Add(this.label8);
this.Controls.Add(this.thresholdHiTextBox);
this.Controls.Add(this.thresholdHiLabel);
this.Controls.Add(this.adcNrTextBox);
this.Controls.Add(this.label7);
this.Controls.Add(this.groupBox4);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.adcToTankTextBox);
this.Controls.Add(this.adcTankLabel);
this.Controls.Add(this.adcToSinkTextBox);
this.Controls.Add(this.adcSinkLabel);
this.Controls.Add(this.updateButton);
this.Controls.Add(this.stopButton);
this.Controls.Add(this.startButton);
this.Controls.Add(this.label1);
this.Controls.Add(this.label2);
this.Controls.Add(this.thresholdLoTextBox);
this.Controls.Add(this.thresholdLoLabel);
this.Controls.Add(this.startingEdgeTextBox);
this.Controls.Add(this.startingEdgeLabel);
this.Controls.Add(this.parentNameComboBox);
this.Controls.Add(this.bitPositionTextBox);
this.Controls.Add(this.bitPositionLabel);
this.Controls.Add(this.parentNameLabel);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Name = "DiverterCfgCtrl";
this.Size = new System.Drawing.Size(300, 700);
this.Load += new System.EventHandler(this.DiverterCfgCtrl_Load);
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.Label parentNameLabel;
private System.Windows.Forms.Label bitPositionLabel;
private System.Windows.Forms.TextBox bitPositionTextBox;
private System.Windows.Forms.ComboBox parentNameComboBox;
private System.Windows.Forms.TextBox startingEdgeTextBox;
private System.Windows.Forms.Label startingEdgeLabel;
private System.Windows.Forms.TextBox thresholdLoTextBox;
private System.Windows.Forms.Label thresholdLoLabel;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button startButton;
private System.Windows.Forms.Button stopButton;
private System.Windows.Forms.Button updateButton;
private System.Windows.Forms.TextBox adcToTankTextBox;
private System.Windows.Forms.Label adcTankLabel;
private System.Windows.Forms.TextBox adcToSinkTextBox;
private System.Windows.Forms.Label adcSinkLabel;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox adcTextBox;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button setButton2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Button getButton2;
private System.Windows.Forms.TextBox pctTextBox2;
private System.Windows.Forms.TextBox adcTextBox2;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button setButton1;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.Label ADC;
private System.Windows.Forms.Button getButton1;
private System.Windows.Forms.TextBox pctTextBox1;
private System.Windows.Forms.TextBox adcTextBox1;
private System.Windows.Forms.TextBox adcNrTextBox;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox thresholdHiTextBox;
private System.Windows.Forms.Label thresholdHiLabel;
private System.Windows.Forms.TextBox dfltSwitchTimeEndTextBox;
private System.Windows.Forms.Label dfltSwitchTimeEndLabel;
private System.Windows.Forms.TextBox dfltSwitchTimeStartTextBox;
private System.Windows.Forms.Label dfltSwitchTimeStartLabel;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.TextBox divNr1TextBox;
private System.Windows.Forms.Label divIx1Label;
}
}
+392
View File
@@ -0,0 +1,392 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System;
using System.Linq;
using System.Windows.Forms;
using log4net;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.UI.Bench.Components;
namespace TBF.Rig.Uni.Diverter
{
public partial class DiverterCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(DiverterCfgCtrl));
ComponentParametersDlg parent;
public bool ShowMore { get { return true; } }
DiverterCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as DiverterCfg;
Redraw();
}
}
public DiverterCfgCtrl()
{
InitializeComponent();
}
private void DiverterCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
if (parent.CmpntEntities != null)
{
foreach (var c in parent.CmpntEntities.Where(x => x.ClassName == "ControlBoard.Uni"))
{
parentNameComboBox.Items.Add(c.Name);
}
}
if (config != null)
{
adc1 = config.AdcValueToSink;
pct1 = 0;
adc2 = config.AdcValueToTank;
pct2 = 100;
}
Redraw();
StartResponseHandler();
}
public void Closing()
{
StopResponseHandler();
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
nameTextBox.Text = config.Name;
divNr1TextBox.Text = config.DivNr1.ToString();
bitPositionTextBox.Text = config.BitNr.ToString();
adcNrTextBox.Text = config.AdcNr.ToString();
adcToSinkTextBox.Text = config.AdcValueToSink.ToString();
adcToTankTextBox.Text = config.AdcValueToTank.ToString();
startingEdgeTextBox.Text = config.StartingLevel.ToString();
thresholdLoTextBox.Text = config.ThresholdLo.ToString();
thresholdHiTextBox.Text = config.ThresholdHi.ToString();
dfltSwitchTimeStartTextBox.Text = config.DfltSwithTimeStartMs.ToString();
dfltSwitchTimeEndTextBox.Text = config.DfltSwithTimeEndMs.ToString();
adcTextBox1.Text = adc1.ToString();
adcTextBox2.Text = adc2.ToString();
pctTextBox1.Text = pct1.ToString();
pctTextBox2.Text = pct2.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
divNr1TextBox.Enabled = true;
bitPositionTextBox.Enabled = true;
adcNrTextBox.Enabled = true;
adcToSinkTextBox.Enabled = true;
adcToTankTextBox.Enabled = true;
startingEdgeTextBox.Enabled = true;
thresholdLoTextBox.Enabled = true;
thresholdHiTextBox.Enabled = true;
dfltSwitchTimeStartTextBox.Enabled = true;
dfltSwitchTimeEndTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int dummy;
int divLo;
int divHi;
if (!parentNameComboBox.Items.Contains(parentNameComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Parent Name'";
}
if (!int.TryParse(divNr1TextBox.Text, out dummy) || dummy < 1 || dummy > 5)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Diverter nr.' should be between 1 and 5";
}
if (!int.TryParse(bitPositionTextBox.Text, out dummy) || dummy < 0 || dummy > 127)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Bit Position' should be between 0 and 127";
}
if (!int.TryParse(adcNrTextBox.Text, out dummy) || dummy < 0 || dummy > 15)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Analog input #' should be between 0 and 15";
}
if (!int.TryParse(adcToSinkTextBox.Text, out dummy) || dummy < 0 || dummy > 1023)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'ADC when to sink' should be between 0 and 1023";
}
if (!int.TryParse(adcToTankTextBox.Text, out dummy) || dummy < 0 || dummy > 1023)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'ADC when to tank' should be between 0 and 1023";
}
if (!int.TryParse(startingEdgeTextBox.Text, out dummy) || dummy < 0 || dummy > 100)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Starting Edge' should be between 0 and 100%";
}
if (!int.TryParse(thresholdLoTextBox.Text, out divLo) || divLo < 0 || divLo > 100)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Threshold LO' should be between 0 and 100%";
}
if (!int.TryParse(thresholdHiTextBox.Text, out divHi) || dummy > 100 || divHi <= divLo)
{
flags |= CfgUpdateFlags.Error;
if (divHi <= divLo)
{
message += Environment.NewLine + "'Threshold HI' should greater then 'Threshold LO'";
}
else
{
message += Environment.NewLine + "'Threshold HI' should be between 0 and 100%";
}
}
if (!int.TryParse(dfltSwitchTimeStartTextBox.Text, out dummy) || dummy <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Default switch time start' should be positive integer";
}
if (!int.TryParse(dfltSwitchTimeEndTextBox.Text, out dummy) || dummy <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Default switch time end' should be positive integer";
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
// CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
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;
}
int tmp = int.Parse(divNr1TextBox.Text);
if (config.DivNr1 != tmp)
{
config.DivNr1 = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(bitPositionTextBox.Text);
if (config.BitNr != tmp)
{
config.BitNr = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(adcNrTextBox.Text);
if (config.AdcNr != tmp)
{
config.AdcNr = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(adcToSinkTextBox.Text);
if (config.AdcValueToSink != tmp)
{
config.AdcValueToSink = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(adcToTankTextBox.Text);
if (config.AdcValueToTank != tmp)
{
config.AdcValueToTank = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(startingEdgeTextBox.Text);
if (config.StartingLevel != tmp)
{
config.StartingLevel = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(thresholdLoTextBox.Text);
if (config.ThresholdLo != tmp)
{
config.ThresholdLo = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(thresholdHiTextBox.Text);
if (config.ThresholdHi != tmp)
{
config.ThresholdHi = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(dfltSwitchTimeStartTextBox.Text);
if (config.DfltSwithTimeStartMs != tmp)
{
config.DfltSwithTimeStartMs = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(dfltSwitchTimeEndTextBox.Text);
if (config.DfltSwithTimeEndMs != tmp)
{
config.DfltSwithTimeEndMs = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
return flags;
}
int adc1;
int pct1;
int adc2;
int pct2;
private void getButton1_Click(object sender, EventArgs e)
{
Diverter.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.GetAdc1, config));
}
private void getButton2_Click(object sender, EventArgs e)
{
Diverter.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.GetAdc2, config));
}
private void setButton_Click(object sender, EventArgs e)
{
int tmpPct1;
int tmpPct2;
if ((int.TryParse(pctTextBox1.Text, out tmpPct1) && (tmpPct1 >= 0) && (tmpPct1 <= 100)) &&
(int.TryParse(pctTextBox2.Text, out tmpPct2) && (tmpPct2 >= 0) && (tmpPct2 <= 100)))
{
pct1 = tmpPct1;
pct2 = tmpPct2;
UpdateDivAdc();
}
}
void UpdateDivAdc()
{
if ((adc1 == adc2) || (pct1 == pct2)) return;
double factor = (float)(adc2 - adc1) / (float)(pct2 - pct1);
int adcToSink = (int)((float)(0 - pct1) * factor + (float)adc1 + 0.5f);
int adcToTank = (int)((float)(100 - pct1) * factor + (float)adc1 + 0.5f);
if ((adcToSink >= 0) && (adcToTank >= 0))
{
adcToSinkTextBox.Text = adcToSink.ToString();
adcToTankTextBox.Text = adcToTank.ToString();
}
}
private void startButton_Click(object sender, EventArgs e)
{
Diverter.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.DivToTank, config));
}
private void stopButton_Click(object sender, EventArgs e)
{
Diverter.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.DivToSink, config));
}
private void updateButton_Click(object sender, EventArgs e)
{
Diverter.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.ReadDivTransition, config));
}
#region Configuration Change Handling
public static void OnCmdResponse(object sender, CmdResponseArgs args)
{
if (CmdResponseHandler == null) return;
try { CmdResponseHandler(sender, args); }
catch (Exception e) { log.Error("CmdResponseHandler(...) failed", e); }
}
public static event EventHandler<CmdResponseArgs> CmdResponseHandler;
public void StartResponseHandler()
{
Handlers.AdcChangedHandler += delegate(object sndr, CmdResponseArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CmdResponseArgs>(OnAdcChanged), sndr, args); }
else OnAdcChanged(sndr, args);
};
CmdResponseHandler += delegate(object sender, CmdResponseArgs args)
{
if (args.Command == CfgChangeCmd.GetAdc1)
{
adc1 = args.Response;
adcTextBox1.Text = adc1.ToString();
}
else if (args.Command == CfgChangeCmd.GetAdc2)
{
adc2 = args.Response;
adcTextBox2.Text = adc2.ToString();
}
};
}
public void StopResponseHandler()
{
CmdResponseHandler = null;
}
void OnAdcChanged(object sender, CmdResponseArgs data)
{
if (data.Command == CfgChangeCmd.GetAdc && data.Id == config.BitNr)
{
adcTextBox.Text = data.Response.ToString();
}
}
#endregion Configuration Change Handling
}
}
+120
View File
@@ -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>
+27
View File
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Uni.Diverter
{
public class Factory : IComponentFactory
{
public string ClassName { get { return "Diverter"; } }
public override string ToString() { return ClassName; }
public void ResetStaticProperties() { Diverter.ResetStaticProperties(); }
public IComponent DummyComponent() { return new Diverter(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Diverter(cfg, components); }
public IComponentCfg DefaultConfig() { return new DiverterCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(DiverterCfg.Serializer, component, this);
}
}
}
+36
View File
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.Rig.Uni.Diverter
{
static class Handlers
{
static readonly ILog log = LogManager.GetLogger(typeof(Handlers));
static Handlers()
{
}
/// <summary>
/// Called from the state machine when a procedure is selected and UI needs to be updated.
/// </summary>
public static void OnAdcChanged(object sender, CmdResponseArgs data)
{
if (AdcChangedHandler == null)
return;
try
{
AdcChangedHandler(sender, data);
}
catch (Exception e)
{
log.Error("AdcChangedHandler(...) failed", e);
}
}
public static event EventHandler<CmdResponseArgs> AdcChangedHandler;
}
}
@@ -0,0 +1,62 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.Rig.Uni.Diverter
{
public class ReadDiverterStateOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadDiverterStateOp));
public override string ToString() { return string.Format("ReadDiverterStateOp(div={0}, delay={1})", div.Name, delay); }
/// Set by the constructor
readonly Diverter div;
readonly int delay;
int startTime;
/// <summary>
/// Events: FlowInDone, FlowOutDone or Error
/// </summary>
/// <param name="flowMeter">Flow meter reference</param>
/// <param name="flowBox">Reference to the measured flow variable, value is in bar</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public ReadDiverterStateOp(GenericDevices.IDiverter div, int delay)
{
this.div = div as Diverter;
if (div == null) throw new ArgumentNullException();
this.delay = delay;
log.Debug(this.ToString());
}
public ReadDiverterStateOp(GenericDevices.IDiverter div)
: this(div, 0)
{
}
/// <summary>Start this operation</summary>
public void Start()
{
startTime = StateMachine.Time;
}
/// <summary>Run this operation</summary>
/// <returns> Event.ToTank or Event.ToSink </returns>
public Event Run()
{
if (StateMachine.Time - startTime <= delay)
{
return Event.None;
}
return div.State ? Event.ToTank : Event.ToSink;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}
+38
View File
@@ -0,0 +1,38 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
namespace TBF.Rig.Uni.Diverter
{
public class SwitchDiverterOp : IOperation
{
TBF.Rig.ControlBoard.Uni.UniCB cBoard;
bool toTank;
int diverterNr; /// 1 .. 5
public SwitchDiverterOp(TBF.Rig.ControlBoard.Uni.UniCB cBoard, bool toTank, int diverterNr)
{
this.cBoard = cBoard;
this.toTank = toTank;
this.diverterNr = diverterNr;
}
public void Start()
{
if (toTank)
{
cBoard.DiverterToTank(diverterNr);
}
else
{
cBoard.DiverterToSink(diverterNr);
}
}
public Event Run()
{
return Event.ConditionMet;
}
public void Stop() { }
}
}
+27
View File
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Uni.FlowMeter
{
public class Factory : IComponentFactory
{
public string ClassName { get { return "FlowMeter"; } }
public override string ToString() { return ClassName; }
public void ResetStaticProperties() { FlowMeter.ResetStaticProperties(); }
public IComponent DummyComponent() { return new FlowMeter(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new FlowMeter(cfg, components); }
public IComponentCfg DefaultConfig() { return new FlowMeterCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(FlowMeterCfg.Serializer, component, this);
}
}
}
+213
View File
@@ -0,0 +1,213 @@
///
/// 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;
using TBF.Resources;
namespace TBF.Rig.Uni.FlowMeter
{
public class FlowMeter : ComponentBase, Generic.IDevice, GenericDevices.IFlowMeter, GenericDevices.IHasCalendarEvents, IDrawingItCmpntWithMeasuredVal
{
private static readonly ILog log = LogManager.GetLogger(typeof(FlowMeter));
public override string ToString() { return string.Format("FlowMeter({0})", Cfg.ToString(1)); }
readonly FlowMeterCfg flowMeterCfg;
public SchematicDrawing.IDrawingItem DrawingItem { get { return flowMeterCfg as SchematicDrawing.IDrawingItem; } }
readonly UniCB cBoard;
public bool MsrmntAvailable
{
get { return cBoard.Devices != null && cBoard.Devices.FlowMeter != null && cBoard.Devices.FlowMeter.Idx1 == Idx1; }
}
public double MeasuredVal { get { return cBoard.RefFrequency * NominalFlow / 2000.0; } }
public string AltString { get { return string.Format("Calibration expires on {0:dd.MM.yyyy}", flowMeterCfg.CalibValidDate); } }
public int Idx1 { get { return (flowMeterCfg != null) ? flowMeterCfg.Idx1 : 0; } }
public double NominalFlow { get { return (flowMeterCfg != null) ? flowMeterCfg.NominalFlow : 0; } }
public double LtrPerPulse { get { return (flowMeterCfg != null) ? flowMeterCfg.NominalFlow / 7200.0 : 0; } } /// Nominal frequency is 2000 Hz
public double LtrPerPulseCorrected(double flow, int rangeIx)
{
/// Apply correction
var rangeCorrections = new List<Config.Entities.MeasurementCorrection>();
foreach (var corr in Corrections)
{
if (corr.RangeIx == rangeIx) rangeCorrections.Add(corr);
}
double correctedFlow = Config.Formulas.CorrectedValue(flow, rangeCorrections);
return (LtrPerPulse * correctedFlow / flow);
}
public bool RangeEnabled(int ix) { return flowMeterCfg.RangeEnabled(ix); }
public double GetTempLo(int ix) { return flowMeterCfg.GetTempLo(ix); }
public double GetTempHi(int ix) { return flowMeterCfg.GetTempHi(ix); }
public double GetPressLo(int ix) { return flowMeterCfg.GetPressLo(ix); }
public double GetPressHi(int ix) { return flowMeterCfg.GetPressHi(ix); }
public FlowMeter()
{
}
public FlowMeter(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
flowMeterCfg = cfg as FlowMeterCfg;
cBoard = TbfComponents.FindComponent(cfg.ParentName, components) as UniCB;
if (cBoard == null) throw new Exception(string.Format("Cannot find {0} (a parent of {1})", cfg.ParentName, Name));
log.Warn(this.ToString());
}
///
/// IDevice interface functions
///
public void Initialize()
{
for (int r = 0; r <= 5; r++)
{
if (RangeEnabled(r) && flowMeterCfg.GetCalibValidDate(r) != DateTime.MinValue
&& flowMeterCfg.GetCalibValidDate(r).Date < DateTime.Now.Date)
{
throw new Exception(string.Format("{0}/r{1}: {2}", Name, r, Strings.Calibration_certificate_validity_expired));
}
}
TBF.UiBridge.Bridge.MeasurementRequestHandler += delegate(object sender, TBF.UiBridge.MeasurementRequestArgs args)
{
if (args.Name == Name) { cBoard.MeasureFlow(Idx1); }
};
log.FatalFormat("Successfully initialized device {0}", Name);
}
public void RunDeviceBefore() { }
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
///
/// Calendar support
///
public IList<Config.CalendarEvent.ICalendarEvent> GetCalendarEvents()
{
DateTime calibrationDue = flowMeterCfg.CalibValidDate;
IList<Config.CalendarEvent.ICalendarEvent> calendarEvents = new List<Config.CalendarEvent.ICalendarEvent>();
if (calibrationDue > TBF.UI.Constants.MinDate)
{
/// Calibration due date calendar event
calendarEvents.Add(new TBF.UI.Calendar.CalibrationDueDateEvent(calibrationDue.Date, Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat))));
if (DateTime.Now.Date <= calibrationDue.AddDays(-7))
{
/// Weekly reminders (last 5 weeks)
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.Date.AddDays(-35), Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
false));
}
if (DateTime.Now.Date <= calibrationDue.Date)
{
/// Daily reminders (last 5 days)
calendarEvents.Add(new TBF.UI.Calendar.CalibrationReminderEvent(calibrationDue.AddDays(-5), Name,
string.Format(Strings.Calibration_due_date_is_0,
calibrationDue.Date.ToString(TBF.UI.Constants.DateFormat)),
true));
}
}
return calendarEvents;
}
public bool IsActive
{
get
{
if ((cBoard.State & (ulong)StatusP.TestWithRefFlowmtr) == 0)
{
/// Not a test with flow meter
return false;
}
else if ((int)(cBoard.State & (ulong)StatusP.FlowmtrNrMask) == Idx1)
{
/// Flow meter is active, ID matches
return true;
}
else if ((int)(cBoard.State & (ulong)StatusP.FlowmtrNrMask) == 0)
{
/// Measurement with parallel flow meters is active
switch (Idx1)
{
case 1: return (cBoard.State & (ulong)StatusP.Flowmtr1Active) != 0;
case 2: return (cBoard.State & (ulong)StatusP.Flowmtr2Active) != 0;
case 3: return (cBoard.State & (ulong)StatusP.Flowmtr3Active) != 0;
default: return false;
}
}
else
{
return false;
}
}
}
public double ReadFrequency()
{
if ((int)(cBoard.State & (ulong)StatusP.FlowmtrNrMask) == Idx1)
{
return cBoard.RefFrequency;
}
else if (Idx1 == 1 && (cBoard.State & (ulong)StatusP.Flowmtr1Active) != 0)
{
return cBoard.Data.ReferenceFreq[1];
}
else if (Idx1 == 2 && (cBoard.State & (ulong)StatusP.Flowmtr2Active) != 0)
{
return cBoard.Data.ReferenceFreq[2];
}
else if (Idx1 == 3 && (cBoard.State & (ulong)StatusP.Flowmtr3Active) != 0)
{
return cBoard.Data.ReferenceFreq[3];
}
else
{
return 0;
}
}
public double ReadFlow()
{
return flowMeterCfg.NominalFlow * ReadFrequency() / 2000.0;
}
/// <summary>
/// Events: FlowDone, Error
/// </summary>
/// <param name="flow">Reference to a variable for the flow in Bar</param>
/// <returns>ReadFlowOp instance reference casted to IOperaton</returns>
public IOperation ReadFlowOp(ref DoubleBox flow)
{
return new ReadFlowOp(this, ref flow);
}
/// <summary>
/// Events: flowDone, Error
/// </summary>
/// <param name="flow">Reference to a variable for the flow in Bar</param>
/// <param name="flowDone">Event returned when measurement done</param>
/// <returns>ReadFlowOp instance reference casted to IOperaton</returns>
public IOperation ReadFlowOp(ref DoubleBox flow, Event flowDone)
{
return new ReadFlowOp(this, ref flow, flowDone);
}
}
}
+606
View File
@@ -0,0 +1,606 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using Config;
using Config.Entities;
using SchematicDrawing;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.Uni.FlowMeter
{
public class FlowMeterCfg : ComponentCfgBase, GenericDevices.ICalibRangesCfg, IChildComponentCfg, IParamsProvider,
IDrawingItemWithMeasuredVal
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(FlowMeterCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities)
{
var parents = cmpntEntities.Where(x => x.ClassName == "ControlBoard.Uni");
return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents);
}
///
/// Serialized parameters
///
public int Idx1; /// 0 /// 1..7, (DEWA300 : I1+I2=48, I1+I3=80, I2_I3=96, I1+I2+I3=112)
public double NominalFlow; /// 1 /// Nominal flow in m3/h at nominal output frequency (typ. 2000 Hz)
public string MsrdFormat { get; set; } /// 3
public Unit MsrdUnit { get; set; } /// 2
public double MsrdValLimLo { get; set; } /// 4
public double MsrdValLimHi { get; set; } /// 5
public Unit TempUnit; /// 6
public Unit PressureUnit; /// 7
public bool Range1Enabled; /// 8
public double Temp1Lo; /// 9
public double Temp1Hi; /// 10
public double Press1Lo; /// 11
public double Press1Hi; /// 12
public bool Range2Enabled; /// 13
public double Temp2Lo; /// 14
public double Temp2Hi; /// 15
public double Press2Lo; /// 16
public double Press2Hi; /// 17
public bool Range3Enabled; /// 18
public double Temp3Lo; /// 19
public double Temp3Hi; /// 20
public double Press3Lo; /// 21
public double Press3Hi; /// 22
public bool Range4Enabled; /// 23
public double Temp4Lo; /// 24
public double Temp4Hi; /// 25
public double Press4Lo; /// 26
public double Press4Hi; /// 27
public bool Range5Enabled; /// 28
public double Temp5Lo; /// 29
public double Temp5Hi; /// 30
public double Press5Lo; /// 31
public double Press5Hi; /// 32
/// Calibration info serialized parameters displayed in Metrology tab page
public string CalibCertificateNr;
public string CalibCertificate1;
public string CalibCertificate2;
public string CalibCertificate3;
public string CalibCertificate4;
public string CalibCertificate5;
public DateTime CalibDate;
public DateTime CalibDate1;
public DateTime CalibDate2;
public DateTime CalibDate3;
public DateTime CalibDate4;
public DateTime CalibDate5;
public DateTime CalibValidDate;
public DateTime CalibValidDate1;
public DateTime CalibValidDate2;
public DateTime CalibValidDate3;
public DateTime CalibValidDate4;
public DateTime CalibValidDate5;
/// 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 MsrdX { get; set; }
public int MsrdY { get; set; }
public Orient MsrdOrient { get; set; }
[XmlIgnore]
public IList<GNode> GNodes { get; set; }
public bool RangeEnabled(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return !(Range1Enabled || Range2Enabled || Range3Enabled || Range4Enabled || Range5Enabled);
case 1: return Range1Enabled;
case 2: return Range2Enabled;
case 3: return Range3Enabled;
case 4: return Range4Enabled;
case 5: return Range5Enabled;
}
}
public double GetTempLo(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return 5.0; /// °C
case 1: return Temp1Lo;
case 2: return Temp2Lo;
case 3: return Temp3Lo;
case 4: return Temp4Lo;
case 5: return Temp5Lo;
}
}
public double GetTempHi(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return 95.0; /// °C
case 1: return Temp1Hi;
case 2: return Temp2Hi;
case 3: return Temp3Hi;
case 4: return Temp4Hi;
case 5: return Temp5Hi;
}
}
public double GetPressLo(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return 0; /// bar
case 1: return Press1Lo;
case 2: return Press2Lo;
case 3: return Press3Lo;
case 4: return Press4Lo;
case 5: return Press5Lo;
}
}
public double GetPressHi(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return 16.0; /// bar
case 1: return Press1Hi;
case 2: return Press2Hi;
case 3: return Press3Hi;
case 4: return Press4Hi;
case 5: return Press5Hi;
}
}
public string GetCalibCertificate(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return CalibCertificateNr;
case 1: return CalibCertificate1;
case 2: return CalibCertificate2;
case 3: return CalibCertificate3;
case 4: return CalibCertificate4;
case 5: return CalibCertificate5;
}
}
public void SetCalibCertificate(int rangeIx1, string certificate)
{
switch (rangeIx1)
{
default:
case 0: CalibCertificateNr = certificate; return;
case 1: CalibCertificate1 = certificate; return;
case 2: CalibCertificate2 = certificate; return;
case 3: CalibCertificate3 = certificate; return;
case 4: CalibCertificate4 = certificate; return;
case 5: CalibCertificate5 = certificate; return;
}
}
public DateTime GetCalibDate(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return CalibDate;
case 1: return CalibDate1;
case 2: return CalibDate2;
case 3: return CalibDate3;
case 4: return CalibDate4;
case 5: return CalibDate5;
}
}
public void SetCalibDate(int rangeIx1, DateTime calibDate)
{
switch (rangeIx1)
{
default:
case 0: CalibDate = calibDate; return;
case 1: CalibDate1 = calibDate; return;
case 2: CalibDate2 = calibDate; return;
case 3: CalibDate3 = calibDate; return;
case 4: CalibDate4 = calibDate; return;
case 5: CalibDate5 = calibDate; return;
}
}
public DateTime GetCalibValidDate(int rangeIx1)
{
switch (rangeIx1)
{
default:
case 0: return CalibValidDate;
case 1: return CalibValidDate1;
case 2: return CalibValidDate2;
case 3: return CalibValidDate3;
case 4: return CalibValidDate4;
case 5: return CalibValidDate5;
}
}
public void SetCalibValidDate(int rangeIx1, DateTime calibValidDate)
{
switch (rangeIx1)
{
default:
case 0: CalibValidDate = calibValidDate; return;
case 1: CalibValidDate1 = calibValidDate; return;
case 2: CalibValidDate2 = calibValidDate; return;
case 3: CalibValidDate3 = calibValidDate; return;
case 4: CalibValidDate4 = calibValidDate; return;
case 5: CalibValidDate5 = calibValidDate; return;
}
}
/// Private parameterless constructor invoked by all other (public) constructors
FlowMeterCfg()
{
GNodes = new List<GNode>();
}
public FlowMeterCfg(IComponentFactory factory)
: this()
{
Shape = Shape.FlowM;
Sz = Sz.M;
Factory = factory;
Name = "FlowMeter";
ParentName = "UniCB";
InitializeAll();
}
public string ComponentName { get { return Name; } }
public void InitializeAll()
{
Idx1 = 1;
NominalFlow = 1;
MsrdFormat = "{0:F3} m2/h";
MsrdUnit = Unit.m3ph;
MsrdValLimLo = 0;
MsrdValLimHi = NominalFlow;
TempUnit = Unit.C;
PressureUnit = Unit.bar;
Range1Enabled = false;
Temp1Lo = 15;
Temp1Hi = 25;
Press1Lo = 0;
Press1Hi = 16;
Range2Enabled = false;
Temp2Lo = 15;
Temp2Hi = 25;
Press2Lo = 0;
Press2Hi = 16;
Range3Enabled = false;
Temp3Lo = 15;
Temp3Hi = 25;
Press3Lo = 0;
Press3Hi = 16;
Range4Enabled = false;
Temp4Lo = 15;
Temp4Hi = 25;
Press4Lo = 0;
Press4Hi = 16;
Range5Enabled = false;
Temp5Lo = 15;
Temp5Hi = 25;
Press5Lo = 0;
Press5Hi = 16;
LblX = 38;
MsrdX = 38;
MsrdY = 22;
}
string[] paramNames = new string[]
{
"Identification number (1 .. 7)", /// 0
"Nominal flow at 2000Hz [m3/h]", /// 1
"Display format", /// 2
"Unit of flow on a display", /// 3
"Flow limit Lo", /// 4
"Flow limit Hi", /// 5
"Unit of temperature", /// 6
"Unit of pressure", /// 7
"Range 1 enabled", /// 8
"Range 1 : Temperature Lo", /// 9
"Range 1 : Temperature Hi", /// 10
"Range 1 : Pressure Lo", /// 11
"Range 1 : Pressure Hi", /// 12
"Range 2 enabled", /// 13
"Range 2 : Temperature Lo",
"Range 2 : Temperature Hi",
"Range 2 : Pressure Lo",
"Range 2 : Pressure Hi",
"Range 3 enabled",
"Range 3 : Temperature Lo",
"Range 3 : Temperature Hi",
"Range 3 : Pressure Lo",
"Range 3 : Pressure Hi",
"Range 4 enabled",
"Range 4 : Temperature Lo",
"Range 4 : Temperature Hi",
"Range 4 : Pressure Lo",
"Range 4 : Pressure Hi",
"Range 5 enabled",
"Range 5 : Temperature Lo",
"Range 5 : Temperature Hi",
"Range 5 : Pressure Lo",
"Range 5 : Pressure Hi",
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
public ICollection<string> ParamValues(int i)
{
switch (i)
{
case 0:
return new string[] { "1", "2", "3", "4", "5", "6", "7" };
case 3:
return new string[] { "m3/h", "l/h" };
case 6:
return new string[] { "°C", "°F", "K" };
case 7:
return new string[] { "Pa", "hPa", "mbar", "kPa", "inHg", "psi", "bar", "MPa" };
case 8:
case 13:
case 18:
case 23:
case 28:
return new string[] { Strings.yes, Strings.no };
default:
return null;
}
}
public string ToString(int i)
{
switch (i)
{
case 0: return Idx1.ToString();
case 1: return NominalFlow.ToString();
case 2: return MsrdFormat;
case 3: return MsrdUnit.ToDescription();
case 4: return MsrdValLimLo.ToString();
case 5: return MsrdValLimHi.ToString();
case 6: return TempUnit.ToDescription();
case 7: return PressureUnit.ToDescription();
case 8: return Range1Enabled ? Strings.yes : Strings.no;
case 9: return Temp1Lo.ToString();
case 10: return Temp1Hi.ToString();
case 11: return Press1Lo.ToString();
case 12: return Press1Hi.ToString();
case 13: return Range2Enabled ? Strings.yes : Strings.no;
case 14: return Temp2Lo.ToString();
case 15: return Temp2Hi.ToString();
case 16: return Press2Lo.ToString();
case 17: return Press2Hi.ToString();
case 18: return Range3Enabled ? Strings.yes : Strings.no;
case 19: return Temp3Lo.ToString();
case 20: return Temp3Hi.ToString();
case 21: return Press3Lo.ToString();
case 22: return Press3Hi.ToString();
case 23: return Range4Enabled ? Strings.yes : Strings.no;
case 24: return Temp4Lo.ToString();
case 25: return Temp4Hi.ToString();
case 26: return Press4Lo.ToString();
case 27: return Press4Hi.ToString();
case 28: return Range5Enabled ? Strings.yes : Strings.no;
case 29: return Temp5Lo.ToString();
case 30: return Temp5Hi.ToString();
case 31: return Press5Lo.ToString();
case 32: return Press5Hi.ToString();
default:
return string.Format("{0}({1}) {2}[{3},{4}] Idx1={5}, NominalFlow={6}",
Name, (string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
Shape, X, Y, Idx1, NominalFlow);
}
}
public CfgUpdateFlags UpdateParam(int i, string str)
{
switch (i)
{
case 0: Idx1 = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 1: NominalFlow = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 2: MsrdFormat = str; return CfgUpdateFlags.RestartRqrd;
case 3: MsrdUnit = (str == "l/h") ? Unit.lph : Unit.m3ph; return CfgUpdateFlags.RestartRqrd;
case 4: MsrdValLimLo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 5: MsrdValLimHi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 6: TempUnit.ToDescription(); return CfgUpdateFlags.RestartRqrd;
case 7: PressureUnit.ToDescription(); return CfgUpdateFlags.RestartRqrd;
case 8: Range1Enabled = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 9: Temp1Lo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 10: Temp1Hi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 11: Press1Lo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 12: Press1Hi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 13: Range2Enabled = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 14: Temp2Lo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 15: Temp2Hi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 16: Press2Lo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 17: Press2Hi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 18: Range3Enabled = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 19: Temp3Lo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 20: Temp3Hi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 21: Press3Lo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 22: Press3Hi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 23: Range4Enabled = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 24: Temp4Lo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 25: Temp4Hi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 26: Press4Lo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 27: Press4Hi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 28: Range5Enabled = (str == Strings.yes); return CfgUpdateFlags.RestartRqrd;
case 29: Temp5Lo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 30: Temp5Hi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd;
case 31: Press5Lo = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
case 32: Press5Hi = TBF.Utils.ParseUDouble(str); return CfgUpdateFlags.RestartRqrd;
default: return CfgUpdateFlags.None;
}
}
public bool ValidateParam(int i, string str, out string message)
{
message = string.Empty;
int idummy;
double dummy;
switch (i)
{
case 0:
if (int.TryParse(str, out idummy) && idummy >= 1 && idummy <= 7) return true;
break;
case 1:
case 4:
case 5:
case 11:
case 12:
case 16:
case 17:
case 21:
case 22:
case 26:
case 27:
case 31:
case 32:
if (TBF.Utils.TryParseUDouble(str, out dummy)) return true;
break;
case 9:
case 10:
case 14:
case 15:
case 19:
case 20:
case 24:
case 25:
case 29:
case 30:
if (TBF.Utils.TryParseSDouble(str, out dummy)) return true;
break;
case 2:
return true;
case 3:
case 6:
case 7:
case 8:
case 13:
case 18:
case 23:
case 28:
if (ParamValues(i).Contains(str)) return true;
break;
default:
message = "Invalid index";
return false;
}
message = ParamName(i) + " is invalid";
return false;
}
void CopyContentTo(FlowMeterCfg prms)
{
prms.ParentName = ParentName;
prms.Idx1 = Idx1;
prms.NominalFlow = NominalFlow;
prms.MsrdFormat = MsrdFormat;
prms.MsrdUnit = MsrdUnit;
prms.MsrdValLimLo = MsrdValLimLo;
prms.MsrdValLimHi = MsrdValLimHi;
prms.TempUnit = TempUnit;
prms.PressureUnit = PressureUnit;
prms.Range1Enabled = Range1Enabled;
prms.Temp1Lo = Temp1Lo;
prms.Temp1Hi = Temp1Hi;
prms.Press1Lo = Press1Lo;
prms.Press1Hi = Press1Hi;
prms.Range2Enabled = Range2Enabled;
prms.Temp2Lo = Temp2Lo;
prms.Temp2Hi = Temp2Hi;
prms.Press2Lo = Press2Lo;
prms.Press2Hi = Press2Hi;
prms.Range3Enabled = Range3Enabled;
prms.Temp3Lo = Temp3Lo;
prms.Temp3Hi = Temp3Hi;
prms.Press3Lo = Press3Lo;
prms.Press3Hi = Press3Hi;
prms.Range4Enabled = Range4Enabled;
prms.Temp4Lo = Temp4Lo;
prms.Temp4Hi = Temp4Hi;
prms.Press4Lo = Press4Lo;
prms.Press4Hi = Press4Hi;
prms.Range5Enabled = Range5Enabled;
prms.Temp5Lo = Temp5Lo;
prms.Temp5Hi = Temp5Hi;
prms.Press5Lo = Press5Lo;
prms.Press5Hi = Press5Hi;
}
public Config.Entities.IParamsProvider Clone()
{
FlowMeterCfg pars = new FlowMeterCfg();
CopyContentTo(pars);
return pars;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
}
}
}
+63
View File
@@ -0,0 +1,63 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.Rig.Uni.FlowMeter
{
public class ReadFlowOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadFlowOp));
public override string ToString() { return string.Format("ReadFlowOp({0},.,.,{1})", flowMeter.Idx1, eventDone); }
/// Set by the constructor
readonly FlowMeter flowMeter;
readonly DoubleBox flowBox;
readonly Event eventDone;
/// <summary>
/// Events: FlowInDone, FlowOutDone or Error
/// </summary>
/// <param name="flowMeter">Flow meter reference</param>
/// <param name="flowBox">Reference to the measured flow variable, value is in bar</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public ReadFlowOp(FlowMeter flowMeter, ref DoubleBox flowBox, Event eventDone)
{
if (flowMeter == null) throw new ArgumentNullException();
this.flowMeter = flowMeter;
this.eventDone = eventDone;
this.flowBox = flowBox;
log.Debug(this.ToString());
}
public ReadFlowOp(FlowMeter flowMeter, ref DoubleBox flowBox)
: this(flowMeter, ref flowBox, Event.FlowMeasurementDone)
{
}
/// <summary>Start this operation</summary>
public void Start() { }
/// <summary>Run this operation</summary>
/// <returns>
/// Event.FlowInDone or Event.FlowOutDone
/// </returns>
public Event Run()
{
if (flowMeter.IsActive)
{
flowBox.Val = flowMeter.ReadFlow();
return eventDone;
}
return Event.Error;
}
/// <summary>Stop this operation</summary>
public void Stop() { }
}
}
@@ -0,0 +1,78 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.Uni.RegValve
{
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 TBF.Rig.ControlBoard.Legacy.CBoard controlBoard;
readonly RegValve regulValve;
readonly int regulValveNr;
readonly double timePulseSec;
/// <summary>
/// Set required water flow.
/// Events: FlowSet, FlowTimeOut
/// </summary>
/// <param name="cb">Control board device</param>
/// <param name="rv">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(TBF.Rig.ControlBoard.IControlBoard cb, RegValve rv, double timePulseSec)
{
controlBoard = cb as TBF.Rig.ControlBoard.Legacy.CBoard;
if (controlBoard == null) throw new ArgumentNullException("ctrlBoard");
regulValve = rv as 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,
TBF.Rig.ControlBoard.Legacy.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()
{
}
}
}
+27
View File
@@ -0,0 +1,27 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.Uni.RegValve
{
public class Factory : IComponentFactory
{
public string ClassName { get { return "RegValve"; } }
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);
}
}
}
+36
View File
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.Rig.Uni.RegValve
{
static class Handlers
{
static readonly ILog log = LogManager.GetLogger(typeof(Handlers));
static Handlers()
{
}
/// <summary>
/// Called from the state machine when a procedure is selected and UI needs to be updated.
/// </summary>
public static void OnAdcChanged(object sender, CmdResponseArgs data)
{
if (AdcChangedHandler == null)
return;
try
{
AdcChangedHandler(sender, data);
}
catch (Exception e)
{
log.Error("AdcChangedHandler(...) failed", e);
}
}
public static event EventHandler<CmdResponseArgs> AdcChangedHandler;
}
}
+223
View File
@@ -0,0 +1,223 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using log4net;
using SchematicDrawing;
using TBF.Rig.ControlBoard.Uni;
using TBF.Rig.Generic;
using TBF.Boxes;
namespace TBF.Rig.Uni.RegValve
{
public class RegValve : ComponentBase, IDevice, GenericDevices.IRegValve, IDrawingItCmpntWithSetpoint
{
private static readonly ILog log = LogManager.GetLogger(typeof(RegValve));
public override string ToString() { return string.Format("RegulValve({0})", Cfg.ToString(1)); }
public readonly RegValveCfg regValveCfg;
public IDrawingItem DrawingItem { get { return regValveCfg as IDrawingItem; } }
IDictionary<double, double> dict;
public IDictionary<double, double> Dict { get { return dict; } }
readonly UniCB uniCB;
readonly int adcChannel;
public ValveCategory Category { get { return regValveCfg.Category; } }
public int Idx1 { get { return regValveCfg.Idx1; } } /// 1 .. 8
public int DacValueClosed { get { return regValveCfg.AdcValueClosed; } } /// 0 .. 1023
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 IsCoax { get { return false; } }
/// 0.0 .. 100.0
public double Position
{
get
{
int denominator = DacValueOpen - DacValueClosed;
if (denominator == 0) denominator = 1;
return 100.0 * Convert.ToDouble(uniCB.AnalogInput(adcChannel) - DacValueClosed) / Convert.ToDouble(denominator);
}
}
///
public double SetpointVal
{
get { return Position; }
set { TargetRegValvePosition = value; }
}
///
public void IncreaseSetpoint()
{
/// TODO
}
///
public void DecreaseSetpoint()
{
/// TODO
}
public RegValveState RegValveState;
public double TargetRegValvePosition;
public void SendCommand(Command command, int v1, int v2, int v3, StopDevs v4)
{
/// TODO
}
public void SetFlow(int flowMeterId, double freqLo, double freqHi)
{
uniCB.SetFlow(flowMeterId, Idx1, freqLo, freqHi);
}
/// <summary>
/// Incremental movement of the regulation valve.
/// </summary>
/// <param name="time">Time in seconds, positive value opens the reg. valve</param>
public void IncrementalMovement(double time)
{
uniCB.RegVlvIncrMove(Idx1, time);
}
/// <summary>
/// Move a regulation valve to specfied position
/// </summary>
/// <param name="rvId">Reg. valve ID</param>
/// <param name="position">Reg. valve position (0 .. 1.0)</param>
public void MoveToPosition(double positionLo, double positionHi = -1)
{
uniCB.RegVlvMoveToPos(Idx1, positionLo, positionHi);
}
#region Configuration Change Handling
public static void OnCfgChange(object sender, CfgChangeArgs args)
{
if (CfgChangeHandler == null) return;
try { CfgChangeHandler(sender, args); }
catch (Exception e) { log.Error("CfgChangeHandler(...) failed", e); }
}
public static event EventHandler<CfgChangeArgs> CfgChangeHandler;
public override void StartChangeHandler()
{
CfgChangeHandler += delegate(object sender, CfgChangeArgs args)
{
RegValveCfg tmpcfg = args.Cfg as RegValveCfg;
if (tmpcfg != null && tmpcfg.Name.Equals(Name))
{
if (args.Command == CfgChangeCmd.CfgChange)
{
regValveCfg.StableTimeMs = tmpcfg.StableTimeMs;
regValveCfg.FlowStableSec = tmpcfg.FlowStableSec;
}
else if (args.Command == CfgChangeCmd.RVOpenStep)
{
IncrementalMovement(0.5);
}
else if (args.Command == CfgChangeCmd.RVCloseStep)
{
IncrementalMovement(-0.5);
}
else if (args.Command == CfgChangeCmd.GetAdc1 || args.Command == CfgChangeCmd.GetAdc2)
{
short adcValue = uniCB.AnalogInput(adcChannel);
RegValveCfgCtrl.OnCmdResponse(this, new CmdResponseArgs(args.Command, Idx1, adcValue));
}
}
};
}
#endregion Configuration Change Handling
public RegValve()
{
}
public RegValve(Generic.IComponentCfg cfg, IList<Generic.IComponent> components)
: base(cfg)
{
regValveCfg = cfg as RegValveCfg;
adcChannel = regValveCfg.Idx1 - 1;
this.uniCB = TbfComponents.FindComponent(cfg.ParentName, components) as UniCB;
if (this.uniCB == null) throw new Exception(string.Format("Cannot find {0} (a parent of {1})", cfg.ParentName, Name));
this.dict = new Dictionary<double, double>();
log.Warn(this.ToString());
}
///
/// IDevice interface implementation
///
public void Initialize() { }
public void RunDeviceBefore()
{
Int16 adcValue = uniCB.AnalogInput(adcChannel);
Handlers.OnAdcChanged(this, new CmdResponseArgs(CfgChangeCmd.GetAdc, Idx1, adcValue));
}
public void RunDeviceAfter() { }
public void StopDevice() { }
public void StopDevice2() { }
/// <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(uniCB, this, flowMeter, requiredFlowLo, requiredFlowHi, 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="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(uniCB, this, flowMeter, requiredFlowLo, requiredFlowHi, 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 SetRegValvePositionOp(uniCB, this, pctLo, pctHi, timeoutMs);
}
public IOperation ChangeRegulValvePositionOp(double timePulseSec)
{
return new ChangeRegulValvePositionOp(uniCB, this, timePulseSec);
}
}
}
+108
View File
@@ -0,0 +1,108 @@
///
/// 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.RegValve
{
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<Component> cmpntEntities)
{
return new RegValveCfgCtrl();
}
///
/// Serialized parameters
///
public int Idx1; /// 1..8
public ValveCategory Category; /// Feeding, Output or All
public int AdcValueClosed; /// 0..1023
public int AdcValueOpen; /// 0..1023
public int StableTimeMs; /// 200..1500 ms, step is 50 ms
public int FlowStableSec; /// 0..60 sec
public bool StoredPositionReuse; /// true = store and re-use previous regulation valve positions
public bool ReTryCommands;
public string SetpFormat { get; set; }
public Config.Unit SetpUnit { get; set; }
/// 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; }
[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 = "UniCB";
Category = ValveCategory.Output;
Idx1 = 1;
AdcValueClosed = 100;
AdcValueOpen = 500;
StableTimeMs = 500;
FlowStableSec = 5;
StoredPositionReuse = false;
ReTryCommands = false;
LblX = 38;
SetpX = 38;
SetpY = 22;
}
public string ToString(int i)
{
return string.Format("Name={0} ({1}), Idx1={2}, Cat.={3}, ADC-Closed={4}, ADC-Open={5}, StabTm={6}ms, FlowStable={7}s, PosReuse={8}, ReTryCmds={9}",
Name,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
Idx1,
Category,
AdcValueClosed,
AdcValueOpen,
StableTimeMs,
FlowStableSec,
StoredPositionReuse,
ReTryCommands);
}
}
}
+377
View File
@@ -0,0 +1,377 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Linq;
using System.Windows.Forms;
using log4net;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.UI.Bench.Components;
namespace TBF.Rig.Uni.RegValve
{
public partial class RegValveCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(RegValveCfgCtrl));
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 c in parent.CmpntEntities.Where(x => x.ClassName == "ControlBoard.Uni"))
{
parentNameComboBox.Items.Add(c.Name);
}
}
categoryComboBox.Items.Add(ValveCategory.Feeding.ToString());
categoryComboBox.Items.Add(ValveCategory.Output.ToString());
if (config != null)
{
adc1 = config.AdcValueClosed;
pct1 = 0;
adc2 = config.AdcValueOpen;
pct2 = 100;
}
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();
StartResponseHandler();
}
public void Closing()
{
StopResponseHandler();
}
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();
adcClosedTextBox.Text = config.AdcValueClosed.ToString();
adcOpenTextBox.Text = config.AdcValueOpen.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();
adcTextBox1.Text = adc1.ToString();
adcTextBox2.Text = adc2.ToString();
pctTextBox1.Text = pct1.ToString();
pctTextBox2.Text = pct2.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
categoryComboBox.Enabled = true;
positionTextBox.Enabled = true;
adcClosedTextBox.Enabled = true;
adcOpenTextBox.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(adcClosedTextBox.Text, out dummy) || dummy < 0 || dummy > 1023)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'ADC when Closed' should be between 0 and 1023";
}
if (!int.TryParse(adcOpenTextBox.Text, out dummy) || dummy < 0 || dummy > 1023)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'ADC when Open' should be between 0 and 1023";
}
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(adcClosedTextBox.Text);
if (config.AdcValueClosed != tmp)
{
config.AdcValueClosed = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(adcOpenTextBox.Text);
if (config.AdcValueOpen != tmp)
{
config.AdcValueOpen = tmp;
flags |= CfgUpdateFlags.RestartRqrd;
}
tmp = int.Parse(stableTimeTextBox.Text);
if (config.StableTimeMs != tmp)
{
config.StableTimeMs = tmp;
flags |= CfgUpdateFlags.AnyChange;
}
tmp = int.Parse(flowStableSecTextBox.Text);
if (config.FlowStableSec != tmp)
{
config.FlowStableSec = tmp;
flags |= CfgUpdateFlags.AnyChange;
}
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;
}
if ((flags & CfgUpdateFlags.AnyChange) != 0)
{
RegValve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.CfgChange, config));
}
config.SetpFormat = formatTextBox.Text;
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;
}
int adc1;
int pct1;
int adc2;
int pct2;
private void openButton_Click(object sender, EventArgs e)
{
RegValve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.RVOpenStep, config));
}
private void closeButton_Click(object sender, EventArgs e)
{
RegValve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.RVCloseStep, config));
}
//
private void getButton1_Click(object sender, EventArgs e)
{
RegValve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.GetAdc1, config));
}
private void getButton2_Click(object sender, EventArgs e)
{
RegValve.OnCfgChange(this, new CfgChangeArgs(CfgChangeCmd.GetAdc2, config));
}
private void setButton_Click(object sender, EventArgs e)
{
int tmpPct1;
int tmpPct2;
if ((int.TryParse(pctTextBox1.Text, out tmpPct1) && (tmpPct1 >= 0) && (tmpPct1 <= 100)) &&
(int.TryParse(pctTextBox2.Text, out tmpPct2) && (tmpPct2 >= 0) && (tmpPct2 <= 100)))
{
pct1 = tmpPct1;
pct2 = tmpPct2;
UpdateValveOpenClose();
}
}
void UpdateValveOpenClose()
{
if ((adc1 == adc2) || (pct1 == pct2)) return;
double factor = (float)(adc2 - adc1) / (float)(pct2 - pct1);
int adcClosed = (int)((float)(0 - pct1) * factor + (float)adc1 + 0.5f);
int adcOpen = (int)((float)(100 - pct1) * factor + (float)adc1 + 0.5f);
if ((adcClosed >= 0) && (adcOpen >= 0))
{
adcClosedTextBox.Text = adcClosed.ToString();
adcOpenTextBox.Text = adcOpen.ToString();
}
}
#region Configuration Change Handling
public static void OnCmdResponse(object sender, CmdResponseArgs args)
{
if (CmdResponseHandler == null) return;
try { CmdResponseHandler(sender, args); }
catch (Exception e) { log.Error("CmdResponseHandler(...) failed", e); }
}
public static event EventHandler<CmdResponseArgs> CmdResponseHandler;
public void StartResponseHandler()
{
Handlers.AdcChangedHandler += delegate(object sndr, CmdResponseArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<CmdResponseArgs>(OnAdcChanged), sndr, args); }
else OnAdcChanged(sndr, args);
};
CmdResponseHandler += delegate(object sender, CmdResponseArgs args)
{
if (args.Command == CfgChangeCmd.GetAdc1)
{
adc1 = args.Response;
adcTextBox1.Text = adc1.ToString();
}
else if (args.Command == CfgChangeCmd.GetAdc2)
{
adc2 = args.Response;
adcTextBox2.Text = adc2.ToString();
}
};
}
public void StopResponseHandler()
{
CmdResponseHandler = null;
}
void OnAdcChanged(object sender, CmdResponseArgs data)
{
if (data.Command == CfgChangeCmd.GetAdc && data.Id == config.Idx1)
{
adcTextBox.Text = data.Response.ToString();
}
}
#endregion Configuration Change Handling
}
}
+570
View File
@@ -0,0 +1,570 @@
///
/// Copyright (c) 2021 Sensus Metering Systems
///
namespace TBF.Rig.Uni.RegValve
{
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.adcClosedLabel = new System.Windows.Forms.Label();
this.adcClosedTextBox = new System.Windows.Forms.TextBox();
this.adcOpenTextBox = new System.Windows.Forms.TextBox();
this.adcOpenLabel = 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.groupBox1 = new System.Windows.Forms.GroupBox();
this.setButton1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.ADC = new System.Windows.Forms.Label();
this.getButton1 = new System.Windows.Forms.Button();
this.pctTextBox1 = new System.Windows.Forms.TextBox();
this.adcTextBox1 = new System.Windows.Forms.TextBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.setButton2 = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.getButton2 = new System.Windows.Forms.Button();
this.pctTextBox2 = new System.Windows.Forms.TextBox();
this.adcTextBox2 = new System.Windows.Forms.TextBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.closeButton = new System.Windows.Forms.Button();
this.openButton = new System.Windows.Forms.Button();
this.adcTextBox = new System.Windows.Forms.TextBox();
this.groupBox4 = new System.Windows.Forms.GroupBox();
this.label4 = new System.Windows.Forms.Label();
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.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.groupBox4.SuspendLayout();
this.SuspendLayout();
//
// positionTextBox
//
this.positionTextBox.Enabled = false;
this.positionTextBox.Location = new System.Drawing.Point(138, 114);
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, 117);
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";
//
// adcClosedLabel
//
this.adcClosedLabel.AutoSize = true;
this.adcClosedLabel.Location = new System.Drawing.Point(28, 141);
this.adcClosedLabel.Name = "adcClosedLabel";
this.adcClosedLabel.Size = new System.Drawing.Size(93, 13);
this.adcClosedLabel.TabIndex = 9;
this.adcClosedLabel.Text = "ADC when Closed";
//
// adcClosedTextBox
//
this.adcClosedTextBox.Enabled = false;
this.adcClosedTextBox.Location = new System.Drawing.Point(138, 138);
this.adcClosedTextBox.Name = "adcClosedTextBox";
this.adcClosedTextBox.Size = new System.Drawing.Size(46, 20);
this.adcClosedTextBox.TabIndex = 10;
//
// adcOpenTextBox
//
this.adcOpenTextBox.Enabled = false;
this.adcOpenTextBox.Location = new System.Drawing.Point(138, 162);
this.adcOpenTextBox.Name = "adcOpenTextBox";
this.adcOpenTextBox.Size = new System.Drawing.Size(46, 20);
this.adcOpenTextBox.TabIndex = 12;
//
// adcOpenLabel
//
this.adcOpenLabel.AutoSize = true;
this.adcOpenLabel.Location = new System.Drawing.Point(28, 165);
this.adcOpenLabel.Name = "adcOpenLabel";
this.adcOpenLabel.Size = new System.Drawing.Size(87, 13);
this.adcOpenLabel.TabIndex = 11;
this.adcOpenLabel.Text = "ADC when Open";
//
// 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, 239);
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, 186);
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, 189);
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, 210);
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, 213);
this.flowStableSecLabel.Name = "flowStableSecLabel";
this.flowStableSecLabel.Size = new System.Drawing.Size(74, 13);
this.flowStableSecLabel.TabIndex = 15;
this.flowStableSecLabel.Text = "Flow stable [s]";
//
// groupBox1
//
this.groupBox1.Controls.Add(this.setButton1);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Controls.Add(this.ADC);
this.groupBox1.Controls.Add(this.getButton1);
this.groupBox1.Controls.Add(this.pctTextBox1);
this.groupBox1.Controls.Add(this.adcTextBox1);
this.groupBox1.Location = new System.Drawing.Point(10, 398);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(280, 59);
this.groupBox1.TabIndex = 19;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Measured value 1";
//
// setButton1
//
this.setButton1.Location = new System.Drawing.Point(229, 17);
this.setButton1.Name = "setButton1";
this.setButton1.Size = new System.Drawing.Size(38, 33);
this.setButton1.TabIndex = 5;
this.setButton1.Text = "Set";
this.setButton1.UseVisualStyleBackColor = true;
this.setButton1.Click += new System.EventHandler(this.setButton_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(209, 28);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(15, 13);
this.label1.TabIndex = 4;
this.label1.Text = "%";
//
// ADC
//
this.ADC.AutoSize = true;
this.ADC.Location = new System.Drawing.Point(11, 28);
this.ADC.Name = "ADC";
this.ADC.Size = new System.Drawing.Size(32, 13);
this.ADC.TabIndex = 3;
this.ADC.Text = "ADC:";
//
// getButton1
//
this.getButton1.Location = new System.Drawing.Point(101, 18);
this.getButton1.Name = "getButton1";
this.getButton1.Size = new System.Drawing.Size(38, 33);
this.getButton1.TabIndex = 2;
this.getButton1.Text = "Get";
this.getButton1.UseVisualStyleBackColor = true;
this.getButton1.Click += new System.EventHandler(this.getButton1_Click);
//
// pctTextBox1
//
this.pctTextBox1.Location = new System.Drawing.Point(160, 24);
this.pctTextBox1.Name = "pctTextBox1";
this.pctTextBox1.Size = new System.Drawing.Size(46, 20);
this.pctTextBox1.TabIndex = 1;
//
// adcTextBox1
//
this.adcTextBox1.Location = new System.Drawing.Point(47, 24);
this.adcTextBox1.Name = "adcTextBox1";
this.adcTextBox1.Size = new System.Drawing.Size(44, 20);
this.adcTextBox1.TabIndex = 0;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.setButton2);
this.groupBox2.Controls.Add(this.label2);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.getButton2);
this.groupBox2.Controls.Add(this.pctTextBox2);
this.groupBox2.Controls.Add(this.adcTextBox2);
this.groupBox2.Location = new System.Drawing.Point(10, 462);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(280, 59);
this.groupBox2.TabIndex = 20;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Measured value 2";
//
// setButton2
//
this.setButton2.Location = new System.Drawing.Point(229, 17);
this.setButton2.Name = "setButton2";
this.setButton2.Size = new System.Drawing.Size(38, 33);
this.setButton2.TabIndex = 5;
this.setButton2.Text = "Set";
this.setButton2.UseVisualStyleBackColor = true;
this.setButton2.Click += new System.EventHandler(this.setButton_Click);
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(209, 28);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(15, 13);
this.label2.TabIndex = 4;
this.label2.Text = "%";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(11, 27);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(32, 13);
this.label3.TabIndex = 3;
this.label3.Text = "ADC:";
//
// getButton2
//
this.getButton2.Location = new System.Drawing.Point(101, 18);
this.getButton2.Name = "getButton2";
this.getButton2.Size = new System.Drawing.Size(38, 33);
this.getButton2.TabIndex = 2;
this.getButton2.Text = "Get";
this.getButton2.UseVisualStyleBackColor = true;
this.getButton2.Click += new System.EventHandler(this.getButton2_Click);
//
// pctTextBox2
//
this.pctTextBox2.Location = new System.Drawing.Point(160, 24);
this.pctTextBox2.Name = "pctTextBox2";
this.pctTextBox2.Size = new System.Drawing.Size(46, 20);
this.pctTextBox2.TabIndex = 1;
//
// adcTextBox2
//
this.adcTextBox2.Location = new System.Drawing.Point(47, 24);
this.adcTextBox2.Name = "adcTextBox2";
this.adcTextBox2.Size = new System.Drawing.Size(44, 20);
this.adcTextBox2.TabIndex = 0;
//
// 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);
//
// adcTextBox
//
this.adcTextBox.Location = new System.Drawing.Point(47, 14);
this.adcTextBox.Name = "adcTextBox";
this.adcTextBox.Size = new System.Drawing.Size(44, 20);
this.adcTextBox.TabIndex = 21;
//
// groupBox4
//
this.groupBox4.Controls.Add(this.label4);
this.groupBox4.Controls.Add(this.adcTextBox);
this.groupBox4.Location = new System.Drawing.Point(10, 352);
this.groupBox4.Name = "groupBox4";
this.groupBox4.Size = new System.Drawing.Size(279, 40);
this.groupBox4.TabIndex = 22;
this.groupBox4.TabStop = false;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(11, 17);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(32, 13);
this.label4.TabIndex = 22;
this.label4.Text = "ADC:";
//
// 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, 262);
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, 309);
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, 312);
this.unitsLabel.Name = "unitsLabel";
this.unitsLabel.Size = new System.Drawing.Size(78, 13);
this.unitsLabel.TabIndex = 31;
this.unitsLabel.Text = "Unit of setpoint";
//
// formatTextBox
//
this.formatTextBox.Enabled = false;
this.formatTextBox.Location = new System.Drawing.Point(138, 285);
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, 288);
this.formatLabel.Name = "formatLabel";
this.formatLabel.Size = new System.Drawing.Size(78, 13);
this.formatLabel.TabIndex = 29;
this.formatLabel.Text = "Setpoint format";
//
// RegValveCfgCtrl
//
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.groupBox4);
this.Controls.Add(this.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
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.adcOpenTextBox);
this.Controls.Add(this.adcOpenLabel);
this.Controls.Add(this.adcClosedTextBox);
this.Controls.Add(this.adcClosedLabel);
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 = "RegValveCfgCtrl";
this.Size = new System.Drawing.Size(300, 700);
this.Load += new System.EventHandler(this.RegulationValveCfgCtrl_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox4.ResumeLayout(false);
this.groupBox4.PerformLayout();
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.Label adcClosedLabel;
private System.Windows.Forms.TextBox adcClosedTextBox;
private System.Windows.Forms.TextBox adcOpenTextBox;
private System.Windows.Forms.Label adcOpenLabel;
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 groupBox1;
private System.Windows.Forms.Button setButton1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label ADC;
private System.Windows.Forms.Button getButton1;
private System.Windows.Forms.TextBox pctTextBox1;
private System.Windows.Forms.TextBox adcTextBox1;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button setButton2;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Button getButton2;
private System.Windows.Forms.TextBox pctTextBox2;
private System.Windows.Forms.TextBox adcTextBox2;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.Button closeButton;
private System.Windows.Forms.Button openButton;
private System.Windows.Forms.TextBox adcTextBox;
private System.Windows.Forms.GroupBox groupBox4;
private System.Windows.Forms.Label label4;
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;
}
}
+120
View File
@@ -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,19 @@
///
/// 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;
}
}
}
+449
View File
@@ -0,0 +1,449 @@
///
/// 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.RegValve
{
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})", regV.Name, shrinkedTgtFlowLo, shrinkedTgtFlowHi);
}
/// Set by the constructor
readonly UniCB cBoard;
readonly RegValve regV;
readonly int regulValveNr;
readonly IFlowMeter flowMeter;
readonly double shrinkedTgtFlowLo;
readonly double shrinkedTgtFlowHi;
readonly double targetFlowAve;
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 startTime;
int expireTime;
DoubleBox flowBox;
int flowWithinBoundsTime;
/// <summary>
/// Set required water flow. Conditionally leave the measurement running.
/// Events: FlowSet, FlowTimeOut
/// </summary>
/// <param name="cBoard">Control board device</param>
/// <param name="regulValve">Regulation valve component</param>
/// <param name="flowMeter">Flowmeter component</param>
/// <param name="targetFlowLo">Lower limit of the flow to be achieved in [m3/h]</param>
/// <param name="targetFlowHi">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(UniCB cBoard, IRegValve regValve, IFlowMeter flowMeter, double targetFlowLo, double targetFlowHi,
DoubleBox flowBox, bool reTryCmds, int timeout, bool leaveMeasurementRunning)
{
this.cBoard = cBoard;
if (this.cBoard == null) throw new ArgumentNullException("cBoard is null or not Uni");
this.regV = regValve as RegValve;
if (this.regV == null) throw new ArgumentNullException("regValve is null or not Uni");
this.flowMeter = flowMeter;
if (this.flowMeter == null) throw new ArgumentNullException("flowMeter");
nominalFlow = flowMeter.NominalFlow;
maximalFlow = nominalFlow * 1.25;
this.targetFlowAve = (targetFlowLo + targetFlowHi) / 2;
this.shrinkedTgtFlowLo = (0.7 * targetFlowLo) + (0.3 * this.targetFlowAve); /// Move the lower limit 15% of the range up
this.shrinkedTgtFlowHi = (0.7 * targetFlowHi) + (0.3 * this.targetFlowAve); /// Move the upper limit 15% of the range down
this.flowBox = flowBox;
if (this.flowBox == null) throw new ArgumentNullException("flowBox");
this.reTryCommands = reTryCmds;
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(UniCB cBoard, IRegValve regValve, IFlowMeter flowMeter, double targetFlowLo, double targetFlowHi,
DoubleBox flowbox, bool reTryCmds, int timeout)
: this(cBoard, regValve, flowMeter, targetFlowLo, targetFlowHi, flowbox, reTryCmds, timeout, false)
{
}
/// <summary>
/// Set required water flow - No timeout.
/// Events: FlowSet
/// </summary>
public SetFlowOp(UniCB cBoard, IRegValve regValve, IFlowMeter flowMeter, double targetFlowLo, double targetFlowHi,
DoubleBox flowbox, bool reTryCmds)
: this(cBoard, regValve, flowMeter, targetFlowLo, targetFlowHi, flowbox, 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 (regV.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;
positionHi = 0;
return false;
}
}
void StoreTargetPosition(double avgReqFlow, double actPosition)
{
if (!regV.Dict.ContainsKey(targetFlowAve))
{
regV.Dict.Add(new KeyValuePair<double, double>(avgReqFlow, actPosition));
}
return;
}
/// <summary>Start this operation</summary>
public void Start()
{
startTime = StateMachine.Time;
expireTime = StateMachine.Time + timeout;
if (expireTime < 0) expireTime = int.MaxValue;
double flowMtrFreq = flowMeter.ReadFrequency();
double flow = flowMeter.ReadFlow();
currentReqFlowLo = shrinkedTgtFlowLo; /// Default lower limit
currentReqFlowHi = shrinkedTgtFlowHi; /// Default upper limit
if (flow != 0)
{
flowBox.Val = flow;
if (flow >= targetFlowAve) currentReqFlowHi = targetFlowAve; /// Decrease upper limit
if (flow <= targetFlowAve) currentReqFlowLo = targetFlowAve; /// Increase lower limit
}
flowWithinBoundsTime = 0;
if (regV.regValveCfg.StoredPositionReuse && FetchTargetPosition(targetFlowAve, out targetPositionLo, out targetPositionHi))
{
log.InfoFormat("SetFlowOp:Start() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
regulValveNr, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
opState = OpState.ValveMoveToPosition1;
}
else
{
log.InfoFormat("SetFlowOp:Start() rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
regulValveNr, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi);
opState = OpState.ValveMoveToFlow1;
}
/// Start flow measurement
regV.SendCommand(Command.Start, int.MaxValue, int.MaxValue, 0, 0); /// TestMethods=0, StopDevs=0
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.OpArgumentError
/// Event.Starting
/// Event.Busy
/// Event.FlowReached
/// Event.RegulValveTimeOut
/// </returns>
public Event Run()
{
double rvPosition = regV.Position;
double flowMtrFreq = flowMeter.ReadFrequency();
double flow = flowMeter.ReadFlow();
if (flow != 0)
{
flowBox.Val = flow;
}
log.InfoFormat("SetFlowOp:Run(T={0}) rv#={1} pos={2}% freq={3} flow={4} opState={5}",
StateMachine.Time - startTime, regulValveNr, rvPosition.ToString("F1"), flowMtrFreq, flow, opState);
if (StateMachine.Time > expireTime)
{
return Event.RegulValveTimeOut;
}
else if (opState == OpState.SendCommandAgain)
{
flowWithinBoundsTime = 0;
if (regV.regValveCfg.StoredPositionReuse && FetchTargetPosition(targetFlowAve, out targetPositionLo, out targetPositionHi))
{
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3} FETCHED: posLo={4} posHi={5}",
regulValveNr, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi, targetPositionLo, targetPositionHi);
opState = OpState.ValveMoveToPosition1;
}
else
{
log.InfoFormat("Run(): rv#={0} flowMtr#={1} TARGET: flowLo={2} flowHi={3}",
regulValveNr, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi);
opState = OpState.ValveMoveToFlow1;
}
/// Start flow measurement
regV.SendCommand(Command.Start, int.MaxValue, int.MaxValue, 0, 0); /// TestMethods=0, StopDevs=0
return Event.Starting;
}
else if (opState == OpState.ValveMoveToPosition1)
{
opState = OpState.ValveMoveToPosition2;
return Event.Starting;
}
else if (opState == OpState.ValveMoveToPosition2) /// Move to position
{
/// Issues the appropriate ValveMove(...) command
regV.MoveToPosition(targetPositionLo, targetPositionHi);
opState = OpState.SettingPosition;
return Event.Starting;
}
else if (opState == OpState.ValveMoveToPosition3)
{
if (reTryCommands)
{
opState = OpState.CheckStatePosition;
}
else
{
opState = OpState.SettingPosition;
}
return Event.Starting;
}
else if (opState == OpState.CheckStatePosition) /// Verify
{
if ((cBoard.State & (ulong)StatusP.TestWithRefFlowmtr) == 0)
{
opState = OpState.SendCommandAgain;
return Event.Starting;
}
else if (regV.RegValveState != RegValveState.DacValueRegul)
{
/// Repeat appropriate ValveMove(...) command
regV.MoveToPosition(targetPositionLo, targetPositionHi);
log.InfoFormat("SetFlowOp: ValveMove({0}, Position, {1}, {2}, {3})",
regulValveNr, targetPositionLo, targetPositionHi, regV.StableTime);
opState = OpState.ValveMoveToPosition3;
return Event.Starting;
}
else
{
opState = OpState.SettingPosition;
return Event.Starting;
}
}
else if (opState == OpState.SettingPosition)
{
/// Repeated untill position is reached
if ((targetPositionLo <= rvPosition) && (rvPosition <= targetPositionHi))
{
opState = OpState.ValveMoveToFlow1;
}
return Event.Starting;
}
else if (opState == OpState.ValveMoveToFlow1)
{
opState = OpState.ValveMoveToFlow2;
return Event.Starting;
}
else if (opState == OpState.ValveMoveToFlow2) /// Move to flow
{
///
/// 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}",
regulValveNr, flowMeter.Idx1, currentReqFlowLo, currentReqFlowHi);
double freqLo = 2000.0 * currentReqFlowLo / nominalFlow;
double freqHi = 2000.0 * currentReqFlowHi / nominalFlow;
regV.SetFlow(flowMeter.Idx1,freqLo, freqHi);
opState = OpState.ValveMoveToFlow3;
return Event.Starting;
}
else if (opState == OpState.ValveMoveToFlow3)
{
if (reTryCommands)
{
opState = OpState.CheckStateFlow;
}
else
{
opState = OpState.SettingFlow;
}
return Event.Starting;
}
else if (opState == OpState.CheckStateFlow) /// Verify the flow setting
{
if ( (cBoard.State & (ulong)StatusP.TestWithRefFlowmtr) == 0 ||
(regV.RegValveState & RegValveState.PwOrFreqRegul) != RegValveState.PwOrFreqRegul)
{
opState = OpState.SendCommandAgain;
return Event.Starting;
}
else if (regV.RegValveState != RegValveState.PwOrFreqRegul)
{
/// Done once, issues an appropriate ValveMove(...) command
double freqLo = 2000.0 * currentReqFlowLo / nominalFlow;
double freqHi = 2000.0 * currentReqFlowHi / nominalFlow;
regV.SetFlow(flowMeter.Idx1, freqLo, freqHi);
log.InfoFormat("SetFlowOp: ValveMove({0}, Frequency, {1}, {2}, {3})",
regulValveNr, freqLo, freqHi, regV.StableTime);
opState = OpState.ValveMoveToFlow3;
return Event.Starting;
}
else
{
opState = OpState.SettingFlow;
return Event.Busy;
}
}
else if (opState == OpState.SettingFlow)
{
/// Regulation valve is setting flow to the required value
if ((currentReqFlowLo <= flow) && (flow <= currentReqFlowHi))
{
/// Flow is within range
if (flowWithinBoundsTime++ >= regV.FlowStableSec)
{
/// Flow is within range for sufficiently long time
if (regV.regValveCfg.StoredPositionReuse)
{
double storedPosition;
if (regV.Dict.TryGetValue(targetFlowAve, out storedPosition))
{
/// update the stored valve position
StoreTargetPosition(targetFlowAve, (rvPosition + storedPosition) / 2.0);
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% stored={3} <--- Updating a stored position",
regulValveNr, targetFlowAve, rvPosition.ToString("F1"), storedPosition);
}
else
{
/// store the valve position
StoreTargetPosition(targetFlowAve, rvPosition);
log.InfoFormat("Run(): rv#={0} reqFlow={1} pos={2}% <--- Storing a new position",
regulValveNr, targetFlowAve, rvPosition.ToString("F1"));
}
}
log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow, currentReqFlowLo, currentReqFlowHi);
opState = OpState.FlowReached;
return Event.FlowReached;
}
else
{
log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, FLOW_OK_TIMER={3}s)", flow, currentReqFlowLo, currentReqFlowHi, flowWithinBoundsTime);
return Event.Busy;
}
}
else if (StateMachine.Time > expireTime)
{
return Event.RegulValveTimeOut;
}
else
{
log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2})", flow, currentReqFlowLo, currentReqFlowHi);
flowWithinBoundsTime = 0;
return Event.Busy;
}
}
else /// opState == OpState.FlowReached
{
log.InfoFormat("flow = {0} m3/h (lo={1}, hi={2}, REACHED)", flow, currentReqFlowLo, currentReqFlowHi);
return Event.FlowReached;
}
}
/// <summary>Start this operation</summary>
public void Stop()
{
if (!leaveMeasurementRunning)
{
/// Stop measurement
regV.SendCommand(Command.Stop, 50000, 50000, 0, StopDevs.RegValveRegulation); /// TestMethods=0
}
opState = OpState.Idle;
}
}
}
@@ -0,0 +1,164 @@
///
/// 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.RegValve
{
public class SetRegValvePositionOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SetRegValvePositionOp));
public override string ToString()
{
return string.Format("SetRegulValvePositionOp({0},{1},{2})", regV.Name, posLoPct, posHiPct);
}
const int CoaxValveNr = 7; /// Coax. valve has number 7
///
/// 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 cBoard;
readonly RegValve regV;
readonly int regValveNr;
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="cBoard">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 SetRegValvePositionOp(UniCB cBoard, RegValve regValve, double posLoPct, double posHiPct, int timeout)
{
this.cBoard = cBoard;
if (this.cBoard == null) throw new ArgumentNullException("ctrlBoard");
this.regV = regValve as RegValve;
if (this.regV == null) throw new ArgumentNullException("regValve is null or not Elde");
this.regValveNr = this.regV.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 SetRegValvePositionOp(UniCB cBoard, RegValve regValve, float posLoPct, float posHiPct)
: this(cBoard, regValve, posLoPct, posHiPct, int.MaxValue)
{
}
/// <summary>Start this operation</summary>
public void Start()
{
firstRun = true;
positionReached = false;
expireTime = StateMachine.Time + timeout;
log.InfoFormat("Start(): {0} reqPosLo={1}%, reqPosHi={2}%", regV.Name, posLoPct.ToString("F1"), posHiPct.ToString("F1"));
opState = OpState.MoveToPosition;
}
/// <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;
regV.MoveToPosition(posLoPct, posHiPct);
opState = OpState.CheckState;
return Event.None;
}
if (positionReached) return Event.PositionReached;
double positionPct = regV.Position;
log.WarnFormat("Run(): RV#={0}, actPos={1}%", regValveNr, positionPct.ToString("F1"));
if (opState == OpState.CheckState)
{
if (regValveNr == CoaxValveNr && (cBoard.State & (ulong)StatusP.CoaxRegValveBusy) == 0)
{
opState = OpState.MoveToPosition;
return Event.None;
}
else if (posLoPct <= positionPct && positionPct <= posHiPct)
{
positionReached = true;
return Event.PositionReached;
}
else if (regV.RegValveState != RegValveState.DacValueRegul)
{
opState = OpState.MoveToPosition; /// Resend move command again in the next run
return Event.None;
}
else
{
opState = OpState.MovingToPosition;
return Event.None;
}
}
else if (StateMachine.Time > expireTime)
{
return Event.RegulValveTimeOut;
}
else if (opState == OpState.MovingToPosition)
{
if (posLoPct <= positionPct && positionPct <= posHiPct)
{
positionReached = true;
return Event.PositionReached;
}
return Event.None;
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}