Refactoring : TestBenchFramework --> TBF ver. 2.18.789

This commit is contained in:
Milan Hanajik
2018-01-29 09:48:01 +01:00
parent 06018303e7
commit 0d3ee53bd5
1300 changed files with 441 additions and 612 deletions
@@ -0,0 +1,61 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.BenchControl.MettlerToledo
{
public class KeepReadingMassesOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(KeepReadingMassesOp));
public override string ToString() { return string.Format("KeepReadingMassesOp()"); }
bool done;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="requiredReadingsCount">Required mass readings count (>= 3)</param>
/// <param name="result">Reference to the measured mass in kg</param>
public KeepReadingMassesOp()
{
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
done = false;
for (int i = 0; i < Standard.BalanceDev.BalancesCount; i++)
{
Standard.BalanceDev.Balances[i].GetImmediateMassMeasurement();
}
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// </returns>
public Event Run()
{
if (done) return Event.BalanceDone; /// Mass has already been read
for (int i = 0; i < Standard.BalanceDev.BalancesCount; i++)
{
if (Standard.BalanceDev.Balances[i].MsrmntState != MsrmntState.Busy)
{
Standard.BalanceDev.Balances[i].GetImmediateMassMeasurement();
}
}
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,130 @@
///
/// Copyright (c) 2015-2018 Sensus Slovensko a.s.
///
using System;
using System.IO;
using System.Collections.Generic;
using System.IO.Ports;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Multi
{
public class BalanceCfg : ComponentCfgBase, GenericDevices.IScaleCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(BalanceCfg) })[0];
protected override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl() { return new BalanceCfgCtrl(); }
///
/// Serialized parameters
///
public int IdNr; /// Identification number 1..3
public float Capacity; /// Max. water mass in 'kg' or volume in 'l'
public float Resolution; /// Resolution of the integer value in the serial protocol in 'kg'
public float Empty; /// 'Empty' water mass in 'kg' or volume in 'l'
public string Format;
public int EmptyTimeSec; /// s
public int ComPortNr;
public int BaudRate;
public Parity Parity;
public int DataBits;
public StopBits StopBits;
public Handshake Handshake;
///
/// Buoyancy related serialized parameters - Displayed in Metrology tab page
///
float buoyancyTemp;
float buoyancyPress;
float buoyancyHumi;
float weightStandardDensity;
string calibCertificateNr;
DateTime calibDate;
DateTime calibValidDate;
///
public float BuoyancyTemp
{
get { return buoyancyTemp; }
set { buoyancyTemp = value; }
}
public float BuoyancyPress
{
get { return buoyancyPress; }
set { buoyancyPress = value; }
}
public float BuoyancyHumi
{
get { return buoyancyHumi; }
set { buoyancyHumi = value; }
}
public float WeightStandardDensity
{
get { return weightStandardDensity; }
set { weightStandardDensity = value; }
}
public string CalibCertificateNr
{
get { return calibCertificateNr; }
set { calibCertificateNr = value; }
}
public DateTime CalibDate
{
get { return calibDate; }
set { calibDate = value; }
}
public DateTime CalibValidDate
{
get { return calibValidDate; }
set { calibValidDate = value; }
}
/// Private parameterless constructor invoked by all other (public) constructors
BalanceCfg()
{
Name = "Balance";
ParentName = string.Empty;
IdNr = 1;
Capacity = 200.0f;
Resolution = 0.001f;
Empty = 20.0f;
Format = "F3";
EmptyTimeSec = 180;
ComPortNr = 3;
BaudRate = 2400;
Parity = System.IO.Ports.Parity.Even;
DataBits = 7;
StopBits = System.IO.Ports.StopBits.One;
Handshake = System.IO.Ports.Handshake.XOnXOff;
BuoyancyTemp = 20.0f;
BuoyancyPress = 1.0f;
BuoyancyHumi = 40.0f;
}
public BalanceCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
if (IdNr == 1)
{
return string.Format("Name={0}, Id#={1}, {2}kg, empty={3}kg, fmt.={4}, emptyTm={5}s, Com{6}, {7}Bd, {8}-bits, parity={9}, stopBits={10}, {11}",
Name, IdNr, Capacity, Empty, Format, EmptyTimeSec, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
else
{
return string.Format("Name={0}, Id#={1}, {2}kg, empty={3}kg, fmt.={4}, emptyTm={5}s",
Name, IdNr, Capacity, Empty, Format, EmptyTimeSec);
}
}
}
}
@@ -0,0 +1,414 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
namespace TBF.BenchControl.MettlerToledo.Multi
{
partial class BalanceCfgCtrl
{
/// <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.handshakeComboBox = new System.Windows.Forms.ComboBox();
this.stopBitsComboBox = new System.Windows.Forms.ComboBox();
this.parityComboBox = new System.Windows.Forms.ComboBox();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.handshakeLabel = new System.Windows.Forms.Label();
this.stopBitsLabel = new System.Windows.Forms.Label();
this.dataBitsTextBox = new System.Windows.Forms.TextBox();
this.dataBitsLabel = new System.Windows.Forms.Label();
this.parityLabel = new System.Windows.Forms.Label();
this.baudRateTextBox = new System.Windows.Forms.TextBox();
this.baudRateLabel = new System.Windows.Forms.Label();
this.comPortNrTextBox = new System.Windows.Forms.TextBox();
this.comPortNrLabel = new System.Windows.Forms.Label();
this.capacityLabel = new System.Windows.Forms.Label();
this.capacityTextBox = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.emptyTextBox = new System.Windows.Forms.TextBox();
this.emptyLabel = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.emptyTimeTextBox = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.formatTextBox = new System.Windows.Forms.TextBox();
this.formatLabel = new System.Windows.Forms.Label();
this.idNrTextBox = new System.Windows.Forms.TextBox();
this.idNrLabel = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.resolutionTextBox = new System.Windows.Forms.TextBox();
this.resolutionLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// handshakeComboBox
//
this.handshakeComboBox.Enabled = false;
this.handshakeComboBox.FormattingEnabled = true;
this.handshakeComboBox.Location = new System.Drawing.Point(236, 224);
this.handshakeComboBox.Name = "handshakeComboBox";
this.handshakeComboBox.Size = new System.Drawing.Size(43, 21);
this.handshakeComboBox.TabIndex = 30;
//
// stopBitsComboBox
//
this.stopBitsComboBox.Enabled = false;
this.stopBitsComboBox.FormattingEnabled = true;
this.stopBitsComboBox.Location = new System.Drawing.Point(236, 203);
this.stopBitsComboBox.Name = "stopBitsComboBox";
this.stopBitsComboBox.Size = new System.Drawing.Size(43, 21);
this.stopBitsComboBox.TabIndex = 28;
//
// parityComboBox
//
this.parityComboBox.Enabled = false;
this.parityComboBox.FormattingEnabled = true;
this.parityComboBox.Location = new System.Drawing.Point(100, 224);
this.parityComboBox.Name = "parityComboBox";
this.parityComboBox.Size = new System.Drawing.Size(43, 21);
this.parityComboBox.TabIndex = 24;
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(136, 26);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(143, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(26, 29);
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(133, 7);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComponentName";
//
// handshakeLabel
//
this.handshakeLabel.AutoSize = true;
this.handshakeLabel.Location = new System.Drawing.Point(162, 227);
this.handshakeLabel.Name = "handshakeLabel";
this.handshakeLabel.Size = new System.Drawing.Size(62, 13);
this.handshakeLabel.TabIndex = 29;
this.handshakeLabel.Text = "Handshake";
//
// stopBitsLabel
//
this.stopBitsLabel.AutoSize = true;
this.stopBitsLabel.Location = new System.Drawing.Point(162, 206);
this.stopBitsLabel.Name = "stopBitsLabel";
this.stopBitsLabel.Size = new System.Drawing.Size(49, 13);
this.stopBitsLabel.TabIndex = 27;
this.stopBitsLabel.Text = "Stop Bits";
//
// dataBitsTextBox
//
this.dataBitsTextBox.Enabled = false;
this.dataBitsTextBox.Location = new System.Drawing.Point(236, 181);
this.dataBitsTextBox.Name = "dataBitsTextBox";
this.dataBitsTextBox.Size = new System.Drawing.Size(43, 20);
this.dataBitsTextBox.TabIndex = 26;
//
// dataBitsLabel
//
this.dataBitsLabel.AutoSize = true;
this.dataBitsLabel.Location = new System.Drawing.Point(162, 184);
this.dataBitsLabel.Name = "dataBitsLabel";
this.dataBitsLabel.Size = new System.Drawing.Size(50, 13);
this.dataBitsLabel.TabIndex = 25;
this.dataBitsLabel.Text = "Data Bits";
//
// parityLabel
//
this.parityLabel.AutoSize = true;
this.parityLabel.Location = new System.Drawing.Point(26, 229);
this.parityLabel.Name = "parityLabel";
this.parityLabel.Size = new System.Drawing.Size(33, 13);
this.parityLabel.TabIndex = 23;
this.parityLabel.Text = "Parity";
//
// baudRateTextBox
//
this.baudRateTextBox.Enabled = false;
this.baudRateTextBox.Location = new System.Drawing.Point(100, 203);
this.baudRateTextBox.Name = "baudRateTextBox";
this.baudRateTextBox.Size = new System.Drawing.Size(43, 20);
this.baudRateTextBox.TabIndex = 22;
//
// baudRateLabel
//
this.baudRateLabel.AutoSize = true;
this.baudRateLabel.Location = new System.Drawing.Point(26, 206);
this.baudRateLabel.Name = "baudRateLabel";
this.baudRateLabel.Size = new System.Drawing.Size(58, 13);
this.baudRateLabel.TabIndex = 21;
this.baudRateLabel.Text = "Baud Rate";
//
// comPortNrTextBox
//
this.comPortNrTextBox.Enabled = false;
this.comPortNrTextBox.Location = new System.Drawing.Point(100, 181);
this.comPortNrTextBox.Name = "comPortNrTextBox";
this.comPortNrTextBox.Size = new System.Drawing.Size(43, 20);
this.comPortNrTextBox.TabIndex = 20;
//
// comPortNrLabel
//
this.comPortNrLabel.AutoSize = true;
this.comPortNrLabel.Location = new System.Drawing.Point(26, 184);
this.comPortNrLabel.Name = "comPortNrLabel";
this.comPortNrLabel.Size = new System.Drawing.Size(68, 13);
this.comPortNrLabel.TabIndex = 19;
this.comPortNrLabel.Text = "Serial Port #:";
//
// capacityLabel
//
this.capacityLabel.AutoSize = true;
this.capacityLabel.Location = new System.Drawing.Point(26, 71);
this.capacityLabel.Name = "capacityLabel";
this.capacityLabel.Size = new System.Drawing.Size(76, 13);
this.capacityLabel.TabIndex = 5;
this.capacityLabel.Text = "Tank Capacity";
//
// capacityTextBox
//
this.capacityTextBox.Enabled = false;
this.capacityTextBox.Location = new System.Drawing.Point(137, 68);
this.capacityTextBox.Name = "capacityTextBox";
this.capacityTextBox.Size = new System.Drawing.Size(43, 20);
this.capacityTextBox.TabIndex = 6;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(186, 71);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(19, 13);
this.label2.TabIndex = 7;
this.label2.Text = "kg";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(186, 113);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(19, 13);
this.label3.TabIndex = 13;
this.label3.Text = "kg";
//
// emptyTextBox
//
this.emptyTextBox.Enabled = false;
this.emptyTextBox.Location = new System.Drawing.Point(137, 110);
this.emptyTextBox.Name = "emptyTextBox";
this.emptyTextBox.Size = new System.Drawing.Size(43, 20);
this.emptyTextBox.TabIndex = 12;
//
// emptyLabel
//
this.emptyLabel.AutoSize = true;
this.emptyLabel.Location = new System.Drawing.Point(26, 113);
this.emptyLabel.Name = "emptyLabel";
this.emptyLabel.Size = new System.Drawing.Size(64, 13);
this.emptyLabel.TabIndex = 11;
this.emptyLabel.Text = "Tank Empty";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(186, 155);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(24, 13);
this.label4.TabIndex = 18;
this.label4.Text = "sec";
//
// emptyTimeTextBox
//
this.emptyTimeTextBox.Enabled = false;
this.emptyTimeTextBox.Location = new System.Drawing.Point(137, 152);
this.emptyTimeTextBox.Name = "emptyTimeTextBox";
this.emptyTimeTextBox.Size = new System.Drawing.Size(43, 20);
this.emptyTimeTextBox.TabIndex = 17;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(26, 155);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(90, 13);
this.label5.TabIndex = 16;
this.label5.Text = "Tank Empty Time";
//
// formatTextBox
//
this.formatTextBox.Enabled = false;
this.formatTextBox.Location = new System.Drawing.Point(137, 131);
this.formatTextBox.Name = "formatTextBox";
this.formatTextBox.Size = new System.Drawing.Size(43, 20);
this.formatTextBox.TabIndex = 15;
//
// formatLabel
//
this.formatLabel.AutoSize = true;
this.formatLabel.Location = new System.Drawing.Point(26, 134);
this.formatLabel.Name = "formatLabel";
this.formatLabel.Size = new System.Drawing.Size(76, 13);
this.formatLabel.TabIndex = 14;
this.formatLabel.Text = "Decimal points";
//
// idNrTextBox
//
this.idNrTextBox.Enabled = false;
this.idNrTextBox.Location = new System.Drawing.Point(137, 47);
this.idNrTextBox.Name = "idNrTextBox";
this.idNrTextBox.Size = new System.Drawing.Size(43, 20);
this.idNrTextBox.TabIndex = 4;
this.idNrTextBox.TextChanged += new System.EventHandler(this.idNrTextBox_TextChanged);
//
// idNrLabel
//
this.idNrLabel.AutoSize = true;
this.idNrLabel.Location = new System.Drawing.Point(26, 50);
this.idNrLabel.Name = "idNrLabel";
this.idNrLabel.Size = new System.Drawing.Size(85, 13);
this.idNrLabel.TabIndex = 3;
this.idNrLabel.Text = "ID Number (1..3)";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(186, 92);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(19, 13);
this.label1.TabIndex = 10;
this.label1.Text = "kg";
//
// resolutionTextBox
//
this.resolutionTextBox.Enabled = false;
this.resolutionTextBox.Location = new System.Drawing.Point(137, 89);
this.resolutionTextBox.Name = "resolutionTextBox";
this.resolutionTextBox.Size = new System.Drawing.Size(43, 20);
this.resolutionTextBox.TabIndex = 9;
//
// resolutionLabel
//
this.resolutionLabel.AutoSize = true;
this.resolutionLabel.Location = new System.Drawing.Point(26, 92);
this.resolutionLabel.Name = "resolutionLabel";
this.resolutionLabel.Size = new System.Drawing.Size(57, 13);
this.resolutionLabel.TabIndex = 8;
this.resolutionLabel.Text = "Resolution";
//
// BalanceCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label1);
this.Controls.Add(this.resolutionTextBox);
this.Controls.Add(this.resolutionLabel);
this.Controls.Add(this.idNrTextBox);
this.Controls.Add(this.idNrLabel);
this.Controls.Add(this.formatTextBox);
this.Controls.Add(this.formatLabel);
this.Controls.Add(this.label4);
this.Controls.Add(this.emptyTimeTextBox);
this.Controls.Add(this.label5);
this.Controls.Add(this.label3);
this.Controls.Add(this.emptyTextBox);
this.Controls.Add(this.emptyLabel);
this.Controls.Add(this.label2);
this.Controls.Add(this.capacityTextBox);
this.Controls.Add(this.capacityLabel);
this.Controls.Add(this.handshakeComboBox);
this.Controls.Add(this.stopBitsComboBox);
this.Controls.Add(this.parityComboBox);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Controls.Add(this.handshakeLabel);
this.Controls.Add(this.stopBitsLabel);
this.Controls.Add(this.dataBitsTextBox);
this.Controls.Add(this.dataBitsLabel);
this.Controls.Add(this.parityLabel);
this.Controls.Add(this.baudRateTextBox);
this.Controls.Add(this.baudRateLabel);
this.Controls.Add(this.comPortNrTextBox);
this.Controls.Add(this.comPortNrLabel);
this.Name = "BalanceCfgCtrl";
this.Size = new System.Drawing.Size(300, 250);
this.Load += new System.EventHandler(this.BalanceCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ComboBox handshakeComboBox;
private System.Windows.Forms.ComboBox stopBitsComboBox;
private System.Windows.Forms.ComboBox parityComboBox;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.Label handshakeLabel;
private System.Windows.Forms.Label stopBitsLabel;
private System.Windows.Forms.TextBox dataBitsTextBox;
private System.Windows.Forms.Label dataBitsLabel;
private System.Windows.Forms.Label parityLabel;
private System.Windows.Forms.TextBox baudRateTextBox;
private System.Windows.Forms.Label baudRateLabel;
private System.Windows.Forms.TextBox comPortNrTextBox;
private System.Windows.Forms.Label comPortNrLabel;
private System.Windows.Forms.Label capacityLabel;
private System.Windows.Forms.TextBox capacityTextBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox emptyTextBox;
private System.Windows.Forms.Label emptyLabel;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox emptyTimeTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox formatTextBox;
private System.Windows.Forms.Label formatLabel;
private System.Windows.Forms.TextBox idNrTextBox;
private System.Windows.Forms.Label idNrLabel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox resolutionTextBox;
private System.Windows.Forms.Label resolutionLabel;
}
}
@@ -0,0 +1,262 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajik
///
using System;
using System.Globalization;
using System.Windows.Forms;
using System.IO.Ports;
using log4net;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Multi
{
public partial class BalanceCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(BalanceCfgCtrl));
public bool ShowMore { get { return false; } }
BalanceCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as BalanceCfg;
Redraw();
}
}
public BalanceCfgCtrl()
{
InitializeComponent();
parityComboBox.Items.Add(Parity.None.ToString());
parityComboBox.Items.Add(Parity.Even.ToString());
parityComboBox.Items.Add(Parity.Odd.ToString());
stopBitsComboBox.Items.Add(StopBits.None.ToString());
stopBitsComboBox.Items.Add(StopBits.One.ToString());
stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString());
stopBitsComboBox.Items.Add(StopBits.Two.ToString());
handshakeComboBox.Items.Add(Handshake.None.ToString());
handshakeComboBox.Items.Add(Handshake.RequestToSend.ToString());
handshakeComboBox.Items.Add(Handshake.XOnXOff.ToString());
}
int GetParityIx(Parity par)
{
if (par == Parity.None) return 0;
if (par == Parity.Even) return 0;
if (par == Parity.Odd) return 0;
return -1;
}
Parity GetParity(string str)
{
if (str.Equals(Parity.None.ToString())) return Parity.None;
if (str.Equals(Parity.Even.ToString())) return Parity.Even;
if (str.Equals(Parity.Odd.ToString())) return Parity.Odd;
return (Parity)(-1);
}
int GetStopBitsIx(StopBits sb)
{
if (sb == StopBits.None) return 0;
if (sb == StopBits.One) return 1;
if (sb == StopBits.OnePointFive) return 2;
if (sb == StopBits.Two) return 3;
return -1;
}
StopBits GetStopBits(string str)
{
if (str.Equals(StopBits.None.ToString())) return StopBits.None;
if (str.Equals(StopBits.One.ToString())) return StopBits.One;
if (str.Equals(StopBits.OnePointFive.ToString())) return StopBits.OnePointFive;
if (str.Equals(StopBits.Two.ToString())) return StopBits.Two;
return (StopBits)(-1);
}
int GetHandshakeIx(Handshake par)
{
if (par == Handshake.None) return 0;
if (par == Handshake.RequestToSend) return 0;
if (par == Handshake.XOnXOff) return 0;
return -1;
}
Handshake GetHandshake(string str)
{
if (str.Equals(Handshake.None.ToString())) return Handshake.None;
if (str.Equals(Handshake.RequestToSend.ToString())) return Handshake.RequestToSend;
if (str.Equals(Handshake.XOnXOff.ToString())) return Handshake.XOnXOff;
return (Handshake)(-1);
}
private void BalanceCfgCtrl_Load(object sender, EventArgs e)
{
Redraw();
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
idNrTextBox.Text = config.IdNr.ToString();
capacityTextBox.Text = config.Capacity.ToString();
resolutionTextBox.Text = config.Resolution.ToString();
emptyTextBox.Text = config.Empty.ToString();
formatTextBox.Text = (config.Format.Length > 1) ? config.Format.Substring(1) : config.Format;
emptyTimeTextBox.Text = config.EmptyTimeSec.ToString();
comPortNrTextBox.Text = config.ComPortNr.ToString();
baudRateTextBox.Text = config.BaudRate.ToString();
parityComboBox.Text = config.Parity.ToString();
dataBitsTextBox.Text = config.DataBits.ToString();
stopBitsComboBox.Text = config.StopBits.ToString();
handshakeComboBox.Text = config.Handshake.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
idNrTextBox.Enabled = true;
capacityTextBox.Enabled = true;
resolutionTextBox.Enabled = true;
emptyTextBox.Enabled = true;
formatTextBox.Enabled = true;
emptyTimeTextBox.Enabled = true;
comPortNrTextBox.Enabled = true;
baudRateTextBox.Enabled = true;
parityComboBox.Enabled = true;
dataBitsTextBox.Enabled = true;
stopBitsComboBox.Enabled = true;
handshakeComboBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int idNr;
if (!int.TryParse(idNrTextBox.Text, out idNr) || idNr < 1 || idNr > 3)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Id Number' is not valid";
}
float mass;
if (!Utils.TryParseUFloat(capacityTextBox.Text, out mass) || mass <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank Capacity' is not valid";
}
if (!Utils.TryParseUFloat(resolutionTextBox.Text, out mass) || mass <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Resolution' is not valid";
}
if (!Utils.TryParseUFloat(emptyTextBox.Text, out mass) || mass <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank Empty' is not valid";
}
int dummy;
if (!int.TryParse(formatTextBox.Text, out dummy) || dummy < 0 || dummy > 9)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Decimal points' should be between 0 and 9";
}
if (!int.TryParse(emptyTimeTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank Empty Time' should be between 1 and 999 sec";
}
if (idNr == 1)
{
if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Serial Port Number' is not valid";
}
if (!int.TryParse(baudRateTextBox.Text, out dummy) || dummy < 150 || dummy > 115200)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Baud Rate' is not valid";
}
if (!int.TryParse(dataBitsTextBox.Text, out dummy) || dummy < 7 || dummy > 8)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Data Bits' is not valid";
}
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
config.Name = nameTextBox.Text;
config.IdNr = int.Parse(idNrTextBox.Text);
config.Capacity = Utils.ParseUFloat(capacityTextBox.Text);
config.Resolution = Utils.ParseUFloat(resolutionTextBox.Text);
config.Empty = Utils.ParseUFloat(emptyTextBox.Text);
config.Format = "F" + formatTextBox.Text;
config.EmptyTimeSec = int.Parse(emptyTimeTextBox.Text);
if (config.IdNr == 1)
{
config.ComPortNr = int.Parse(comPortNrTextBox.Text);
config.BaudRate = int.Parse(baudRateTextBox.Text);
config.Parity = GetParity(parityComboBox.SelectedItem.ToString());
config.DataBits = int.Parse(dataBitsTextBox.Text);
config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString());
config.Handshake = GetHandshake(handshakeComboBox.SelectedItem.ToString());
}
return flags;
}
private void idNrTextBox_TextChanged(object sender, EventArgs e)
{
int idNr;
if (int.TryParse(idNrTextBox.Text, out idNr))
{
bool visible = (idNr == 1);
comPortNrLabel.Visible = visible;
comPortNrTextBox.Visible = visible;
baudRateLabel.Visible = visible;
baudRateTextBox.Visible = visible;
parityLabel.Visible = visible;
parityComboBox.Visible = visible;
dataBitsLabel.Visible = visible;
dataBitsTextBox.Visible = visible;
stopBitsLabel.Visible = visible;
stopBitsComboBox.Visible = visible;
handshakeLabel.Visible = visible;
handshakeComboBox.Visible = visible;
}
}
}
}
@@ -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,331 @@
///
/// Copyright (c) 2015-2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO.Ports;
using log4net;
using Config.Entities;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Multi
{
/// <summary>
/// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232)
/// </summary>
/// <note>
/// Implemented and tested on 15.10.2013 by Milan Hanajik
/// </note>
public class BalanceDev : TankDraining, IDevice, GenericDevices.IScale
{
/// <summary>
/// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..."
/// Warn: Start measurement when busy is true
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(BalanceDev));
public override string ToString() { return string.Format("MettlerToledo.Multi.Balance({0})", Cfg.ToString(1)); }
protected readonly BalanceCfg balanceCfg;
protected static BalanceCfg balance1Cfg;
/// <summary>
/// Enumeration of balances via static fields and methods
/// </summary>
static int nextBalanceIdx = 0;
public static new void ResetStaticProperties()
{
nextBalanceIdx = 0;
}
public static int BalancesCount { get { return nextBalanceIdx; } }
public static BalanceDev[] Balances;
public static double[] Masses;
///
protected int balanceNr; /// 0-based balance number
protected static SerialPort serialPort;
protected static StringBuilder stringBuilder;
public int ScaleNr { get { return balanceNr; } }
public int IdNr { get { return balanceCfg.IdNr; } }
public double Capacity { get { return balanceCfg.Capacity; } }
public double Resolution { get { return balanceCfg.Resolution; } }
public int EmptyTimeSec { get { return balanceCfg.EmptyTimeSec; } }
/// Buoyancy
public float BuoyancyTemp { get { return balanceCfg.BuoyancyTemp; } }
public float BuoyancyPress { get { return balanceCfg.BuoyancyPress; } }
public float BuoyancyHumi { get { return balanceCfg.BuoyancyHumi; } }
public double WeightStandardDensity { get { return balanceCfg.WeightStandardDensity; } }
/// <summary>The state of the mass measurement</summary>
public MsrmntState MsrmntState { get { return msrmntState; } }
protected static MsrmntState msrmntState;
/// <summary>The mass after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
public double Mass { get { return Masses[balanceNr]; } }
/// <summary>The time stamp after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
public int MsrmntTimeStamp { get { return msrmntTimeStamp; } }
protected int msrmntTimeStamp;
public string Format { get { return balanceCfg.Format; } }
public BalanceDev()
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="cfg">Balance properties</param>
public BalanceDev(Generic.IComponentCfg cfg)
: base(cfg)
{
balanceCfg = cfg as BalanceCfg;
if (balanceCfg.IdNr == 1) balance1Cfg = balanceCfg;
balanceNr = nextBalanceIdx++;
Masses = new double[nextBalanceIdx]; /// (re)initialize the static array of masses of all balances
///
if (Balances == null || Balances.Length < nextBalanceIdx)
{
BalanceDev[] balancesSoFar = Balances;
Balances = new BalanceDev[nextBalanceIdx];
if (balancesSoFar != null) for (int i = 0; i < balancesSoFar.Length; i++) Balances[i] = balancesSoFar[i];
Balances[nextBalanceIdx - 1] = this;
}
log.Debug(this.ToString());
}
public void Initialize()
{
msrmntState = MsrmntState.Failed; /// Data not valid yet
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (balanceCfg.IdNr == 1)
{
stringBuilder = new StringBuilder(40);
string comPortName = "COM" + balanceCfg.ComPortNr.ToString();
serialPort = new SerialPort(comPortName, balanceCfg.BaudRate, balanceCfg.Parity, balanceCfg.DataBits, balanceCfg.StopBits);
serialPort.Handshake = balanceCfg.Handshake;
serialPort.Open();
}
log.FatalFormat("Successfully initialized device {0}", ToString());
}
public bool IsEmpty()
{
return (Mass <= balanceCfg.Empty);
}
public bool IsEmpty(double mass)
{
return (mass <= balanceCfg.Empty);
}
/// <summary>
/// Get a stable mass measurement
/// </summary>
public static bool GetStableMassMeasurement(int scaleId, string name)
{
if (balance1Cfg.DebugLevel == DebugMode.Simulate) return true;
if (msrmntState == MsrmntState.Busy ||
msrmntState == MsrmntState.Busy1 ||
msrmntState == MsrmntState.Busy2 ||
msrmntState == MsrmntState.Busy3)
{
log.WarnFormat("{0} - GetStableMassMeasurement() returns false ... measurementState == {1}", name, msrmntState.ToString());
return false;
}
msrmntState = (MsrmntState)((int)MsrmntState.Busy + scaleId);
stringBuilder.Clear();
string serialData = string.Format("AR WT0{0}01\r\n", scaleId);
serialPort.Write(serialData);
log.InfoFormat("{0} - GetStableMassMeasurement() ... \"{1}\" sent", name, serialData);
return true;
}
/// <summary>
/// Get an immediate mass measurement
/// </summary>
public static bool GetImmediateMassMeasurement(int scaleId, string name)
{
if (balance1Cfg.DebugLevel == DebugMode.Simulate) return true;
if (msrmntState == MsrmntState.Busy ||
msrmntState == MsrmntState.Busy1 ||
msrmntState == MsrmntState.Busy2 ||
msrmntState == MsrmntState.Busy3)
{
log.WarnFormat("{0} - GetImmediateMassMeasurement() returns false ... measurementState == {1}", name, msrmntState.ToString());
return false;
}
msrmntState = (MsrmntState)((int)MsrmntState.Busy + scaleId);
stringBuilder.Clear();
string serialData = string.Format("AR WT0{0}01\r\n", scaleId);
serialPort.Write(serialData);
log.InfoFormat("{0} - GetImmediateMassMeasurement() ... \"{1}\" sent", name, serialData);
return true;
}
/// <summary>
/// Parse characters received from the serial port
/// </summary>
public virtual void RunDeviceBefore()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate)
{
Masses[balanceNr] = TestBenchSim.GetSimMass(balanceNr);
msrmntState = MsrmntState.Valid;
msrmntTimeStamp = StateMachine.Time;
return;
}
if (balanceCfg.IdNr != 1) return;
if (serialPort == null)
{
log.ErrorFormat("{0} - RunDevice() - serial port closed", Name);
return;
}
log.DebugFormat("{0} - RunDevice()", Name);
///
/// Communication runs only when the state is MsrmntState.Busy#
///
if (msrmntState != MsrmntState.Busy1 &&
msrmntState != MsrmntState.Busy2 &&
msrmntState != MsrmntState.Busy3)
{
return;
}
string justReceived = serialPort.ReadExisting();
if (justReceived != null && justReceived.Length > 0)
{
log.DebugFormat("RunDevice() received {0}", justReceived);
stringBuilder.Append(justReceived);
}
string currentBuffer = stringBuilder.ToString();
int eolPos = currentBuffer.IndexOf("\r\n");
if (eolPos >= 0)
{
log.InfoFormat("eolPos = {0}", eolPos);
msrmntTimeStamp = StateMachine.Time;
int balanceIdNr = (int)msrmntState - (int)MsrmntState.Busy;
/// Get part of the string before EOL
string received = currentBuffer.Substring(0, eolPos);
/// Put the rest back to the string builder
stringBuilder.Clear();
if (currentBuffer.Length > eolPos + 2)
{
stringBuilder.Append(currentBuffer.Substring(eolPos + 2));
}
if (received.Length == 19 && received.Substring(0, 6).Equals("AR A \""))
{
string weightStr = received.Substring(6, 12);
while ((weightStr[0] == ' ') && (weightStr.Length > 1))
{
weightStr = weightStr.Substring(1, weightStr.Length - 1);
}
double weight = 0;
if (Utils.TryParseSDouble(weightStr, out weight))
{
Masses[balanceIdNr - 1] = weight * Balances[balanceIdNr - 1].Resolution;
log.InfoFormat("Balance({0}) Valid response=\"{1}<cr>\", Mass = {2}kg", balanceIdNr, received, Masses[balanceIdNr - 1]);
msrmntState = MsrmntState.Valid;
}
else
{
log.WarnFormat("Balance({0}) Failed response=\"{1}<cr>\", Error 1 !!!", balanceIdNr, received);
msrmntState = MsrmntState.Failed;
}
}
else
{
//Balances[balanceIdNr - 1].msrmntState = MsrmntState.Failed;
log.WarnFormat("Balance({0}) Failed response=\"{1}<cr>\", Error 2 !!!", balanceIdNr, received);
msrmntState = MsrmntState.Failed;
}
}
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()
{
}
/// <summary>Stop this device</summary>
public void StopDevice()
{
if ((balanceCfg.DebugLevel != DebugMode.Simulate) && (balanceCfg.IdNr == 1) && (serialPort != null))
{
serialPort.Close();
serialPort = null;
}
}
public void StopDevice2() { }
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for 'tara' in kg</param>
/// <returns>TaringOp instance reference casted to IOperaton</returns>
public IOperation TaringOp(ref DoubleBox tara)
{
return new TaringOp(this, ref tara);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for the measured mass in kg</param>
/// <returns>ReadMassOp instance reference casted to IOperaton</returns>
public IOperation ReadMassOp(ref DoubleBox mass)
{
return new ReadMassOp(this, ref mass);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 3)</param>
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
/// <returns>ReadMassAverageOp instance reference casted to IOperaton</returns>
public IOperation ReadStableMassOp(ref DoubleBox mass, int readingsCount, double maxSpread, Config.Entities.MassMethod method)
{
return new ReadStableMassOp(this, ref mass, readingsCount, maxSpread, method);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="serialNumber">Reference to the serialNumber</param>
/// <returns>GetBalanceSNOp instance reference casted to IOperaton</returns>
public IOperation GetSerNumOp(ref string serialNumber)
{
return null;
}
}
}
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2015-2016 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Multi
{
public class BalanceFactory : IComponentFactory
{
public string ClassName { get { return "MettlerToledo-Multi"; } }
/// <summary>Max. number of components of this class in the system</summary>
public int MaxCount { get { return 5; } }
public IComponent DummyComponent() { return new BalanceDev(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new BalanceDev(cfg); }
public IComponentCfg DefaultConfig() { return new BalanceCfg(this); }
public IComponentCfgCtrl CreateCfgCtrl() { return new BalanceCfgCtrl(); }
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
{
return new BalanceDev((BalanceCfg)config);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(BalanceCfg.Serializer, component, this);
}
public void ResetStaticProperties() { BalanceDev.ResetStaticProperties(); }
}
}
@@ -0,0 +1,81 @@
///
/// Copyright (c) 2015-2016 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Multi
{
public class ReadMassOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadMassOp));
public override string ToString() { return string.Format("ReadMassOp(.,.)"); }
bool started;
bool done;
/// Set by the constructor
BalanceDev scale;
DoubleBox result;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="scale">Balance device instance</param>
/// <param name="requiredReadingsCount">Required mass readings count (>= 3)</param>
/// <param name="result">Reference to the measured mass in kg</param>
public ReadMassOp(BalanceDev scale, ref DoubleBox result)
{
if (scale == null) throw new ArgumentNullException("scale");
this.scale = scale;
this.result = result;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
done = false;
started = BalanceDev.GetImmediateMassMeasurement(scale.IdNr, scale.Name);
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (!started)
{
started = BalanceDev.GetImmediateMassMeasurement(scale.IdNr, scale.Name);
if (!done)
return Event.Busy;
else
return Event.BalanceDone;
}
else if (started && scale.MsrmntState != MsrmntState.Busy)
{
if (scale.MsrmntState == MsrmntState.Valid) result.Val = scale.Mass;
log.InfoFormat("ReadMassOp.Run() ... state={0}, mass={1} ... returning Event.BalanceDone",
scale.MsrmntState, scale.Mass);
done = true;
started = false;
return Event.BalanceDone; /// Mass read OK
}
else
{
return Event.Busy;
}
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,136 @@
///
/// Copyright (c) 2015-2017 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Multi
{
/// <summary>
/// Operation to read more mass values and average them to obtain a more accurate result.
/// </summary>
public class ReadStableMassOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadStableMassOp));
public override string ToString() { return string.Format("ReadStableMassOp(.,{0},.)", totalReadingsCount); }
/// Operation specific
double[] massReadings;
int currentReadingsCount;
/// Set by the constructor
BalanceDev balanceDev;
int totalReadingsCount;
double maxSpread; /// Maximum spread of measurements in kg (otherwise the measurement continues)
Config.Entities.MassMethod method; /// false = slow (precise), true = fast (immediate)
DoubleBox result;
bool started;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="result">Reference to the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 3)</param>
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
public ReadStableMassOp(BalanceDev balanceDev, ref DoubleBox result, int readingsCount, double maxSpread, Config.Entities.MassMethod method)
{
if (balanceDev == null) throw new ArgumentNullException("balanceDev");
this.balanceDev = balanceDev;
this.totalReadingsCount = (readingsCount < 4) ? 5 : readingsCount; /// readingsCount is at least 4
this.maxSpread = (maxSpread == 0) ? (balanceDev.Capacity / 20000.0) : maxSpread;
this.method = method;
this.result = result;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
started = false;
currentReadingsCount = 0;
massReadings = new double[totalReadingsCount];
started = BalanceDev.GetImmediateMassMeasurement(balanceDev.IdNr, balanceDev.Name);
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (currentReadingsCount >= totalReadingsCount) return Event.BalanceDone; /// Mass has already been calculated
if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.None;
if (balanceDev.MsrmntState == MsrmntState.Valid)
{
massReadings[currentReadingsCount++] = balanceDev.Mass;
if (currentReadingsCount == totalReadingsCount)
{
#if true /// OLD_WAY_OF_MASS_CALCULATION
/// Exclude min. and max. value, calculate average
Array.Sort(massReadings);
double calcMass = 0;
for (int i = 1; i < totalReadingsCount - 1; i++)
{
calcMass += massReadings[i];
}
calcMass = (calcMass / (totalReadingsCount - 2));
log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", calcMass);
result.Val = calcMass;
return Event.BalanceDone; /// Mass has just been calculated
#else
double minimum = double.MaxValue;
double maximum = double.MinValue;
foreach (double val in massReadings)
{
if (val < minimum) minimum = val;
if (val > maximum) maximum = val;
}
if ((maximum - minimum) <= maxSpread)
{
double calcMass = 0;
for (int i = 0; i < totalReadingsCount; i++)
{
calcMass += massReadings[i];
}
calcMass = (calcMass / totalReadingsCount);
log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", calcMass);
result.Val = calcMass;
return Event.BalanceDone; /// Mass has just been calculated
}
else
{
/// Shift data and decrement 'currentReadingsCount'
for (int i = 0; i < totalReadingsCount - 1; i++)
{
massReadings[i] = massReadings[i + 1];
}
currentReadingsCount--;
}
#endif
}
}
BalanceDev.GetImmediateMassMeasurement(balanceDev.IdNr, balanceDev.Name);
return Event.None;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,77 @@
///
/// Copyright (c) 2015-2016 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Multi
{
public class TaringOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(TaringOp));
public override string ToString() { return string.Format("TaringOp(.,.)"); }
bool done;
/// Set by the constructor
BalanceDev balanceDev;
DoubleBox tara;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="result">Reference to variable for 'tara' in kg</param>
public TaringOp(BalanceDev balanceDev, ref DoubleBox tara)
{
if (balanceDev == null) throw new ArgumentNullException("balanceDev");
this.balanceDev = balanceDev;
this.tara = tara;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
tara.Val = 0.0f; // Don't do anything, tara = 0
done = true;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (done) return Event.BalanceDone; /// Taring has been done already
if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.Busy;
if (balanceDev.MsrmntState == MsrmntState.Overload)
{
tara.Val = balanceDev.Capacity;
done = true;
return Event.BalanceOverload;
}
if (balanceDev.MsrmntState == MsrmntState.Valid)
{
tara.Val = balanceDev.Mass;
done = true;
return Event.BalanceDone; /// Taring completed
}
return Event.Busy;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,71 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.BenchControl.MettlerToledo
{
public class ReadMassesOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadMassesOp));
public override string ToString() { return string.Format("ReadMassesOp()"); }
bool done;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="requiredReadingsCount">Required mass readings count (>= 3)</param>
/// <param name="result">Reference to the measured mass in kg</param>
public ReadMassesOp()
{
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
done = false;
for (int i = 0; i < Standard.BalanceDev.BalancesCount; i++)
{
Standard.BalanceDev.Balances[i].GetImmediateMassMeasurement();
}
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (done) return Event.BalanceDone; /// Mass has already been read
for (int i = 0; i < Standard.BalanceDev.BalancesCount; i++)
{
if (Standard.BalanceDev.Balances[i].MsrmntState == MsrmntState.Busy)
{
return Event.None;
}
}
for (int i = 0; i < Multi.BalanceDev.BalancesCount; i++)
{
if (Multi.BalanceDev.Balances[i].MsrmntState == MsrmntState.Busy)
{
return Event.None;
}
}
done = true;
return Event.BalanceDone;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,142 @@
///
/// Copyright (c) 2013-2018 Sensus Slovensko a.s.
///
using System;
using System.IO;
using System.Collections.Generic;
using System.IO.Ports;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class BalanceCfg : ComponentCfgBase, GenericDevices.IScaleCfg, GenericDevices.ITankDrainingCfg
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(BalanceCfg) })[0];
protected override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl() { return new BalanceCfgCtrl(); }
///
/// Serialized parameters
///
public int ComPortNr;
public int BaudRate;
public Parity Parity;
public int DataBits;
public StopBits StopBits;
public Handshake Handshake;
/// Max. water mass in 'kg' or volume in 'l'
private float capacity;
public float Capacity
{
get { return capacity; }
set { capacity = value; }
}
/// Mass threshold for 'Tank is empty' in 'kg' (or volume in 'l')
private float empty;
public float Empty
{
get { return empty; }
set { empty = value; }
}
private string drainValve;
public string DrainValve
{
get { return drainValve; }
set { drainValve = value; }
}
private int drainTimeSec;
public int DrainTimeSec
{
get { return drainTimeSec; }
set { drainTimeSec = value; }
}
public string Format;
/// Buoyancy related serialized parameters displayed in Metrology tab page
private float buoyancyTemp;
private float buoyancyPress;
private float buoyancyHumi;
private float weightStandardDensity;
public float BuoyancyTemp
{
get { return buoyancyTemp; }
set { buoyancyTemp = value; }
}
public float BuoyancyPress
{
get { return buoyancyPress; }
set { buoyancyPress = value; }
}
public float BuoyancyHumi
{
get { return buoyancyHumi; }
set { buoyancyHumi = value; }
}
public float WeightStandardDensity
{
get { return weightStandardDensity; }
set { weightStandardDensity = value; }
}
/// Calibration info serialized parameters displayed in Metrology tab page
string calibCertificateNr;
DateTime calibDate;
DateTime calibValidDate;
public string CalibCertificateNr
{
get { return calibCertificateNr; }
set { calibCertificateNr = value; }
}
public DateTime CalibDate
{
get { return calibDate; }
set { calibDate = value; }
}
public DateTime CalibValidDate
{
get { return calibValidDate; }
set { calibValidDate = value; }
}
/// Private parameterless constructor invoked by all other (public) constructors
BalanceCfg()
{
Name = "WT1";
ParentName = string.Empty;
ComPortNr = 3;
BaudRate = 2400;
Parity = System.IO.Ports.Parity.Even;
DataBits = 7;
StopBits = System.IO.Ports.StopBits.One;
Handshake = System.IO.Ports.Handshake.XOnXOff;
Capacity = 200.0f;
Empty = 20.0f;
Format = "F3";
DrainValve = "VB1";
DrainTimeSec = 180;
BuoyancyTemp = 20.0f;
BuoyancyPress = 1.0f;
BuoyancyHumi = 40.0f;
}
public BalanceCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format("Name={0}, {1}kg, empty={2}kg, fmt.={3}, drainTm={4}s, Com{5}, {6}Bd, {7}-bits, parity={8}, stopBits={9}, {10}",
Name, Capacity, Empty, Format, DrainTimeSec, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
}
}
@@ -0,0 +1,379 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
namespace TBF.BenchControl.MettlerToledo.Standard
{
partial class BalanceCfgCtrl
{
/// <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.handshakeComboBox = new System.Windows.Forms.ComboBox();
this.stopBitsComboBox = new System.Windows.Forms.ComboBox();
this.parityComboBox = new System.Windows.Forms.ComboBox();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.handshakeLabel = new System.Windows.Forms.Label();
this.stopBitsLabel = new System.Windows.Forms.Label();
this.dataBitsTextBox = new System.Windows.Forms.TextBox();
this.dataBitsLabel = new System.Windows.Forms.Label();
this.partityLabel = new System.Windows.Forms.Label();
this.baudRateTextBox = new System.Windows.Forms.TextBox();
this.baudRateLabel = new System.Windows.Forms.Label();
this.comPortNrTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.capacityLabel = new System.Windows.Forms.Label();
this.capacityTextBox = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.emptyTextBox = new System.Windows.Forms.TextBox();
this.emptyLabel = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.drainTimeTextBox = new System.Windows.Forms.TextBox();
this.label5 = new System.Windows.Forms.Label();
this.formatTextBox = new System.Windows.Forms.TextBox();
this.formatLabel = new System.Windows.Forms.Label();
this.drainValveComboBox = new System.Windows.Forms.ComboBox();
this.drainingValveLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// handshakeComboBox
//
this.handshakeComboBox.Enabled = false;
this.handshakeComboBox.FormattingEnabled = true;
this.handshakeComboBox.Location = new System.Drawing.Point(236, 222);
this.handshakeComboBox.Name = "handshakeComboBox";
this.handshakeComboBox.Size = new System.Drawing.Size(43, 21);
this.handshakeComboBox.TabIndex = 27;
//
// stopBitsComboBox
//
this.stopBitsComboBox.Enabled = false;
this.stopBitsComboBox.FormattingEnabled = true;
this.stopBitsComboBox.Location = new System.Drawing.Point(236, 200);
this.stopBitsComboBox.Name = "stopBitsComboBox";
this.stopBitsComboBox.Size = new System.Drawing.Size(43, 21);
this.stopBitsComboBox.TabIndex = 25;
//
// parityComboBox
//
this.parityComboBox.Enabled = false;
this.parityComboBox.FormattingEnabled = true;
this.parityComboBox.Location = new System.Drawing.Point(100, 222);
this.parityComboBox.Name = "parityComboBox";
this.parityComboBox.Size = new System.Drawing.Size(43, 21);
this.parityComboBox.TabIndex = 21;
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(137, 27);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(142, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(26, 30);
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(134, 9);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(89, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComponentName";
//
// handshakeLabel
//
this.handshakeLabel.AutoSize = true;
this.handshakeLabel.Location = new System.Drawing.Point(162, 225);
this.handshakeLabel.Name = "handshakeLabel";
this.handshakeLabel.Size = new System.Drawing.Size(62, 13);
this.handshakeLabel.TabIndex = 26;
this.handshakeLabel.Text = "Handshake";
//
// stopBitsLabel
//
this.stopBitsLabel.AutoSize = true;
this.stopBitsLabel.Location = new System.Drawing.Point(162, 203);
this.stopBitsLabel.Name = "stopBitsLabel";
this.stopBitsLabel.Size = new System.Drawing.Size(49, 13);
this.stopBitsLabel.TabIndex = 24;
this.stopBitsLabel.Text = "Stop Bits";
//
// dataBitsTextBox
//
this.dataBitsTextBox.Enabled = false;
this.dataBitsTextBox.Location = new System.Drawing.Point(236, 178);
this.dataBitsTextBox.Name = "dataBitsTextBox";
this.dataBitsTextBox.Size = new System.Drawing.Size(43, 20);
this.dataBitsTextBox.TabIndex = 23;
//
// dataBitsLabel
//
this.dataBitsLabel.AutoSize = true;
this.dataBitsLabel.Location = new System.Drawing.Point(162, 181);
this.dataBitsLabel.Name = "dataBitsLabel";
this.dataBitsLabel.Size = new System.Drawing.Size(50, 13);
this.dataBitsLabel.TabIndex = 22;
this.dataBitsLabel.Text = "Data Bits";
//
// partityLabel
//
this.partityLabel.AutoSize = true;
this.partityLabel.Location = new System.Drawing.Point(26, 225);
this.partityLabel.Name = "partityLabel";
this.partityLabel.Size = new System.Drawing.Size(33, 13);
this.partityLabel.TabIndex = 20;
this.partityLabel.Text = "Parity";
//
// baudRateTextBox
//
this.baudRateTextBox.Enabled = false;
this.baudRateTextBox.Location = new System.Drawing.Point(100, 200);
this.baudRateTextBox.Name = "baudRateTextBox";
this.baudRateTextBox.Size = new System.Drawing.Size(43, 20);
this.baudRateTextBox.TabIndex = 19;
//
// baudRateLabel
//
this.baudRateLabel.AutoSize = true;
this.baudRateLabel.Location = new System.Drawing.Point(26, 203);
this.baudRateLabel.Name = "baudRateLabel";
this.baudRateLabel.Size = new System.Drawing.Size(53, 13);
this.baudRateLabel.TabIndex = 18;
this.baudRateLabel.Text = "Baud rate";
//
// comPortNrTextBox
//
this.comPortNrTextBox.Enabled = false;
this.comPortNrTextBox.Location = new System.Drawing.Point(100, 178);
this.comPortNrTextBox.Name = "comPortNrTextBox";
this.comPortNrTextBox.Size = new System.Drawing.Size(43, 20);
this.comPortNrTextBox.TabIndex = 17;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(26, 181);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(67, 13);
this.label1.TabIndex = 16;
this.label1.Text = "Serial port #:";
//
// capacityLabel
//
this.capacityLabel.AutoSize = true;
this.capacityLabel.Location = new System.Drawing.Point(26, 82);
this.capacityLabel.Name = "capacityLabel";
this.capacityLabel.Size = new System.Drawing.Size(75, 13);
this.capacityLabel.TabIndex = 5;
this.capacityLabel.Text = "Tank capacity";
//
// capacityTextBox
//
this.capacityTextBox.Enabled = false;
this.capacityTextBox.Location = new System.Drawing.Point(137, 79);
this.capacityTextBox.Name = "capacityTextBox";
this.capacityTextBox.Size = new System.Drawing.Size(43, 20);
this.capacityTextBox.TabIndex = 6;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(186, 82);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(19, 13);
this.label2.TabIndex = 7;
this.label2.Text = "kg";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(186, 104);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(19, 13);
this.label3.TabIndex = 10;
this.label3.Text = "kg";
//
// emptyTextBox
//
this.emptyTextBox.Enabled = false;
this.emptyTextBox.Location = new System.Drawing.Point(137, 101);
this.emptyTextBox.Name = "emptyTextBox";
this.emptyTextBox.Size = new System.Drawing.Size(43, 20);
this.emptyTextBox.TabIndex = 9;
//
// emptyLabel
//
this.emptyLabel.AutoSize = true;
this.emptyLabel.Location = new System.Drawing.Point(26, 104);
this.emptyLabel.Name = "emptyLabel";
this.emptyLabel.Size = new System.Drawing.Size(109, 13);
this.emptyLabel.TabIndex = 8;
this.emptyLabel.Text = "Tank empty threshold";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(186, 149);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(24, 13);
this.label4.TabIndex = 15;
this.label4.Text = "sec";
//
// drainTimeTextBox
//
this.drainTimeTextBox.Enabled = false;
this.drainTimeTextBox.Location = new System.Drawing.Point(137, 146);
this.drainTimeTextBox.Name = "drainTimeTextBox";
this.drainTimeTextBox.Size = new System.Drawing.Size(43, 20);
this.drainTimeTextBox.TabIndex = 14;
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(26, 149);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(54, 13);
this.label5.TabIndex = 13;
this.label5.Text = "Drain time";
//
// formatTextBox
//
this.formatTextBox.Enabled = false;
this.formatTextBox.Location = new System.Drawing.Point(137, 49);
this.formatTextBox.Name = "formatTextBox";
this.formatTextBox.Size = new System.Drawing.Size(43, 20);
this.formatTextBox.TabIndex = 4;
//
// formatLabel
//
this.formatLabel.AutoSize = true;
this.formatLabel.Location = new System.Drawing.Point(26, 52);
this.formatLabel.Name = "formatLabel";
this.formatLabel.Size = new System.Drawing.Size(76, 13);
this.formatLabel.TabIndex = 3;
this.formatLabel.Text = "Decimal points";
//
// drainValveComboBox
//
this.drainValveComboBox.Enabled = false;
this.drainValveComboBox.FormattingEnabled = true;
this.drainValveComboBox.Location = new System.Drawing.Point(137, 123);
this.drainValveComboBox.Name = "drainValveComboBox";
this.drainValveComboBox.Size = new System.Drawing.Size(143, 21);
this.drainValveComboBox.TabIndex = 12;
//
// drainingValveLabel
//
this.drainingValveLabel.AutoSize = true;
this.drainingValveLabel.Location = new System.Drawing.Point(26, 126);
this.drainingValveLabel.Name = "drainingValveLabel";
this.drainingValveLabel.Size = new System.Drawing.Size(61, 13);
this.drainingValveLabel.TabIndex = 11;
this.drainingValveLabel.Text = "Drain valve";
//
// BalanceCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.drainValveComboBox);
this.Controls.Add(this.drainingValveLabel);
this.Controls.Add(this.formatTextBox);
this.Controls.Add(this.formatLabel);
this.Controls.Add(this.label4);
this.Controls.Add(this.drainTimeTextBox);
this.Controls.Add(this.label5);
this.Controls.Add(this.label3);
this.Controls.Add(this.emptyTextBox);
this.Controls.Add(this.emptyLabel);
this.Controls.Add(this.label2);
this.Controls.Add(this.capacityTextBox);
this.Controls.Add(this.capacityLabel);
this.Controls.Add(this.handshakeComboBox);
this.Controls.Add(this.stopBitsComboBox);
this.Controls.Add(this.parityComboBox);
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Controls.Add(this.handshakeLabel);
this.Controls.Add(this.stopBitsLabel);
this.Controls.Add(this.dataBitsTextBox);
this.Controls.Add(this.dataBitsLabel);
this.Controls.Add(this.partityLabel);
this.Controls.Add(this.baudRateTextBox);
this.Controls.Add(this.baudRateLabel);
this.Controls.Add(this.comPortNrTextBox);
this.Controls.Add(this.label1);
this.Name = "BalanceCfgCtrl";
this.Size = new System.Drawing.Size(300, 250);
this.Load += new System.EventHandler(this.BalanceCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ComboBox handshakeComboBox;
private System.Windows.Forms.ComboBox stopBitsComboBox;
private System.Windows.Forms.ComboBox parityComboBox;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.Label handshakeLabel;
private System.Windows.Forms.Label stopBitsLabel;
private System.Windows.Forms.TextBox dataBitsTextBox;
private System.Windows.Forms.Label dataBitsLabel;
private System.Windows.Forms.Label partityLabel;
private System.Windows.Forms.TextBox baudRateTextBox;
private System.Windows.Forms.Label baudRateLabel;
private System.Windows.Forms.TextBox comPortNrTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label capacityLabel;
private System.Windows.Forms.TextBox capacityTextBox;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox emptyTextBox;
private System.Windows.Forms.Label emptyLabel;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox drainTimeTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox formatTextBox;
private System.Windows.Forms.Label formatLabel;
private System.Windows.Forms.ComboBox drainValveComboBox;
private System.Windows.Forms.Label drainingValveLabel;
}
}
@@ -0,0 +1,233 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
///
using System;
using System.Globalization;
using System.Windows.Forms;
using System.IO.Ports;
using log4net;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public partial class BalanceCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(BalanceCfgCtrl));
ComponentParametersDlg parent;
public bool ShowMore { get { return false; } }
BalanceCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as BalanceCfg;
Redraw();
}
}
int GetParityIx(Parity par)
{
if (par == Parity.None) return 0;
if (par == Parity.Even) return 0;
if (par == Parity.Odd) return 0;
return -1;
}
Parity GetParity(string str)
{
if (str.Equals(Parity.None.ToString())) return Parity.None;
if (str.Equals(Parity.Even.ToString())) return Parity.Even;
if (str.Equals(Parity.Odd.ToString())) return Parity.Odd;
return (Parity)(-1);
}
int GetStopBitsIx(StopBits sb)
{
if (sb == StopBits.None) return 0;
if (sb == StopBits.One) return 1;
if (sb == StopBits.OnePointFive) return 2;
if (sb == StopBits.Two) return 3;
return -1;
}
StopBits GetStopBits(string str)
{
if (str.Equals(StopBits.None.ToString())) return StopBits.None;
if (str.Equals(StopBits.One.ToString())) return StopBits.One;
if (str.Equals(StopBits.OnePointFive.ToString())) return StopBits.OnePointFive;
if (str.Equals(StopBits.Two.ToString())) return StopBits.Two;
return (StopBits)(-1);
}
int GetHandshakeIx(Handshake par)
{
if (par == Handshake.None) return 0;
if (par == Handshake.RequestToSend) return 0;
if (par == Handshake.XOnXOff) return 0;
return -1;
}
Handshake GetHandshake(string str)
{
if (str.Equals(Handshake.None.ToString())) return Handshake.None;
if (str.Equals(Handshake.RequestToSend.ToString())) return Handshake.RequestToSend;
if (str.Equals(Handshake.XOnXOff.ToString())) return Handshake.XOnXOff;
return (Handshake)(-1);
}
public BalanceCfgCtrl()
{
InitializeComponent();
parityComboBox.Items.Add(Parity.None.ToString());
parityComboBox.Items.Add(Parity.Even.ToString());
parityComboBox.Items.Add(Parity.Odd.ToString());
stopBitsComboBox.Items.Add(StopBits.None.ToString());
stopBitsComboBox.Items.Add(StopBits.One.ToString());
stopBitsComboBox.Items.Add(StopBits.OnePointFive.ToString());
stopBitsComboBox.Items.Add(StopBits.Two.ToString());
handshakeComboBox.Items.Add(Handshake.None.ToString());
handshakeComboBox.Items.Add(Handshake.RequestToSend.ToString());
handshakeComboBox.Items.Add(Handshake.XOnXOff.ToString());
}
private void BalanceCfgCtrl_Load(object sender, EventArgs e)
{
parent = ParentForm as ComponentParametersDlg;
if (parent == null) return;
if (parent.TbfComponents != null)
{
drainValveComboBox.Items.Add("---");
foreach (var cmpnt in parent.TbfComponents)
{
if (TbfComponents.CmpntFactoryFromClassName(cmpnt.ClassName) is Elde.Valve.ValveFactory)
{
drainValveComboBox.Items.Add(cmpnt.Name);
}
}
}
Redraw();
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
capacityTextBox.Text = config.Capacity.ToString();
emptyTextBox.Text = config.Empty.ToString();
formatTextBox.Text = (config.Format.Length > 1) ? config.Format.Substring(1) : config.Format;
drainTimeTextBox.Text = config.DrainTimeSec.ToString();
drainValveComboBox.Text = string.IsNullOrEmpty(config.DrainValve) ? "---" : config.DrainValve;
comPortNrTextBox.Text = config.ComPortNr.ToString();
baudRateTextBox.Text = config.BaudRate.ToString();
parityComboBox.Text = config.Parity.ToString();
dataBitsTextBox.Text = config.DataBits.ToString();
stopBitsComboBox.Text = config.StopBits.ToString();
handshakeComboBox.Text = config.Handshake.ToString();
}
public void Unlock()
{
nameTextBox.Enabled = true;
capacityTextBox.Enabled = true;
emptyTextBox.Enabled = true;
formatTextBox.Enabled = true;
drainTimeTextBox.Enabled = true;
drainValveComboBox.Enabled = true;
comPortNrTextBox.Enabled = true;
baudRateTextBox.Enabled = true;
parityComboBox.Enabled = true;
dataBitsTextBox.Enabled = true;
stopBitsComboBox.Enabled = true;
handshakeComboBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
int dummy;
if (!int.TryParse(comPortNrTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Serial Port Number' is not valid";
}
if (!int.TryParse(baudRateTextBox.Text, out dummy) || dummy < 150 || dummy > 115200)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Baud Rate' is not valid";
}
if (!int.TryParse(dataBitsTextBox.Text, out dummy) || dummy < 7 || dummy > 8)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Data Bits' is not valid";
}
float mass;
if (!Utils.TryParseUFloat(capacityTextBox.Text, out mass) || mass <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank Capacity' is not valid";
}
if (!Utils.TryParseUFloat(emptyTextBox.Text, out mass) || mass <= 0)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank Empty' is not valid";
}
if (!int.TryParse(formatTextBox.Text, out dummy) || dummy < 0 || dummy > 9)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Decimal points' should be between 0 and 9";
}
if (!drainValveComboBox.Items.Contains(drainValveComboBox.Text))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'Drain valve'";
}
if (!int.TryParse(drainTimeTextBox.Text, out dummy) || dummy < 1 || dummy > 999)
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Tank drain time' should be between 1 and 999 sec";
}
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
config.Name = nameTextBox.Text;
config.Capacity = Utils.ParseUFloat(capacityTextBox.Text);
config.Empty = Utils.ParseUFloat(emptyTextBox.Text);
config.Format = "F" + formatTextBox.Text;
config.DrainTimeSec = int.Parse(drainTimeTextBox.Text);
config.DrainValve = drainValveComboBox.Text.Equals("---") ? string.Empty : drainValveComboBox.Text;
config.ComPortNr = int.Parse(comPortNrTextBox.Text);
config.BaudRate = int.Parse(baudRateTextBox.Text);
config.Parity = GetParity(parityComboBox.SelectedItem.ToString());
config.DataBits = int.Parse(dataBitsTextBox.Text);
config.StopBits = GetStopBits(stopBitsComboBox.SelectedItem.ToString());
config.Handshake = GetHandshake(handshakeComboBox.SelectedItem.ToString());
return flags;
}
}
}
@@ -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,507 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO.Ports;
using log4net;
using Config.Entities;
using TBF.BenchControl.Generic;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Standard
{
/// <summary>
/// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232)
/// </summary>
/// <note>
/// Implemented and tested on 15.10.2013 by Milan Hanajik
/// </note>
public class BalanceDev : TankDraining, IDevice, GenericDevices.IScale
{
/// <summary>
/// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..."
/// Warn: Start measurement when busy is true
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(BalanceDev));
public override string ToString() { return string.Format("MettlerToledo.Standard.Balance({0})", Cfg.ToString(1)); }
protected readonly BalanceCfg balanceCfg;
/// <summary>
/// Enumeration of balances via static fields and methods
/// </summary>
static int nextBalanceIdx = 0;
public static new void ResetStaticProperties()
{
nextBalanceIdx = 0;
}
public static int BalancesCount { get { return nextBalanceIdx; } }
public static BalanceDev[] Balances;
public static double[] Masses;
///
protected int balanceNr; /// 0-based balance number
protected SerialPort serialPort;
protected StringBuilder stringBuilder;
public int ScaleNr { get { return balanceNr; } }
public double Capacity { get { return balanceCfg.Capacity; } }
public int EmptyTimeSec { get { return balanceCfg.DrainTimeSec; } }
/// Buoyancy
public float BuoyancyTemp { get { return balanceCfg.BuoyancyTemp; } }
public float BuoyancyPress { get { return balanceCfg.BuoyancyPress; } }
public float BuoyancyHumi { get { return balanceCfg.BuoyancyHumi; } }
public double WeightStandardDensity { get { return balanceCfg.WeightStandardDensity; } }
/// <summary>The state of the mass measurement</summary>
public MsrmntState MsrmntState { get { return msrmntState; } }
protected MsrmntState msrmntState;
/// <summary>The mass after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
public double Mass { get { return mass; } }
protected double mass;
/// <summary>The time stamp after StartMassMeasurement() when MsrmntState == MsrmntState.Valid</summary>
public int MsrmntTimeStamp { get { return msrmntTimeStamp; } }
protected int msrmntTimeStamp;
public string Format { get { return balanceCfg.Format; } }
public BalanceDev()
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="cfg">Balance properties</param>
/// <param components="cfg">A list of components loaded so far</param>
public BalanceDev(Generic.IComponentCfg cfg)
: base(cfg)
{
balanceCfg = cfg as BalanceCfg;
balanceNr = nextBalanceIdx++;
Masses = new double[nextBalanceIdx]; /// (re)initialize the static array of masses of all balances
///
if (Balances == null || Balances.Length < nextBalanceIdx)
{
BalanceDev[] balancesSoFar = Balances;
Balances = new BalanceDev[nextBalanceIdx];
if (balancesSoFar != null) for (int i = 0; i < balancesSoFar.Length; i++) Balances[i] = balancesSoFar[i];
Balances[nextBalanceIdx - 1] = this;
}
log.Debug(this.ToString());
}
public void Initialize()
{
base.Initalize();
msrmntState = MsrmntState.Failed; /// Data not valid yet
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
stringBuilder = new StringBuilder(40);
string comPortName = "COM" + balanceCfg.ComPortNr.ToString();
serialPort = new SerialPort(comPortName, balanceCfg.BaudRate, balanceCfg.Parity, balanceCfg.DataBits, balanceCfg.StopBits);
serialPort.Handshake = balanceCfg.Handshake;
serialPort.Open();
log.FatalFormat("Successfully initialized device {0}", ToString());
}
public override bool IsEmpty()
{
return (this.mass <= balanceCfg.Empty);
}
public bool IsEmpty(double mass)
{
return (mass <= balanceCfg.Empty);
}
public void ZeroWhenStable()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - ZeroWhenStable() returns without starting zeroing the scale because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - ZeroWhenStable()", Name);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
serialPort.Write("Z\r\n");
}
public virtual void Taring()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - Taring() returns without starting taring the scale because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - Taring()", Name);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
serialPort.Write("T\r\n");
}
/// <summary>
/// Get a stable mass measurement
/// </summary>
public void GetStableMassMeasurement()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - GetStableMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - GetStableMassMeasurement()", Name);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
serialPort.Write("S\r\n");
}
/// <summary>
/// Get an immediate mass measurement
/// </summary>
public void GetImmediateMassMeasurement()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate || serialPort == null) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - GetImmediateMassMeasurement() returns without starting a measurement because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - GetImmediateMassMeasurement()", Name);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
serialPort.Write("SI\r\n");
}
/// <summary>Units for SetUnits() argument</summary>
public enum Units
{
g,
kg,
t,
lb,
oz
}
/// <summary>
/// Get the serial number
/// </summary>
/// <remarks>After a successful SetUnits(kg) mass is still sent in g. MH 15.10.2013</remarks>
public void SetUnits(Units unit)
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - SetUnits() returns without setting the units because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - SetUnits({1})", Name, unit);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
switch (unit)
{
case Units.g: serialPort.Write("U g\r\n"); break;
case Units.kg: serialPort.Write("U kg\r\n"); break;
case Units.t: serialPort.Write("U t\r\n"); break;
case Units.lb: serialPort.Write("U lb\r\n"); break;
case Units.oz: serialPort.Write("U oz\r\n"); break;
}
}
/// <summary>
/// Parse characters received from the serial port
/// </summary>
public virtual void RunDeviceBefore()
{
base.RunBefore();
if (balanceCfg.DebugLevel == DebugMode.Simulate)
{
Masses[balanceNr] = TestBenchSim.GetSimMass(balanceNr);
msrmntState = MsrmntState.Valid;
msrmntTimeStamp = StateMachine.Time;
return;
}
if (serialPort == null)
{
log.ErrorFormat("{0} - RunDevice() - serial port closed", Name);
return;
}
log.DebugFormat("{0} - RunDeviceBefore()", Name);
if (msrmntState != MsrmntState.Busy) return; /// No measurement in progress
string justReceived = serialPort.ReadExisting();
if (justReceived != null && justReceived.Length > 0)
{
log.DebugFormat("{0} - RunDeviceBefore() received {1}", Name, justReceived);
stringBuilder.Append(justReceived);
}
string currentBuffer = stringBuilder.ToString();
int eolPos = currentBuffer.IndexOf("\r\n");
if (eolPos >= 0)
{
msrmntTimeStamp = StateMachine.Time;
/// Get part of the string before EOL
string received = currentBuffer.Substring(0, eolPos);
/// Put the rest back to the string builder
stringBuilder.Clear();
if (currentBuffer.Length > eolPos + 2)
{
stringBuilder.Append(currentBuffer.Substring(eolPos + 2));
}
while (true)
{
string tmp = received.Replace(" ", " ");
if (tmp.Length == received.Length) break;
received = tmp;
}
string[] fields = received.Split(new char[] { ' ' });
if (fields.Length == 1 && fields[0].Equals("ZA")) /// Zero when stable
{
mass = 0;
Masses[balanceNr] = mass;
//msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\"", Name, received);
return;
}
else if (fields.Length < 2)
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", Unexpected error !!!", Name, received);
return;
}
if (fields[0].Equals("Z")) /// Zero when stable
{
if (fields.Length == 2 && fields[1].Equals("A"))
{
mass = 0;
Masses[balanceNr] = mass;
//msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\"", Name, received);
return;
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", error !!!", Name, received);
}
}
else if (fields[0].Equals("S")) /// Stable mass: field[1] = <mass> field[2] = "kg"
{
if (fields.Length == 3 &&
double.TryParse(fields[1],
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture,
out mass))
{
if (fields[2].Equals("g")) mass /= 1000.0f;
if (fields[2].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Mass = {2}", Name, received, mass);
}
else if (fields.Length == 4 && (fields[1].Equals("S") || fields[1].Equals("D")) &&
double.TryParse(fields[2],
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture,
out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Mass = {2}", Name, received, mass);
}
else if (fields.Length == 2 && fields[1].Equals("-"))
{
mass = 0;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Mass = {2}", Name, received, mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} Balance response = \"{1}<cr><lf>\", Overload or and unexpected error !!!", Name, received);
bool b = double.TryParse(fields[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out mass);
}
}
else if (fields[0].Equals("SD")) /// Dynamic mass: field[1] = <mass> field[2] = "kg"
{
if (fields.Length >= 3 &&
double.TryParse(fields[1],
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture,
out mass))
{
if (fields[2].Equals("g")) mass /= 1000.0f;
if (fields[2].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Mass = {2}", Name, received, mass);
}
else if (fields.Length == 2 && fields[1].Equals("-"))
{
mass = 0;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Mass = {2}", Name, received, mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", Overload or and unexpected error !!!", Name, received);
bool b = double.TryParse(fields[1], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out mass);
}
}
else if (fields[0].Equals("TB")) /// Taring
{
if (fields.Length >= 3 &&
double.TryParse(fields[1],
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture,
out mass))
{
if (fields[2].Equals("g")) mass /= 1000.0f;
if (fields[2].Equals("t")) mass *= 1000.0f;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Tara = {2}", Name, received, mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", Overload or and unexpected error !!!", Name, received);
}
}
else if (fields[0].Equals("T")) /// Taring
{
if (fields.Length >= 4 && fields[1].Equals("S") &&
double.TryParse(fields[2],
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign,
CultureInfo.InvariantCulture,
out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}<cr><lf>\", Tara = {2}", Name, received, mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", Overload or and unexpected error !!!", Name, received);
}
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}<cr><lf>\", Unexpected error !!!", Name, received);
}
}
}
/// <summary>Run this device</summary>
public void RunDeviceAfter()
{
base.RunAfter();
}
/// <summary>Stop this device</summary>
public void StopDevice()
{
if ((balanceCfg.DebugLevel != DebugMode.Simulate) && (serialPort != null))
{
serialPort.Close();
serialPort = null;
}
}
public void StopDevice2() { }
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for 'tara' in kg</param>
/// <returns>TaringOp instance reference casted to IOperaton</returns>
public IOperation TaringOp(ref DoubleBox tara)
{
return new TaringOp(this, ref tara);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for the measured mass in kg</param>
/// <returns>ReadMassOp instance reference casted to IOperaton</returns>
public IOperation ReadMassOp(ref DoubleBox mass)
{
return new ReadMassOp(this, ref mass);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="result">Reference to a variable for the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 3)</param>
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
/// <returns>ReadMassAverageOp instance reference casted to IOperaton</returns>
public IOperation ReadStableMassOp(ref DoubleBox mass, int readingsCount, double maxSpread, Config.Entities.MassMethod method)
{
return new ReadStableMassOp(this, ref mass, readingsCount, maxSpread, method);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="serialNumber">Reference to the serialNumber</param>
/// <returns>GetBalanceSNOp instance reference casted to IOperaton</returns>
public virtual IOperation GetSerNumOp(ref string serialNumber)
{
return null;
}
}
}
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class BalanceFactory : IComponentFactory
{
public string ClassName { get { return "MettlerToledo Balance"; } }
/// <summary>Max. number of components of this class in the system</summary>
public int MaxCount { get { return 5; } }
public IComponent DummyComponent() { return new BalanceDev(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new BalanceDev(cfg); }
public IComponentCfg DefaultConfig() { return new BalanceCfg(this); }
public IComponentCfgCtrl CreateCfgCtrl() { return new BalanceCfgCtrl(); }
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
{
return new BalanceDev((BalanceCfg)config);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(BalanceCfg.Serializer, component, this);
}
public void ResetStaticProperties() { BalanceDev.ResetStaticProperties(); }
}
}
@@ -0,0 +1,270 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
///
using System;
using System.Globalization;
using log4net;
using Config.Entities;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
/// <summary>
/// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232)
/// </summary>
/// <note>
/// Implemented and tested on 15.10.2013 by Milan Hanajik
/// </note>
public class BalanceNewDev : BalanceDev, IDevice, GenericDevices.IScale
{
/// <summary>
/// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..."
/// Warn: Start measurement when busy is true
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(BalanceNewDev));
public override string ToString() { return string.Format("MettlerToledo.Standard.BalanceNew({0})", Cfg.ToString(1)); }
/// <summary>Serial number after GetSerialNumber() when MsrmntState == MsrmntState.Valid</summary>
public string SerialNumber { get { return serialNumber; } }
string serialNumber;
public BalanceNewDev()
{
}
public BalanceNewDev(Generic.IComponentCfg cfg)
: base(cfg)
{
log.Debug(this.ToString());
}
/// <summary>
/// Get the serial number
/// </summary>
public void GetSerialNumber()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - GetSerialNumber() returns without getting the s/n because measurementState == MeasurementState.Busy", Name);
return;
}
log.WarnFormat("{0} - GetSerialNumber()", Name);
msrmntState = MsrmntState.Busy;
stringBuilder.Clear();
serialPort.Write(new byte[] { (byte)'I', (byte)'4', (byte)0x0D, (byte)0x0A }, 0, 4);
}
/// <summary>
/// Parse characters received from the serial port
/// </summary>
public override void RunDeviceBefore()
{
base.RunBefore();
if (balanceCfg.DebugLevel == DebugMode.Simulate)
{
mass = TestBenchSim.GetSimMass(balanceNr);
Masses[balanceNr] = mass;
serialNumber = "1234567890";
msrmntState = MsrmntState.Valid;
msrmntTimeStamp = StateMachine.Time;
return;
}
if (serialPort == null)
{
log.ErrorFormat("{0} - RunDevice() - serial port closed", Name);
return;
}
log.DebugFormat("{0} - RunDevice()", Name);
if (base.msrmntState != MsrmntState.Busy) return; /// No measurement in progress
string justReceived = serialPort.ReadExisting();
if (justReceived != null && justReceived.Length > 0)
{
log.DebugFormat("{0} - RunDevice() received {1}", Name, justReceived);
stringBuilder.Append(justReceived);
if (stringBuilder.ToString().EndsWith("\r\n"))
{
msrmntTimeStamp = StateMachine.Time;
string received = stringBuilder.ToString();
while (true)
{
string tmp = received.Replace(" ", " ");
if (tmp.Length == received.Length) break;
received = tmp;
}
string[] fields = received.Substring(0, received.Length - 2).Split(new char[] { ' ' });
if (fields.Length < 2)
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = {1}, Unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
return;
}
if (fields[0].Equals("I4")) /// Serial number
{
if (fields.Length == 3 && fields[1].Equals("A") && fields[2].Length >= 3)
{
serialNumber = fields[2].Substring(1, fields[2].Length - 2);
msrmntState = MsrmntState.Valid;
log.WarnFormat("{0} - Balance response = {1}, s/n = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), serialNumber);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = {1}, error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("Z")) /// Zero when stable
{
if (fields.Length == 2 && fields[1].Equals("A"))
{
mass = 0;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.WarnFormat("{0} - Balance response = {1}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("S")) /// Stable (field[1] == "S") or dynamic (field[1] == "D") mass measurement
{
if (fields.Length == 4 && (fields[1].Equals("S") || fields[1].Equals("D")) &&
double.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite,
CultureInfo.InvariantCulture, out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length == 2 && fields[1].Equals("-"))
{
//mass = 0;
//Masses[balanceNr] = mass;
msrmntState = MsrmntState.Failed;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length == 2 && fields[1].Equals("+"))
{
//mass = Capacity;
//Masses[balanceNr] = mass;
msrmntState = MsrmntState.Overload;
log.InfoFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else if (fields.Length >= 2 && fields[1].Equals("I"))
{
//mass = balanceCfg.Capacity;
//Masses[balanceNr] = mass;
msrmntState = MsrmntState.Overload;
log.InfoFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload or and unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("T")) /// Taring
{
if (fields.Length == 4 && fields[1].Equals("S") &&
double.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite,
CultureInfo.InvariantCulture, out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
msrmntState = MsrmntState.Valid;
log.WarnFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length >= 2 && fields[1].Equals("I"))
{
mass = mass = balanceCfg.Capacity;
msrmntState = MsrmntState.Overload;
log.WarnFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload or and unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("U"))
{
if (fields.Length == 2 && fields[1].Equals("A"))
{
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}\"", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("SI")) /// "SI I<cr><lf>" received in case of overload -> empty the tank
{
if (fields.Length >= 2 && fields[1].Equals("I"))
{
mass = balanceCfg.Capacity;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
//msrmntState = MsrmntState.Overload;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload.", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
}
}
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="serialNumber">Reference to the serialNumber</param>
/// <returns>GetBalanceSNOp instance reference casted to IOperaton</returns>
public override IOperation GetSerNumOp(ref string serialNumber)
{
return new GetSerNumOp(this, ref serialNumber);
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="units"></param>
/// <returns>SetUnitsOp instance reference casted to IOperaton</returns>
public IOperation SetUnitsOp(Units units)
{
return new SetUnitsOp(this, units);
}
}
}
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class BalanceNewFactory : IComponentFactory
{
public string ClassName { get { return "MettlerToledoBalanceSN"; } }
/// <summary>Max. number of components of this class in the system</summary>
public int MaxCount { get { return 5; } }
public IComponent DummyComponent() { return new BalanceNewDev(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new BalanceNewDev(cfg); }
public IComponentCfg DefaultConfig() { return new BalanceCfg(this); }
public IComponentCfgCtrl CreateCfgCtrl() { return new BalanceCfgCtrl(); }
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
{
return new BalanceNewDev((BalanceCfg)config);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(BalanceCfg.Serializer, component, this);
}
public void ResetStaticProperties() { BalanceNewDev.ResetStaticProperties(); }
}
}
@@ -0,0 +1,251 @@
///
/// Copyright (c) 2016-2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.IO.Ports;
using log4net;
using Config.Entities;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
/// <summary>
/// Mettler Toledo ICS4_5 Weighting terminal connected via serial interface (RS232)
/// </summary>
/// <note>
/// Implemented and tested on 15.10.2013 by Milan Hanajik
/// </note>
public class BalanceOld : BalanceDev, IDevice, GenericDevices.IScale
{
/// <summary>
/// Info: StartMassMeasurement() and "Balnce response = .., Mass = ..."
/// Warn: Start measurement when busy is true
/// </summary>
private static readonly ILog log = LogManager.GetLogger(typeof(BalanceOld));
public override string ToString() { return string.Format("MettlerToledo.Standard.BalanceOld({0})", Cfg.ToString(1)); }
public BalanceOld()
{
}
public BalanceOld(Generic.IComponentCfg cfg)
: base(cfg)
{
log.Debug(this.ToString());
}
public override void Taring()
{
if (balanceCfg.DebugLevel == DebugMode.Simulate) return;
if (msrmntState == MsrmntState.Busy)
{
log.WarnFormat("{0} - Taring() returns without starting taring the scale because measurementState == MeasurementState.Busy", Name);
return;
}
log.InfoFormat("{0} - Taring()", Name);
stringBuilder.Clear();
serialPort.Write("T\r\n");
mass = 0;
msrmntState = MsrmntState.Valid;
}
/// <summary>
/// Parse characters received from the serial port
/// </summary>
public override void RunDeviceBefore()
{
base.RunBefore();
if (balanceCfg.DebugLevel == DebugMode.Simulate)
{
mass = TestBenchSim.GetSimMass(balanceNr);
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
msrmntTimeStamp = StateMachine.Time;
return;
}
if (serialPort == null)
{
log.ErrorFormat("{0} - RunDevice() - serial port closed", Name);
return;
}
log.DebugFormat("{0} - RunDevice()", Name);
if (base.msrmntState != MsrmntState.Busy) return; /// No measurement in progress
string justReceived = serialPort.ReadExisting();
if (justReceived != null && justReceived.Length > 0)
{
log.DebugFormat("{0} - RunDevice() received {1}", Name, justReceived);
stringBuilder.Append(justReceived);
if (stringBuilder.ToString().EndsWith("\r\n"))
{
msrmntTimeStamp = StateMachine.Time;
string received = stringBuilder.ToString();
while (true)
{
string tmp = received.Replace(" ", " ");
if (tmp.Length == received.Length) break;
received = tmp;
}
string[] fields = received.Substring(0, received.Length - 2).Split(new char[] { ' ' });
if (fields.Length < 2)
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = {1}, Unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
return;
}
else if (fields[0].Equals("Z")) /// Zero when stable
{
if (fields.Length == 2 && fields[1].Equals("A"))
{
mass = 0;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("S")) /// Stable (field[1] == "S") or dynamic (field[1] == "D") mass measurement
{
if (fields.Length == 4 && fields[1].Equals("S") &&
double.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite,
CultureInfo.InvariantCulture, out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length == 4 && fields[1].Equals("D") &&
double.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite,
CultureInfo.InvariantCulture, out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length == 2 && fields[1].Equals("-"))
{
mass = 0;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length == 2 && fields[1].Equals("+"))
{
mass = Capacity;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else if (fields.Length >= 2 && fields[1].Equals("I"))
{
mass = balanceCfg.Capacity;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Overload;
log.InfoFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload or and unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("T")) /// Taring
{
if (fields.Length == 4 && fields[1].Equals("S") &&
double.TryParse(fields[2], NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite,
CultureInfo.InvariantCulture, out mass))
{
if (fields[3].Equals("g")) mass /= 1000.0f;
if (fields[3].Equals("t")) mass *= 1000.0f;
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = {1}, Mass = {2}", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else if (fields.Length >= 2 && fields[1].Equals("I"))
{
mass = mass = balanceCfg.Capacity;
msrmntState = MsrmntState.Overload;
log.InfoFormat("{0} - Balance response = {1}, Overload", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"), mass);
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload or and unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("U"))
{
if (fields.Length == 2 && fields[1].Equals("A"))
{
msrmntState = MsrmntState.Valid;
log.InfoFormat("{0} - Balance response = \"{1}\"", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
else
{
msrmntState = MsrmntState.Failed;
log.WarnFormat("{0} - Balance response = \"{1}\", Unexpected error !!!", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
else if (fields[0].Equals("SI")) /// "SI I<cr><lf>" received in case of overload -> empty the tank
{
if (fields.Length >= 2 && fields[1].Equals("I"))
{
mass = balanceCfg.Capacity;
Masses[balanceNr] = mass;
msrmntState = MsrmntState.Valid;
//msrmntState = MsrmntState.Overload;
log.WarnFormat("{0} - Balance response = \"{1}\", Overload.", Name,
received.Replace("\r", "<cr>").Replace("\n", "<lf>"));
}
}
}
}
}
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="units"></param>
/// <returns>SetUnitsOp instance reference casted to IOperaton</returns>
public IOperation SetUnitsOp(Units units)
{
return new SetUnitsOp(this, units);
}
}
}
@@ -0,0 +1,36 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
///
using System.Collections.Generic;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class BalanceOldFactory : IComponentFactory
{
public string ClassName { get { return "MettlerToledoBalanceOld"; } }
/// <summary>Max. number of components of this class in the system</summary>
public int MaxCount { get { return 5; } }
public IComponent DummyComponent() { return new BalanceOld(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new BalanceOld(cfg); }
public IComponentCfg DefaultConfig() { return new BalanceCfg(this); }
public IComponentCfgCtrl CreateCfgCtrl() { return new BalanceCfgCtrl(); }
public IComponent ComponentFromCmpntCfg(IComponentCfg config, IList<Generic.IComponent> components)
{
return new BalanceOld((BalanceCfg)config);
}
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(BalanceCfg.Serializer, component, this);
}
public void ResetStaticProperties() { BalanceOld.ResetStaticProperties(); }
}
}
@@ -0,0 +1,70 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
///
using System;
using log4net;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class GetSerNumOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(GetSerNumOp));
public override string ToString() { return string.Format("GetSerNumOp(.,.)"); }
/// Set by the constructor
BalanceNewDev scale;
string serialNumber;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="scale">Balance device instance</param>
/// <param name="serialNumber">Reference to the serialNumber</param>
public GetSerNumOp(BalanceNewDev scale, ref string serialNumber)
{
if (scale == null) throw new ArgumentNullException("balanceDev");
this.scale = scale;
this.serialNumber = serialNumber;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
log.DebugFormat("{0} - Start()", scale.Name);
scale.GetSerialNumber();
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// </returns>
public Event Run()
{
log.DebugFormat("{0} - GetSerNumOp.Run() ... MsrmntState = {1}", scale.Name, scale.MsrmntState);
if (scale.MsrmntState == MsrmntState.Valid)
{
serialNumber = scale.SerialNumber;
return Event.BalanceDone; /// S/N read successful
}
else if (scale.MsrmntState == MsrmntState.Failed)
{
return Event.Error; /// S/N read failed
}
else
{
return Event.Busy; /// No result yet
}
}
/// <summary>Stop this operation</summary>
public void Stop()
{
log.DebugFormat("{0} - Stop()", scale.Name);
}
}
}
@@ -0,0 +1,81 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class ReadMassOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadMassOp));
public override string ToString() { return string.Format("ReadMassOp(.,.)"); }
bool started;
bool done;
/// Set by the constructor
BalanceDev scale;
DoubleBox result;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="scale">Balance device instance</param>
/// <param name="requiredReadingsCount">Required mass readings count (>= 3)</param>
/// <param name="result">Reference to the measured mass in kg</param>
public ReadMassOp(BalanceDev scale, ref DoubleBox result)
{
if (scale == null) throw new ArgumentNullException("balanceDev");
this.scale = scale;
this.result = result;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
scale.GetImmediateMassMeasurement();
started = true;
done = false;
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (!started)
{
scale.GetImmediateMassMeasurement();
started = true;
done = false;
return Event.Busy;
}
else if (started && scale.MsrmntState != MsrmntState.Busy)
{
if (scale.MsrmntState == MsrmntState.Valid) result.Val = scale.Mass;
log.InfoFormat("ReadMassOp.Run() ... state={0}, mass={1} ... returning Event.BalanceDone",
scale.MsrmntState, scale.Mass);
done = true;
started = false;
return Event.BalanceDone; /// Mass read OK
}
else
{
return Event.Busy;
}
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,181 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Standard
{
/// <summary>
/// Operation to read more mass values and average them to obtain a more accurate result.
/// </summary>
public class ReadStableMassOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(ReadStableMassOp));
public override string ToString() { return string.Format("ReadStableMassOp(.,{0},.)", totalReadingsCount); }
/// Set by the constructor
BalanceDev balanceDev;
int totalReadingsCount;
double maxSpread; /// Maximum spread of measurements in kg (otherwise the measurement continues)
Config.Entities.MassMethod method; /// by the scale, mass spread threshold or mass standard deviation threshold
DoubleBox result;
/// Operation specific
double[] massReadings;
int currentReadingsCount;
bool measurementCompleted;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="result">Reference to the measured mass in kg</param>
/// <param name="readingsCount">Required mass readings count (>= 4)</param>
/// <param name="maxSpread">Maximum spread of measurements in kg (otherwise the measurement continues)</param>
/// <param name="method">Method: false = slow (precise), true = fast (immediate)</param>
public ReadStableMassOp(BalanceDev balanceDev, ref DoubleBox result, int readingsCount, double maxSpread, Config.Entities.MassMethod method)
{
if (balanceDev == null) throw new ArgumentNullException("balanceDev");
this.balanceDev = balanceDev;
this.totalReadingsCount = (readingsCount < 4) ? 5 : readingsCount; /// readingsCount is at least 4
this.maxSpread = (maxSpread == 0) ? (balanceDev.Capacity / 20000.0) : maxSpread;
this.method = method;
this.result = result;
massReadings = new double[totalReadingsCount];
currentReadingsCount = 0;
measurementCompleted = false;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
currentReadingsCount = 0;
measurementCompleted = false;
if (method == Config.Entities.MassMethod.Scale)
balanceDev.GetStableMassMeasurement();
else
balanceDev.GetImmediateMassMeasurement();
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (measurementCompleted) return Event.BalanceDone;
if (balanceDev.MsrmntState == MsrmntState.Busy)
{
return Event.None; /// Wait for a mass measurement
}
if (balanceDev.MsrmntState == MsrmntState.Valid)
{
/// Save the measurement
if (currentReadingsCount < totalReadingsCount)
{
massReadings[currentReadingsCount++] = balanceDev.Mass;
}
else
{
/// Shift data in the (already full) buffer, save the mass into the last buffer item
for (int i = 1; i < totalReadingsCount; i++)
{
massReadings[i - 1] = massReadings[i];
}
massReadings[totalReadingsCount - 1] = balanceDev.Mass;
}
}
if (currentReadingsCount >= totalReadingsCount)
{
Array.Sort(massReadings);
#if STABLE_MASS_EXTRAS
if (method == Config.Entities.MassMethod.Spread)
{
/// Immediate mass measurement, end condition calculated below
if ((massReadings[totalReadingsCount - 2] - massReadings[1]) <= maxSpread)
{
double massSum = 0;
for (int i = 1; i < totalReadingsCount - 1; i++) massSum += massReadings[i];
result.Val = (massSum / (totalReadingsCount - 2));
log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", result.Val);
measurementCompleted = true;
return Event.BalanceDone; /// Mass has just been calculated
}
}
else if (method == Config.Entities.MassMethod.StdDev)
{
/// Immediate mass measurement, end condition calculated below
double massSum = 0;
for (int i = 1; i < totalReadingsCount - 1; i++) massSum += massReadings[i];
double ave = (massSum / (totalReadingsCount - 2));
double sdev = 0;
for (int i = 1; i < totalReadingsCount - 1; i++) sdev += ((massReadings[i] - ave) * (massReadings[i] - ave));
if (Math.Sqrt(sdev / (totalReadingsCount - 2)) <= maxSpread)
{
result.Val = ave;
log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", result.Val);
measurementCompleted = true;
return Event.BalanceDone; /// Mass has just been calculated
}
}
else
#endif
{
/// Stable mass measurement
/// Sort, exclude min. and max. values, calculate the average
double massSum = 0;
for (int i = 1; i < totalReadingsCount - 1; i++) massSum += massReadings[i];
result.Val = (massSum / (totalReadingsCount - 2));
log.InfoFormat("ReadStableMassOp.Run() ... valid mass={0} ... returning Event.BalanceDone", result.Val);
measurementCompleted = true;
return Event.BalanceDone; /// Mass has just been calculated
}
}
if (measurementCompleted)
{
return Event.BalanceDone;
}
else
{
///
/// Start a new measurement
///
if (method == Config.Entities.MassMethod.Scale)
balanceDev.GetStableMassMeasurement();
else
balanceDev.GetImmediateMassMeasurement();
return Event.None;
}
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}
@@ -0,0 +1,62 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
/// Author: Milan Hanajik
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class SetUnitsOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SetUnitsOp));
public override string ToString() { return string.Format("SetUnitsOp({0})", units); }
/// Set by the constructor
BalanceDev balanceDev;
BalanceDev.Units units;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="result">Reference to the serialNumber</param>
public SetUnitsOp(BalanceDev balanceDev, BalanceDev.Units units)
{
if (balanceDev == null) throw new ArgumentNullException("balanceDev");
this.balanceDev = balanceDev;
this.units = units;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
log.DebugFormat("{0} - Start()", balanceDev.Name);
balanceDev.SetUnits(units);
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// </returns>
public Event Run()
{
if (balanceDev.MsrmntState == MsrmntState.Valid) return Event.BalanceDone; /// Units set
if (balanceDev.MsrmntState == MsrmntState.Failed) return Event.Error; /// Failed
return Event.None; /// No result yet
}
/// <summary>Stop this operation</summary>
public void Stop()
{
log.DebugFormat("{0} - Stop()", balanceDev.Name);
}
}
}
@@ -0,0 +1,80 @@
///
/// Copyright (c) 2013-2016 Sensus Metering Systems
///
using System;
using log4net;
using TBF.Boxes;
namespace TBF.BenchControl.MettlerToledo.Standard
{
public class TaringOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(TaringOp));
public override string ToString() { return string.Format("TaringOp(.,.)"); }
bool done;
/// Set by the constructor
BalanceDev balanceDev;
DoubleBox tara;
/// <summary>
/// Events: BalanceDone, Error
/// </summary>
/// <param name="balanceDev">Balance device instance</param>
/// <param name="result">Reference to variable for 'tara' in kg</param>
public TaringOp(BalanceDev balanceDev, ref DoubleBox tara)
{
if (balanceDev == null) throw new ArgumentNullException("balanceDev");
this.balanceDev = balanceDev;
this.tara = tara;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
log.DebugFormat("{0} - Start()", balanceDev.Name);
done = false;
balanceDev.Taring();
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.None
/// Event.BalanceDone
/// Event.Error . . . . . Current.Tick == null
/// </returns>
public Event Run()
{
if (done) return Event.BalanceDone; /// Taring has been done already
if (balanceDev.MsrmntState == MsrmntState.Busy) return Event.Busy;
if (balanceDev.MsrmntState == MsrmntState.Overload)
{
tara.Val = balanceDev.Capacity;
done = true;
return Event.BalanceOverload;
}
if (balanceDev.MsrmntState == MsrmntState.Valid)
{
tara.Val = balanceDev.Mass;
done = true;
return Event.BalanceDone; /// Taring completed
}
balanceDev.Taring(); /// Failed -> repeat taring
return Event.Busy;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
log.DebugFormat("{0} - Stop()", balanceDev.Name);
}
}
}
@@ -0,0 +1,144 @@
///
/// Copyright (c) 2017 Sensus Metering Systems
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl.GenericDevices;
using TBF.Resources;
namespace TBF.BenchControl.MettlerToledo
{
public enum DrainState
{
None,
OpeningDV_Start,
OpeningDV_Run,
OpeningDV_Stop,
Draining,
ClosingDV_Start,
ClosingDV_Run,
ClosingDV_Stop,
TankClosed,
}
public class TankDraining : ComponentBase, ITankDraining, ISequenceCondition
{
private static readonly ILog log = LogManager.GetLogger(typeof(TankDraining));
readonly GenericDevices.ITankDrainingCfg tankDrainingCfg;
private IValve drainValve;
public GenericDevices.IValve DrainValve { get { return drainValve; } }
private IOperation openTheDrainValveOp;
private IOperation closeTheDrainValveOp;
private IOperation waitTankEmptyOp;
DrainState drainState;
public TankDraining()
: base()
{
openTheDrainValveOp = null;
closeTheDrainValveOp = null;
waitTankEmptyOp = null;
}
public TankDraining(Generic.IComponentCfg cfg)
: base(cfg)
{
tankDrainingCfg = cfg as GenericDevices.ITankDrainingCfg;
if (tankDrainingCfg == null) throw new Exception(string.Format("Cannot create component {0}", cfg.Name));
openTheDrainValveOp = null;
closeTheDrainValveOp = null;
waitTankEmptyOp = null;
}
protected void Initalize()
{
drainValve = TbfComponents.FindComponent(tankDrainingCfg.DrainValve) as IValve;
openTheDrainValveOp = new Elde.SetValvesOp(StateMachine.ControlBoard, drainValve, null);
closeTheDrainValveOp = new Elde.SetValvesOp(StateMachine.ControlBoard, null, drainValve);
waitTankEmptyOp = new WaitTankEmptyOp(this);
}
protected void RunBefore()
{
switch (drainState)
{
case DrainState.OpeningDV_Start:
openTheDrainValveOp.Start();
drainState = DrainState.OpeningDV_Run;
return;
case DrainState.OpeningDV_Run:
if (openTheDrainValveOp.Run() == Event.ValvesSet) drainState = DrainState.OpeningDV_Stop;
return;
case DrainState.OpeningDV_Stop:
openTheDrainValveOp.Stop();
return;
case DrainState.Draining:
if (IsEmpty()) drainState = DrainState.ClosingDV_Start;
return;
case DrainState.ClosingDV_Start:
closeTheDrainValveOp.Start();
drainState = DrainState.ClosingDV_Run;
return;
case DrainState.ClosingDV_Run:
if (closeTheDrainValveOp.Run() == Event.ValvesSet) drainState = DrainState.ClosingDV_Stop;
return;
case DrainState.ClosingDV_Stop:
closeTheDrainValveOp.Stop();
return;
default:
return;
}
}
protected void RunAfter() { } /// Not used
public virtual string GetName() { return string.Empty; }
public virtual bool IsEmpty() { return false; }
public int ConditionsCount { get { return 3; } }
/// Strings are added to the combo-box for transition sequence condition selection
public string ConditionName(int i)
{
switch (i)
{
case 0: return string.Format(Strings._0_open_the_drain_valve, Name);
case 1: return string.Format(Strings._0_close_the_drain_valve, Name);
case 2: return string.Format(Strings._0_wait_until_the_tank_is_empty, Name);
default: return string.Empty;
}
}
/// Operation to be executed as a part of a transition sequence
public IOperation ConditionOp(int i)
{
switch (i)
{
case 0: return openTheDrainValveOp;
case 1: return closeTheDrainValveOp;
case 2: return waitTankEmptyOp;
default: return null;
}
}
}
}
@@ -0,0 +1,50 @@
///
/// Copyright (c) 2017 Sensus Metering Systems
///
using log4net;
namespace TBF.BenchControl.MettlerToledo
{
public class WaitTankEmptyOp : IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(WaitTankEmptyOp));
public override string ToString() { return string.Format("WaitTankEmptyOp()"); }
readonly GenericDevices.ITankDraining tankDraining;
bool conditionMet;
/// <summary>
/// Events: ConditionMet, ConditionNotMet
/// </summary>
/// <param name="tankDraining">Tank draining (Balance device) instance</param>
public WaitTankEmptyOp(GenericDevices.ITankDraining tankDraining)
{
this.tankDraining = tankDraining;
log.Debug(this.ToString());
}
/// <summary>Start this operation</summary>
public void Start()
{
conditionMet = tankDraining.IsEmpty();
}
/// <summary>Run this operation</summary>
/// <returns>
/// Event.ConditionMet . . . tank is empty
/// Event.ConditionNotMet . tank is not empty
/// </returns>
public Event Run()
{
conditionMet = conditionMet || tankDraining.IsEmpty();
return conditionMet ? Event.ConditionMet : Event.ConditionNotMet;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
}
}
}