SerialStream.S640Stream in progress.

This commit is contained in:
Milan Hanajik
2021-05-25 22:13:11 +02:00
parent 9d01d565df
commit 7613613fad
26 changed files with 1502 additions and 1122 deletions
@@ -0,0 +1,12 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
namespace TBF.Rig.GenericDevices
{
public interface IHasClearSessionData
{
void ClearSessionData();
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ using System;
namespace TBF.Rig.GenericDevices
{
interface IHasTestName
public interface IHasTestName
{
string TestName { set; }
int TestRepeats { set; }
@@ -7,6 +7,8 @@ namespace TBF.Rig.GenericDevices
{
interface IRegReaderDatastream : IRegReader
{
IOperation ReadDatastreamOp();
bool NoSamples { get; }
double VolumeLtrStart { get; }
double VolumeLtrEnd { get; }
-1
View File
@@ -1,7 +1,6 @@
///
/// Copyright (c) 2015-2021 Sensus Slovensko a.s.
///
using System.IO;
using System.Collections.Generic;
using System.IO.Ports;
using System.Xml.Serialization;
@@ -15,7 +15,7 @@ namespace TBF.Rig.RegisterReaders.KPackE.Radio
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new Radio(cfg); }
public IComponentCfg DefaultConfig() { return new RadioCfg(this); }
public IComponentCfg DefaultConfig() { return new RadioCfg("KPackE.Radio", this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
+128 -15
View File
@@ -1,7 +1,6 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
/// Copyright (c) 2018-2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Xml.Serialization;
@@ -10,12 +9,12 @@ using TBF.Rig.Generic;
namespace TBF.Rig.RegisterReaders.KPackE.Radio
{
public class RadioCfg : ComponentCfgBase, Generic.IComponentCfg
public class RadioCfg : ComponentCfgBase, IComponentCfg, Config.Entities.IParamsProvider
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(RadioCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new RadioCfgCtrl(); }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
///
/// Serialized parameters
@@ -28,10 +27,20 @@ namespace TBF.Rig.RegisterReaders.KPackE.Radio
public Handshake Handshake;
/// Private parameterless constructor invoked by all other (public) constructors
RadioCfg()
RadioCfg() { }
public RadioCfg(string name, IComponentFactory factory)
{
Name = "KPackE.Radio";
Name = name;
Factory = factory;
ParentName = string.Empty;
InitializeAll();
}
public string ComponentName { get { return Name; } }
public void InitializeAll()
{
ComPortNr = 3;
BaudRate = 38400;
Parity = System.IO.Ports.Parity.None;
@@ -40,16 +49,120 @@ namespace TBF.Rig.RegisterReaders.KPackE.Radio
Handshake = System.IO.Ports.Handshake.None;
}
public RadioCfg(IComponentFactory factory)
: this()
string[] paramNames = new string[]
{
this.Factory = factory;
"Serial port number", /// 0
"Baud rate", /// 1
"Parity", /// 2
"Data bits", /// 3
"Stop bits", /// 4
"Handshake", /// 5
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
public ICollection<string> ParamValues(int i)
{
switch (i)
{
case 1:
return new string[] { "150", "300", "600", "1200", "2400", "4800", "9600",
"19200", "38400", "57600", "76800", "115200"};
case 2:
return new string[] { Parity.None.ToString(), Parity.Odd.ToString(), Parity.Even.ToString() };
case 3:
return new string[] { "7", "8" };
case 4:
return new string[] { StopBits.None.ToString(),
StopBits.One.ToString(),
StopBits.OnePointFive.ToString(),
StopBits.Two.ToString() };
case 5:
return new string[] { Handshake.None.ToString(),
Handshake.XOnXOff.ToString(),
Handshake.RequestToSend.ToString(),
Handshake.RequestToSendXOnXOff.ToString() };
default:
return null;
}
}
public string ToString(int i)
{
return string.Format("Name={0}, Com{1}, {2}Bd, {3}-bits, parity={4}, stopBits={5}, {6}",
Name, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
}
public string ToString(int i)
{
switch (i)
{
case 0: return ComPortNr.ToString();
case 1: return BaudRate.ToString();
case 2: return Parity.ToString();
case 3: return DataBits.ToString();
case 4: return StopBits.ToString();
case 5: return Handshake.ToString();
default:
return string.Format("{0}: Com{1}, {2}Bd, {3}-bits, parity={4}, stopBits={5}, {6}",
Name, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
}
public CfgUpdateFlags UpdateParam(int i, string str)
{
switch (i)
{
case 0: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 1: BaudRate = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 2: Parity = TBF.Utils.GetParity(str); return CfgUpdateFlags.RestartRqrd;
case 3: DataBits = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 4: StopBits = TBF.Utils.GetStopBits(str); return CfgUpdateFlags.RestartRqrd;
case 5: Handshake = TBF.Utils.GetHandshake(str); return CfgUpdateFlags.RestartRqrd;
default: return CfgUpdateFlags.None;
}
}
public bool ValidateParam(int i, string strValue, out string message)
{
message = string.Empty;
int idummy;
switch (i)
{
case 0:
if (int.TryParse(strValue, out idummy) && idummy > 0) return true;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
if (ParamValues(i).Contains(strValue)) return true;
break;
default:
message = "Invalid index";
return false;
}
message = ParamName(i) + " is invalid";
return false;
}
void CopyContentTo(RadioCfg prms)
{
prms.ComPortNr = this.ComPortNr;
prms.BaudRate = this.BaudRate;
prms.Parity = this.Parity;
prms.DataBits = this.DataBits;
prms.StopBits = this.StopBits;
prms.Handshake = this.Handshake;
}
public Config.Entities.IParamsProvider Clone()
{
RadioCfg pars = new RadioCfg();
CopyContentTo(pars);
return pars;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
}
}
}
@@ -1,171 +0,0 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using System.IO.Ports;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.RegisterReaders.KPackE.Radio
{
public partial class RadioCfgCtrl : UserControl, IComponentCfgCtrl
{
public bool ShowMore { get { return false; } }
RadioCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as RadioCfg;
Redraw();
}
}
public RadioCfgCtrl()
{
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 ModbusCfgCtrl_Load(object sender, EventArgs e)
{
nameLabel.Text = Strings.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;
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;
comPortNrTextBox.Enabled = true;
baudRateTextBox.Enabled = true;
parityComboBox.Enabled = true;
dataBitsTextBox.Enabled = true;
stopBitsComboBox.Enabled = true;
handshakeComboBox.Enabled = true;
}
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.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;
}
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";
}
return flags;
}
}
}
@@ -1,229 +0,0 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
namespace TBF.Rig.RegisterReaders.KPackE.Radio
{
partial class RadioCfgCtrl
{
/// <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.comPortNrTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.baudRateLabel = new System.Windows.Forms.Label();
this.baudRateTextBox = new System.Windows.Forms.TextBox();
this.partityLabel = new System.Windows.Forms.Label();
this.dataBitsLabel = new System.Windows.Forms.Label();
this.dataBitsTextBox = new System.Windows.Forms.TextBox();
this.stopBitsLabel = new System.Windows.Forms.Label();
this.handshakeLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.parityComboBox = new System.Windows.Forms.ComboBox();
this.stopBitsComboBox = new System.Windows.Forms.ComboBox();
this.handshakeComboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comPortNrTextBox
//
this.comPortNrTextBox.Enabled = false;
this.comPortNrTextBox.Location = new System.Drawing.Point(140, 52);
this.comPortNrTextBox.Name = "comPortNrTextBox";
this.comPortNrTextBox.Size = new System.Drawing.Size(34, 20);
this.comPortNrTextBox.TabIndex = 4;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(29, 55);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(98, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Serial Port Number:";
//
// baudRateLabel
//
this.baudRateLabel.AutoSize = true;
this.baudRateLabel.Location = new System.Drawing.Point(29, 79);
this.baudRateLabel.Name = "baudRateLabel";
this.baudRateLabel.Size = new System.Drawing.Size(58, 13);
this.baudRateLabel.TabIndex = 5;
this.baudRateLabel.Text = "Baud Rate";
//
// baudRateTextBox
//
this.baudRateTextBox.Enabled = false;
this.baudRateTextBox.Location = new System.Drawing.Point(140, 76);
this.baudRateTextBox.Name = "baudRateTextBox";
this.baudRateTextBox.Size = new System.Drawing.Size(130, 20);
this.baudRateTextBox.TabIndex = 6;
//
// partityLabel
//
this.partityLabel.AutoSize = true;
this.partityLabel.Location = new System.Drawing.Point(29, 103);
this.partityLabel.Name = "partityLabel";
this.partityLabel.Size = new System.Drawing.Size(33, 13);
this.partityLabel.TabIndex = 7;
this.partityLabel.Text = "Parity";
//
// dataBitsLabel
//
this.dataBitsLabel.AutoSize = true;
this.dataBitsLabel.Location = new System.Drawing.Point(29, 127);
this.dataBitsLabel.Name = "dataBitsLabel";
this.dataBitsLabel.Size = new System.Drawing.Size(50, 13);
this.dataBitsLabel.TabIndex = 9;
this.dataBitsLabel.Text = "Data Bits";
//
// dataBitsTextBox
//
this.dataBitsTextBox.Enabled = false;
this.dataBitsTextBox.Location = new System.Drawing.Point(140, 124);
this.dataBitsTextBox.Name = "dataBitsTextBox";
this.dataBitsTextBox.Size = new System.Drawing.Size(34, 20);
this.dataBitsTextBox.TabIndex = 10;
//
// stopBitsLabel
//
this.stopBitsLabel.AutoSize = true;
this.stopBitsLabel.Location = new System.Drawing.Point(29, 151);
this.stopBitsLabel.Name = "stopBitsLabel";
this.stopBitsLabel.Size = new System.Drawing.Size(49, 13);
this.stopBitsLabel.TabIndex = 11;
this.stopBitsLabel.Text = "Stop Bits";
//
// handshakeLabel
//
this.handshakeLabel.AutoSize = true;
this.handshakeLabel.Location = new System.Drawing.Point(29, 175);
this.handshakeLabel.Name = "handshakeLabel";
this.handshakeLabel.Size = new System.Drawing.Size(62, 13);
this.handshakeLabel.TabIndex = 13;
this.handshakeLabel.Text = "Handshake";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(140, 28);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(30, 31);
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(137, 7);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComonentName";
//
// parityComboBox
//
this.parityComboBox.Enabled = false;
this.parityComboBox.FormattingEnabled = true;
this.parityComboBox.Location = new System.Drawing.Point(140, 100);
this.parityComboBox.Name = "parityComboBox";
this.parityComboBox.Size = new System.Drawing.Size(130, 21);
this.parityComboBox.TabIndex = 8;
//
// stopBitsComboBox
//
this.stopBitsComboBox.Enabled = false;
this.stopBitsComboBox.FormattingEnabled = true;
this.stopBitsComboBox.Location = new System.Drawing.Point(140, 148);
this.stopBitsComboBox.Name = "stopBitsComboBox";
this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21);
this.stopBitsComboBox.TabIndex = 12;
//
// handshakeComboBox
//
this.handshakeComboBox.Enabled = false;
this.handshakeComboBox.FormattingEnabled = true;
this.handshakeComboBox.Location = new System.Drawing.Point(140, 172);
this.handshakeComboBox.Name = "handshakeComboBox";
this.handshakeComboBox.Size = new System.Drawing.Size(130, 21);
this.handshakeComboBox.TabIndex = 14;
//
// AmbientCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
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 = "AmbientCfgCtrl";
this.Size = new System.Drawing.Size(300, 240);
this.Load += new System.EventHandler(this.ModbusCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox comPortNrTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label baudRateLabel;
private System.Windows.Forms.TextBox baudRateTextBox;
private System.Windows.Forms.Label partityLabel;
private System.Windows.Forms.Label dataBitsLabel;
private System.Windows.Forms.TextBox dataBitsTextBox;
private System.Windows.Forms.Label stopBitsLabel;
private System.Windows.Forms.Label handshakeLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.ComboBox parityComboBox;
private System.Windows.Forms.ComboBox stopBitsComboBox;
private System.Windows.Forms.ComboBox handshakeComboBox;
}
}
@@ -1,120 +0,0 @@
<?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,243 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Globalization;
using System.Text;
namespace TBF.Rig.RegisterReaders.S640Stream
{
public class DatastreamFrame
{
public const int FrameLength = 49; /// Including CR,LF
public static double VolumeScaleFactor = 1000.0; /// Raw volume is in ml
public static double TimeScaleFactor = 1000.0; /// Raw time is in ms
///
/// Stored values
///
public FrameFlags Flags;
public DateTime DateTime; /// From PC
public int Counter;
public float RefFlow; /// [m3/h]
char[] data = new char[FrameLength - 2];
public Int32 VolumeRaw;
public Int64 VolumeRawExt;
public Int64 Timestamp;
public Int64 TimestampExt;
///
/// Calculated values
///
public double Volume() { return (double)VolumeRawExt / VolumeScaleFactor; }
public double TimestampDbl() { return (double)TimestampExt / TimeScaleFactor; }
public string Label()
{
if (Flags == FrameFlags.OK_TestStart) return "#### start test ####";
else if (Flags == FrameFlags.OK_TestEnd) return "#### end of test ####";
else return string.Empty;
}
static DatastreamFrame()
{
}
public DatastreamFrame()
{
}
/// <summary>
/// Parses optical telegram and returns OptoTelegramRaw object
/// </summary>
/// <description>
/// Create a configuration structure from a complete byte array
///
/// Telegram description:
///
/// AAAAAAAAAAAA[tab]BBBBBBBBBB[tab]CCCCCCCCC[tab]DDDDDDDDDD[tab]EE[cr][lf] (49 bytes)
///
/// Data Comment Type Calculate to decimal
/// ----------------------------------------------------------------
/// AAAAAAAAAAAA PCB number Decimal
/// BBBBBBBBBB Radio address Decimal
/// CCCCCCCCC Meter reading Decimal Volume in ml
/// DDDDDDDDDD Timestamp Decimal Time in ms
/// EE Checksum Hexadecimal
/// ----------------------------------------------------------------
///
/// Example:
/// 540210730770 4291524429 000250215 0433411626 4F
/// 540210730770 4291524429 000250215 0433411876 56
/// ...
/// </description>
/// <param name="data">A complete byte array data</param>
/// <returns>true = telegram OK, false = telegram NOK</returns>
public bool UpdateFromString(string frame, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast, int counter)
{
DateTime = DateTime.Now;
Counter = counter;
RefFlow = (float)Sequences.ProcessData.RefFlow.Val;
if (frame == null || frame.Length < FrameLength ||
frame[FrameLength - 2] != '\r' || frame[FrameLength - 1] != '\n' ||
frame[12] != '\t' || frame[23] != '\t' || frame[33] != '\t' || frame[44] != '\t')
{
Flags = FrameFlags.InvalidFrame;
return false;
}
/// Copy data into the fixed size buffer
int sum = 0;
for (int i = 0; i < FrameLength - 4; i++)
{
data[i] = frame[i];
sum += (int)frame[i];
}
data[FrameLength - 4] = frame[FrameLength - 4];
data[FrameLength - 3] = frame[FrameLength - 3];
byte checkSum;
bool chksumOk = byte.TryParse(frame.Substring(FrameLength - 4, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out checkSum)
&& checkSum == (sum & 0xFF);
bool volumeOk = Int32.TryParse(frame.Substring(24, 9), out VolumeRaw);
volumeRawExtLast = VolumeRawExt = VolumeRaw;
bool timeOk = Int64.TryParse(frame.Substring(34, 10), out Timestamp);
timestampExtLast = TimestampExt = Timestamp;
bool allOk = volumeOk && timeOk && chksumOk;
Flags = allOk ? FrameFlags.OK : FrameFlags.InvalidFrame;
return allOk;
}
/// <summary>
/// Alternative to UpdateFromString(...) when data are flushed
/// </summary>
public bool UpdateFromStringDummy(string frame, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast,
out Int64 pcbNumber, out Int64 radioAddress)
{
pcbNumber = 0;
radioAddress = 0;
if (frame == null || frame.Length < FrameLength ||
frame[FrameLength - 2] != '\r' || frame[FrameLength - 1] != '\n' ||
frame[12] != '\t' || frame[23] != '\t' || frame[33] != '\t' || frame[44] != '\t')
{
Flags = FrameFlags.InvalidFrame;
return false;
}
/// Copy data into the fixed size buffer
int sum = 0;
for (int i = 0; i < FrameLength - 4; i++) sum += (int)frame[i];
byte checkSum;
bool chksumOk = byte.TryParse(frame.Substring(FrameLength - 4, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out checkSum)
&& checkSum == (sum & 0xFF);
bool pcbNumberOk = Int64.TryParse(frame.Substring(0, 12), out pcbNumber);
bool radioAddressOk = Int64.TryParse(frame.Substring(13, 10), out radioAddress);
bool volumeOk = Int32.TryParse(frame.Substring(24, 9), out VolumeRaw);
volumeRawExtLast = VolumeRawExt = VolumeRaw;
bool timeOk = Int64.TryParse(frame.Substring(34, 10), out Timestamp);
timestampExtLast = TimestampExt = Timestamp;
return chksumOk && pcbNumberOk && radioAddressOk && volumeOk && timeOk;
}
public void SetFlags(FrameFlags flags)
{
this.Flags = flags;
}
public override string ToString()
{
if (Flags == FrameFlags.SyncError)
{
return "Sychronization error";
}
else if (Flags == FrameFlags.InvalidFrame)
{
return "Invalid telegram";
}
else /// if (flags == OptoTelegramFlags.OK || OptoTelegramFlags.OK_TestStart || OptoTelegramFlags.OK_TestEnd)
{
StringBuilder sb = new StringBuilder(FrameLength - 2);
for (int i = 0; i < FrameLength - 2; i++) sb.Append(data[i]);
return string.Format("{0}:{1}:{2}.{3} #{4} : {5} Volume={6} Time={7} {8}",
DateTime.Hour.ToString("D2"),
DateTime.Minute.ToString("D2"),
DateTime.Second.ToString("D2"),
DateTime.Millisecond.ToString("D3"),
Counter.ToString("D6"),
sb.ToString(),
Volume(),
TimestampDbl(),
Label());
}
}
/// <summary>
/// Filter RefFlow data in an array of OptoTelegramRaw objects by a FIR filter:
///
/// kSize = 5, kSize2 = 2
///
/// i k
/// ---------------------------------------------------------------------------
/// 0 -5 filtered[0] = data[0]
/// 1 -4 filtered[1] = data[1]
/// 2 -3 filtered[2] = data[0]*k[0] + ... + data[4]*k[4]
/// 3 -2 filtered[3] = data[1]*k[0] + ... + data[5]*k[4]
/// 4 -1 filtered[4] = data[2]*k[0] + ... + data[6]*k[4]
/// 5 0 data[0] = filtered[0], filtered[0] = data[3]*k[0] + ... + data[7]*k[4]
/// 6 1 data[1] = filtered[1], filtered[1] = data[4]*k[0] + ... + data[8]*k[4]
/// 7 ...
/// </summary>
/// <param name="optoData">array of OptoTelegramRaw objects</param>
/// <param name="optoDataCount">number of objects to process</param>
public static void FIRFilterFlow(DatastreamFrame[] optoData, int optoDataCount)
{
float[] kernel = new float[] { 0.1f, 0.2f, 0.4f, 0.2f, 0.1f };
int kSize = kernel.Length;
int kSize2 = kernel.Length / 2;
float[] filtered = new float[kSize];
for (int i = 0; i < optoDataCount; i++)
{
int k = i - kSize;
if (k >= 0) optoData[k].RefFlow = filtered[i % kSize];
if (i < kSize2 || i >= optoDataCount - kSize2)
{
filtered[i % kSize] = optoData[i].RefFlow;
}
else
{
float weoightedSum = 0;
for (int j = -kSize2; j <= kSize2; j++)
weoightedSum += optoData[i + j].RefFlow * kernel[j + kSize2];
filtered[i % kSize] = weoightedSum;
}
}
for (int k = optoDataCount - kSize; k < optoDataCount; k++)
{
if (k >= 0) optoData[k].RefFlow = filtered[k % kSize];
}
}
}
}
@@ -0,0 +1,23 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
namespace TBF.Rig.RegisterReaders.S640Stream
{
public enum FrameFlags : byte
{
OK = 0,
OK_TestStart,
OK_FullRound,
OK_TestEnd,
InvalidFrame, /// Wrong frame format or checksum error
SyncError,
}
public enum DatastreamState
{
Read,
Flush,
}
}
@@ -0,0 +1,25 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System.Collections.Generic;
using TBF.Rig.Generic;
namespace TBF.Rig.RegisterReaders.S640Stream
{
public class Factory : IComponentFactory
{
public string ClassName { get { return GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public IComponent DummyComponent() { return new S640Stream(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new S640Stream(cfg); }
public IComponentCfg DefaultConfig() { return new S640StreamCfg("S640Stream", this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(S640StreamCfg.Serializer, component, this);
}
}
}
@@ -0,0 +1,20 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TBF.Rig.RegisterReaders.S640Stream
{
public class FrameReceivedEventArgs : EventArgs
{
public string Data;
public FrameReceivedEventArgs(string data)
{
this.Data = data;
}
}
}
@@ -0,0 +1,685 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
using log4net;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.RegisterReaders.S640Stream
{
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class S640Stream : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(S640Stream));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
readonly S640StreamCfg myCfg;
public int Position { get { return myCfg.Position; } }
public Config.Entities.RegisterReaderType RegisterReaderType { get { return Config.Entities.RegisterReaderType.DataStream; } }
public double PulsesPerLtr { get { return 1000.0; } }
public double LtrsPerPulse { get { return 1 / PulsesPerLtr; } }
public Config.Unit VolumeUnits { get { return Config.Unit.ml; } }
public double VolumeScaleFactor { get { return 1; } }
public Config.Unit TimeUnits { get { return Config.Unit.ms; } }
public double TimeScaleFactor { get { return 1; } }
public bool CommFailed
{
get { return commFailed; }
set { commFailed = value; }
}
bool commFailed;
///
/// Required for IRegisterReader interface
///
public int WMPulses { get { return wmPulses; } }
public int WMRefPulses { get { return wmRefPulses; } }
public double WMVolume { get { return wmVolume; } }
public double BeginWMState { get { return beginWMState; } }
public double EndWMState { get { return endWMState; } }
public double WMTestTime { get { return wmTestTime; } }
double beginWMState;
double endWMState;
double wmVolume;
int wmPulses;
int wmRefPulses;
double wmTestTime;
/// <summary> Name set by the test, to be used as a part of the opto-data log file name </summary>
public string TestName { set { testName = value; } }
public int TestRepeats { set { testRepeats = value; } }
public int RepetitionNr { set { repetitionNr = value; } }
///
string testName;
int testRepeats;
int repetitionNr;
///
/// PCB Number from the data stream
///
public Int64 PcbNumber { get { return (pcbNrFrequency1 >= 10) ? pcbNumber1 : 0; } }
long pcbNumber1;
long pcbNumber2;
long pcbNumber3;
long pcbNrFrequency1;
long pcbNrFrequency2;
long pcbNrFrequency3;
///
/// Radio address from the data stream
///
public Int64 RadioAddress { get { return (rAddrFrequency1 >= 10) ? radioAddress1 : 0; } }
long radioAddress1;
long radioAddress2;
long radioAddress3;
long rAddrFrequency1;
long rAddrFrequency2;
long rAddrFrequency3;
///
/// Extracted from datastream, passed to OptoTelegramRaw.UpdateFromString(...)
///
Int64 currentRawVolumeUnwrapped;
Int64 currentRawTimeUnwrapped;
///
/// Volume of water from the opto telegram
///
private double volumeLtr;
private double volumeLtr0; /// The very first volume from the first valid datastream frame
public double VolumeLtrStart { get { return volumeLtrStart; } } /// Test start volume for metrology
public double VolumeLtrEnd { get { return volumeLtrEnd; } } /// Test end volume for metrology
double volumeLtrStart; /// Test start volume for metrology
double volumeLtrEnd; /// Test end volume for metrology
double volumeLtrEnd1; /// auxiliary buffer1 to keep the end volume before test stops
double volumeLtrEnd2; /// auxiliary buffer2 to keep the end volume before test stops
double volumeLtrEnd3; /// auxiliary buffer3 to keep the end volume before test stops
///
/// Timestamp from the opto telegram
///
private double timestampSec;
private double timestampSec0; /// The very first timestamp from the first valid datastream frame
public bool NoSamples { get { return (timestampSecEnd - timestampSecStart) < float.Epsilon; } }
public double TimestampSecStart { get { return timestampSecStart; } }
public double TimestampSecEnd { get { return timestampSecEnd; } }
double timestampSecStart;
double timestampSecEnd;
double timestampSecEnd1;
double timestampSecEnd2;
double timestampSecEnd3;
private int frameIx;
public int TestStartFrameIx;
public int TestEndFrameIx;
DatastreamFrame[] datastreamFrames;
const int MaxDatastreamFramesCount = 80000; /// almost 3h at 8 Hz
int datastreamFramesCount;
string datastreamLogFileName;
DatastreamFrame toBeFlushed;
int flushedFramesCount;
public int FlushedFramesCount
{
get { return flushedFramesCount; }
set { flushedFramesCount = lastFlushedFramesCount = lastFlushedFramesCount_1 = value; }
}
int lastFlushedFramesCount_1;
int lastFlushedFramesCount;
public int FlushedFramesDelta
{
get
{
int retval = Math.Max(flushedFramesCount - lastFlushedFramesCount, lastFlushedFramesCount - lastFlushedFramesCount_1);
lastFlushedFramesCount_1 = lastFlushedFramesCount;
lastFlushedFramesCount = flushedFramesCount;
return retval;
}
}
///
/// Opto serial port and worker thread related private variables
///
private SerialPort serialPort; /// Used in DebugMode.Normal
private TextReader textReader; /// Used instead of serialPort in DebugMode.Simulate
public S640Stream() { }
public S640Stream(IComponentCfg cfg)
: base(cfg)
{
myCfg = cfg as S640StreamCfg;
}
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearSessionData()
{
currentRawVolumeUnwrapped = 0;
currentRawTimeUnwrapped = 0;
pcbNumber1 = 0;
pcbNumber2 = 0;
pcbNumber3 = 0;
pcbNrFrequency1 = 0;
pcbNrFrequency2 = 0;
pcbNrFrequency3 = 0;
radioAddress1 = 0;
radioAddress2 = 0;
radioAddress3 = 0;
rAddrFrequency1 = 0;
rAddrFrequency2 = 0;
rAddrFrequency3 = 0;
commFailed = false;
flushedFramesCount = 0;
synchronized = false;
synchronized2 = false;
partOfTelegram = string.Empty;
}
public override void Initialize()
{
ClearSessionData();
datastreamParsingEnabled = false;
/// Allocate memory for opto-data from iPerl
datastreamFrames = new DatastreamFrame[MaxDatastreamFramesCount];
for (int i = 0; i < MaxDatastreamFramesCount; i++) datastreamFrames[i] = new DatastreamFrame();
toBeFlushed = new DatastreamFrame();
if (DebugLevel == DebugMode.Normal)
{
/// Prepare serial port
serialPort = new SerialPort(string.Format("COM{0}", myCfg.ComPortNr),
myCfg.BaudRate,
myCfg.Parity,
myCfg.DataBits,
myCfg.StopBits);
serialPort.Handshake = myCfg.Handshake;
serialPort.Open();
log.FatalFormat("{0} initialized: {1}", Name, this);
}
else if (DebugLevel == DebugMode.Simulate)
{
try
{
textReader = new StreamReader("C:\\TBF\\Simulate\\serialstream.txt");
}
catch (Exception)
{
MessageBox.Show("Missing file C:\\TBF\\Simulate\\seriastream.txt");
}
log.FatalFormat("{0} simulated: {1}", Name, this);
}
}
public void RunDeviceBefore()
{
if (DebugLevel == DebugMode.Normal || DebugLevel == DebugMode.Simulate)
{
try
{
ReadDatastream(datastreamParsingEnabled ? DatastreamState.Read : DatastreamState.Flush);
}
catch (Exception e)
{
DebugLevel = DebugMode.FailureDuringOperation;
log.FatalFormat("Opto-data serial port failure : {0}", e.Message);
if (e.InnerException != null)
{
log.FatalFormat("InnerMessage : {0}", e.InnerException.Message);
}
}
}
else if (DebugLevel == DebugMode.FailureDuringOperation)
{
}
}
public void RunDeviceAfter() { }
public void StopDevice()
{
try
{
if (DebugLevel == DebugMode.Normal && serialPort != null)
{
serialPort.Close();
serialPort = null;
}
}
catch
{
}
}
public void StopDevice2() { }
/// <summary>
/// Events: Event.ReadRegisterDone, Event.Error
/// </summary>
/// <returns>ReadWaterMeter instance reference casted to IOperaton</returns>
public IOperation ReadDatastreamOp()
{
return this;
}
/// <summary>
/// Clear data/counters related to a specific tests
/// </summary>
public void Clear()
{
secondsSinceOpStart = 0;
volumeLtr = 0;
volumeLtr0 = 0;
timestampSec = 0;
timestampSec0 = 0;
/// Reset opto data
datastreamFramesCount = 0;
TestStartFrameIx = 0;
TestEndFrameIx = 0;
}
int secondsSinceOpStart; /// This is to determine when the test start sample should be taken
/// <summary>Start this operation</summary>
public void Start()
{
Clear();
ReadPulses();
/// File name
datastreamLogFileName = string.Format("{0}_{1}_{2}_{3}.txt",
StateMachine.CycleStartTimeStamp.ToString("HHmmss"),
Position.ToString("D2"),
testName,
repetitionNr);
StartParsingDatastream();
}
/// <summary>Run this operation</summary>
/// <returns>eventDone</returns>
public Event Run()
{
ReadPulses();
if (++secondsSinceOpStart == 4) /// 4 seconds after operation start
{
/// Take the test start sample
volumeLtrStart = volumeLtr;
timestampSecStart = timestampSec;
TestStartFrameIx = frameIx;
}
/// Shift data in pipelines
volumeLtrEnd = volumeLtrEnd3;
volumeLtrEnd3 = volumeLtrEnd2;
volumeLtrEnd2 = volumeLtrEnd1;
volumeLtrEnd1 = volumeLtr;
timestampSecEnd = timestampSecEnd3;
timestampSecEnd3 = timestampSecEnd2;
timestampSecEnd2 = timestampSecEnd1;
timestampSecEnd1 = timestampSec;
TestEndFrameIx = frameIx - 3;
return Event.ReadRegisterDone;
}
/// <summary>Stop this operation</summary>
public void Stop()
{
if (TestStartFrameIx > 0 && TestStartFrameIx < datastreamFrames.Length && datastreamFrames[TestStartFrameIx].Flags == FrameFlags.OK)
{
datastreamFrames[TestStartFrameIx].Flags = FrameFlags.OK_TestStart;
}
if (TestEndFrameIx > 0 && TestEndFrameIx < datastreamFrames.Length && datastreamFrames[TestEndFrameIx].Flags == FrameFlags.OK)
{
datastreamFrames[TestEndFrameIx].Flags = FrameFlags.OK_TestEnd;
}
StopParsingDatastream();
DatastreamFrame.FIRFilterFlow(datastreamFrames, datastreamFramesCount);
SaveDatastreamLog();
}
void SaveDatastreamLog()
{
string directory = string.Format("C:\\TBF\\ProcessData\\{0}\\{1}\\{2}\\",
StateMachine.CycleStartTimeStamp.ToString("yy"),
StateMachine.CycleStartTimeStamp.ToString("MM"),
StateMachine.CycleStartTimeStamp.ToString("dd"));
string datastreamLogPathName = directory + datastreamLogFileName;
try
{
Directory.CreateDirectory(directory);
using (TextWriter datastreamLogFile = new StreamWriter(datastreamLogPathName))
{
for (int i = 0; i < datastreamFramesCount; i++)
{
datastreamLogFile.WriteLine(datastreamFrames[i].ToString());
}
datastreamLogFile.Close();
}
}
catch (Exception exc)
{
File.Delete(datastreamLogPathName);
log.ErrorFormat(string.Format("Error writing into file {0}", datastreamLogPathName));
log.ErrorFormat(string.Format("Exception message: {0}", exc.Message));
}
}
void ReadPulses()
{
beginWMState = volumeLtr0;
endWMState = volumeLtr;
wmVolume = Math.Abs(endWMState - beginWMState);
wmPulses = (int)(wmVolume * (double)PulsesPerLtr + 0.5);
wmRefPulses = StateMachine.ControlBoard.RefPulses;
wmTestTime = timestampSec - timestampSec0;
}
bool datastreamParsingEnabled;
/// <summary> Flush internal buffers and start parsing the opto serial port data </summary>
void StartParsingDatastream()
{
datastreamParsingEnabled = true;
}
/// <summary> Stop parsig the opto serial port data </summary>
void StopParsingDatastream()
{
datastreamParsingEnabled = false;
}
///
/// Variables storing the context of serial port data parsing (ReadOptoSerialPort(...))
///
bool synchronized;
bool synchronized2;
string partOfTelegram;
/// <summary>
/// 9600 Bd, 8 data bits, 1 stop bit, no parity
///
/// Telegram description:
///
/// AAAAAAAAAAAA[tab]BBBBBBBBBB[tab]CCCCCCCCC[tab]DDDDDDDDDD[tab]EE[cr][lf] (49 bytes)
///
/// Data Comment Type Calculate to decimal
/// ----------------------------------------------------------------
/// AAAAAAAAAAAA PCB number Decimal
/// BBBBBBBBBB Radio address Decimal
/// CCCCCCCCC Meter reading Decimal Volume in ml
/// DDDDDDDDDD Timestamp Decimal Time in ms
/// EE Checksum Hexadecimal
/// ----------------------------------------------------------------
///
/// Example:
/// 540210730770 4291524429 000250215 0433411876 56
/// 540210730770 4291524429 000250223 0433412126 4A
/// ...
/// </summary>
/// <param name="streamState">OptoState.Read or OptoState.Flush</param>
void ReadDatastream(DatastreamState streamState)
{
string received = null;
if (DebugLevel == DebugMode.Normal)
{
int nrBytes = serialPort.BytesToRead;
char[] buffer = new char[nrBytes];
serialPort.Read(buffer, 0, nrBytes);
received = new string(buffer);
}
else if (DebugLevel == DebugMode.Simulate)
{
string line = textReader.ReadLine();
received = line + '\r' + '\n';
}
if (received != null)
{
string allRcvd = partOfTelegram + received;
while (true)
{
int pos = allRcvd.IndexOf("\r\n");
if (pos < 0)
{
/// No CR+LF found, wait for more characters in the buffer (next invocation)
partOfTelegram = allRcvd;
return;
}
else
{
/// CR+LF found ==> Check datastream state: Read or Flush
if (streamState == DatastreamState.Read)
{
if (pos < DatastreamFrame.FrameLength - 2)
{
/// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop
allRcvd = allRcvd.Substring(pos + 2);
if (synchronized)
{
datastreamFrames[datastreamFramesCount].Counter = datastreamFramesCount;
datastreamFrames[datastreamFramesCount++].SetFlags(FrameFlags.SyncError);
}
synchronized = true;
}
// CR+LF found and (pos >= OptoTelegramRaw.Length - 2)
else if (datastreamFrames[datastreamFramesCount].UpdateFromString(allRcvd.Substring(pos - DatastreamFrame.FrameLength + 2, DatastreamFrame.FrameLength),
ref currentRawVolumeUnwrapped, ref currentRawTimeUnwrapped,
datastreamFramesCount))
{
OptoTelegramRreceived(datastreamFramesCount++, currentRawVolumeUnwrapped, currentRawTimeUnwrapped, synchronized2);
synchronized2 = synchronized;
allRcvd = allRcvd.Substring(pos + 2);
}
else
{
datastreamFrames[datastreamFramesCount].Counter = datastreamFramesCount;
datastreamFramesCount++;
allRcvd = allRcvd.Substring(pos + 2);
}
}
else /// optoState == SerialStreamState.Flush
{
Int64 pcbNumber;
Int64 radioAddress;
if (pos < DatastreamFrame.FrameLength - 2)
{
/// CR+LF found too early, truncate the beginning incl CR+LF and keep scanning in this loop
allRcvd = allRcvd.Substring(pos + 2);
synchronized = true;
}
// CR+LF found and (pos >= OptoTelegram.Length - 2)
else if (toBeFlushed.UpdateFromStringDummy(allRcvd.Substring(pos - DatastreamFrame.FrameLength + 2, DatastreamFrame.FrameLength),
ref currentRawVolumeUnwrapped, ref currentRawTimeUnwrapped,
out pcbNumber,
out radioAddress))
{
flushedFramesCount++;
synchronized2 = synchronized;
allRcvd = allRcvd.Substring(pos + 2);
///
/// Process received PCB number
///
if (pcbNrFrequency1 == 0 || pcbNumber == pcbNumber1)
{
pcbNumber1 = pcbNumber;
pcbNrFrequency1++;
}
else if (pcbNrFrequency2 == 0 || pcbNumber == pcbNumber2)
{
pcbNumber2 = pcbNumber;
pcbNrFrequency2++;
if (pcbNrFrequency2 > pcbNrFrequency1)
{
long tmp = pcbNumber1;
pcbNumber1 = pcbNumber2;
pcbNumber2 = tmp;
tmp = pcbNrFrequency1;
pcbNrFrequency1 = pcbNrFrequency2;
pcbNrFrequency2 = tmp;
}
}
else if (pcbNrFrequency3 == 0 || pcbNumber == pcbNumber3)
{
pcbNumber3 = pcbNumber;
pcbNrFrequency3++;
if (pcbNrFrequency3 > pcbNrFrequency2)
{
long tmp = pcbNumber2;
pcbNumber2 = pcbNumber3;
pcbNumber3 = tmp;
tmp = pcbNrFrequency2;
pcbNrFrequency2 = pcbNrFrequency3;
pcbNrFrequency3 = tmp;
}
if (pcbNrFrequency2 > pcbNrFrequency1)
{
long tmp = pcbNumber1;
pcbNumber1 = pcbNumber2;
pcbNumber2 = tmp;
tmp = pcbNrFrequency1;
pcbNrFrequency1 = pcbNrFrequency2;
pcbNrFrequency2 = tmp;
}
}
///
/// Process received radio address
///
if (rAddrFrequency1 == 0 || radioAddress == radioAddress1)
{
radioAddress1 = radioAddress;
rAddrFrequency1++;
}
else if (rAddrFrequency2 == 0 || radioAddress == radioAddress2)
{
radioAddress2 = radioAddress;
rAddrFrequency2++;
if (rAddrFrequency2 > rAddrFrequency1)
{
long tmp = radioAddress1;
radioAddress1 = radioAddress2;
radioAddress2 = tmp;
tmp = rAddrFrequency1;
rAddrFrequency1 = rAddrFrequency2;
rAddrFrequency2 = tmp;
}
}
else if (rAddrFrequency3 == 0 || radioAddress == radioAddress3)
{
radioAddress3 = radioAddress;
rAddrFrequency3++;
if (rAddrFrequency3 > rAddrFrequency2)
{
long tmp = radioAddress2;
radioAddress2 = radioAddress3;
radioAddress3 = tmp;
tmp = rAddrFrequency2;
rAddrFrequency2 = rAddrFrequency3;
rAddrFrequency3 = tmp;
}
if (rAddrFrequency2 > rAddrFrequency1)
{
long tmp = rAddrFrequency1;
rAddrFrequency1 = rAddrFrequency2;
rAddrFrequency2 = tmp;
tmp = radioAddress1;
radioAddress1 = radioAddress2;
radioAddress2 = tmp;
}
}
}
else
{
allRcvd = allRcvd.Substring(pos + 2);
}
}
}
}
}
}
void OptoTelegramRreceived(int currentIx, long currentRawVolumeUnwrapped, long currentRawTimeUnwrapped, bool async)
{
DatastreamFrame optoTelegram = datastreamFrames[currentIx];
frameIx = currentIx;
if (volumeLtr == 0 && volumeLtr0 == 0)
{
volumeLtr0 = volumeLtr = (double)currentRawVolumeUnwrapped / DatastreamFrame.VolumeScaleFactor;
}
else
{
volumeLtr = (double)currentRawVolumeUnwrapped / DatastreamFrame.VolumeScaleFactor;
}
if (timestampSec == 0 && timestampSec0 == 0)
{
timestampSec0 = timestampSec = (double)currentRawTimeUnwrapped / DatastreamFrame.TimeScaleFactor;
}
else
{
timestampSec = (double)currentRawTimeUnwrapped / DatastreamFrame.TimeScaleFactor;
}
}
}
}
@@ -0,0 +1,180 @@
///
/// Copyright (c) 2021 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Xml.Serialization;
using Config.Entities;
using TBF.Rig.Generic;
namespace TBF.Rig.RegisterReaders.S640Stream
{
public class S640StreamCfg : ComponentCfgBase, IComponentCfg, Config.Entities.IParamsProvider
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(S640StreamCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
///
/// Serialized parameters
///
public int Position; /// 1 .. nrWaterMeters
public int ComPortNr;
public int BaudRate;
public Parity Parity;
public int DataBits;
public StopBits StopBits;
public Handshake Handshake;
/// Private parameterless constructor invoked by all other (public) constructors
S640StreamCfg() { }
public S640StreamCfg(string name, IComponentFactory factory)
: this()
{
Name = name;
Factory = factory;
ParentName = string.Empty;
InitializeAll();
}
public string ComponentName { get { return Name; } }
public void InitializeAll()
{
Position = 1;
ComPortNr = 3;
BaudRate = 9600;
Parity = System.IO.Ports.Parity.None;
DataBits = 8;
StopBits = System.IO.Ports.StopBits.One;
Handshake = System.IO.Ports.Handshake.None;
}
string[] paramNames = new string[]
{
"Position", /// 0
"Serial port number", /// 1
"Baud rate", /// 2
"Parity", /// 3
"Data bits", /// 4
"Stop bits", /// 5
"Handshake", /// 6
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
public ICollection<string> ParamValues(int i)
{
switch (i)
{
case 0:
return new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20" };
case 2:
return new string[] { "150", "300", "600", "1200", "2400", "4800", "9600",
"19200", "38400", "57600", "76800", "115200"};
case 3:
return new string[] { Parity.None.ToString(), Parity.Odd.ToString(), Parity.Even.ToString() };
case 4:
return new string[] { "7", "8" };
case 5:
return new string[] { StopBits.None.ToString(),
StopBits.One.ToString(),
StopBits.OnePointFive.ToString(),
StopBits.Two.ToString() };
case 6:
return new string[] { Handshake.None.ToString(),
Handshake.XOnXOff.ToString(),
Handshake.RequestToSend.ToString(),
Handshake.RequestToSendXOnXOff.ToString() };
default:
return null;
}
}
public string ToString(int i)
{
switch (i)
{
case 0: return Position.ToString();
case 1: return ComPortNr.ToString();
case 2: return BaudRate.ToString();
case 3: return Parity.ToString();
case 4: return DataBits.ToString();
case 5: return StopBits.ToString();
case 6: return Handshake.ToString();
default:
return string.Format("{0}: Position={1} Com{2}, {3}Bd, {4}-bits, parity={5}, stopBits={6}, {7}",
Name, Position, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
}
public CfgUpdateFlags UpdateParam(int i, string str)
{
switch (i)
{
case 0: Position = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 1: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 2: BaudRate = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 3: Parity = TBF.Utils.GetParity(str); return CfgUpdateFlags.RestartRqrd;
case 4: DataBits = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 5: StopBits = TBF.Utils.GetStopBits(str); return CfgUpdateFlags.RestartRqrd;
case 6: Handshake = TBF.Utils.GetHandshake(str); return CfgUpdateFlags.RestartRqrd;
default: return CfgUpdateFlags.None;
}
}
public bool ValidateParam(int i, string strValue, out string message)
{
message = string.Empty;
int idummy;
switch (i)
{
case 1:
if (int.TryParse(strValue, out idummy) && idummy > 0) return true;
break;
case 0:
case 2:
case 3:
case 4:
case 5:
case 6:
if (ParamValues(i).Contains(strValue)) return true;
break;
default:
message = "Invalid index";
return false;
}
message = ParamName(i) + " is invalid";
return false;
}
void CopyContentTo(S640StreamCfg prms)
{
prms.Position = this.Position;
prms.ComPortNr = this.ComPortNr;
prms.BaudRate = this.BaudRate;
prms.Parity = this.Parity;
prms.DataBits = this.DataBits;
prms.StopBits = this.StopBits;
prms.Handshake = this.Handshake;
}
public Config.Entities.IParamsProvider Clone()
{
S640StreamCfg pars = new S640StreamCfg();
CopyContentTo(pars);
return pars;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
}
}
}
@@ -8,14 +8,14 @@ namespace TBF.Rig.RegisterReaders.SerialStream
{
public class Factory : IComponentFactory
{
public string ClassName { get { return this.GetType().Namespace.Substring(8); } }
public string ClassName { get { return GetType().Namespace.Substring(8); } }
public override string ToString() { return ClassName; }
public IComponent DummyComponent() { return new SerialStream(); }
public IComponent GetComponent(IComponentCfg cfg, IList<IComponent> components) { return new SerialStream(cfg); }
public IComponentCfg DefaultConfig() { return new SerialStreamCfg(this.GetType().Namespace.Substring(8), this); }
public IComponentCfg DefaultConfig() { return new SerialStreamCfg("SerialStream", this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
{
@@ -8,13 +8,14 @@ using System.Windows.Forms;
using log4net;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
namespace TBF.Rig.RegisterReaders.SerialStream
{
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class SerialStream : ComponentBase, IDevice, GenericDevices.IRegReaderDatastream, GenericDevices.IHasTestName, IOperation
public class SerialStream : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(SerialStream));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
@@ -187,7 +188,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearData()
public void ClearSessionData()
{
commFailed = false;
datastreamFramesCount = 0;
@@ -195,7 +196,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
public override void Initialize()
{
ClearData();
ClearSessionData();
datastreamParsingEnabled = false;
currentFrameFormat = new FrameFormat(FrameLength, FrameFrequency,
@@ -291,7 +292,7 @@ namespace TBF.Rig.RegisterReaders.SerialStream
/// Events: Event.ReadRegisterDone, Event.Error
/// </summary>
/// <returns>ReadWaterMeter instance reference casted to IOperaton</returns>
public IOperation ReadRegisterOp()
public IOperation ReadDatastreamOp()
{
return this;
}
@@ -10,44 +10,51 @@ using TBF.Rig.Generic;
namespace TBF.Rig.RegisterReaders.SerialStream
{
public class SerialStreamCfg : ComponentCfgBase, Generic.IComponentCfg
public class SerialStreamCfg : ComponentCfgBase, IComponentCfg, Config.Entities.IParamsProvider
{
public static XmlSerializer Serializer = XmlSerializer.FromTypes(new[] { typeof(SerialStreamCfg) })[0];
public override XmlSerializer GetSerializer() { return Serializer; }
public override XmlSerializer GetSerializer() { return Serializer; }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new SerialStreamCfgCtrl(); }
public IComponentCfgCtrl GetControl(IList<Config.Entities.Component> cmpntEntities) { return new Configs.ParamsProvider.ComponentCfgCtrl(this, null); }
///
/// Serialized parameters
///
public int ComPortNr;
public int ComPortNr;
public int BaudRate;
public Parity Parity;
public int DataBits;
public StopBits StopBits;
public Handshake Handshake;
///
///
/// Procedure parameters
///
[XmlIgnore]
public ProcParams ProcParams;
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
[XmlIgnore]
public ProcParams ProcParams;
public override IParamsProvider GetRuntimeProcParamsProvider() { return ProcParams; }
public override IParamsProvider CreateProcParamsProvider() { return new ProcParams(true); }
/// Private parameterless constructor invoked by all other (public) constructors
SerialStreamCfg()
/// Private parameterless constructor invoked by all other (public) constructors
SerialStreamCfg()
{
ProcParams = CreateProcParamsProvider() as ProcParams;
}
public SerialStreamCfg(string name, IComponentFactory factory)
: this()
{
{
Name = name;
Factory = factory;
ParentName = string.Empty;
ComPortNr = 21;
InitializeAll();
}
public string ComponentName { get { return Name; } }
public void InitializeAll()
{
ComPortNr = 3;
BaudRate = 9600;
Parity = System.IO.Ports.Parity.None;
DataBits = 8;
@@ -55,10 +62,120 @@ namespace TBF.Rig.RegisterReaders.SerialStream
Handshake = System.IO.Ports.Handshake.None;
}
public string ToString(int i)
{
return string.Format("{0} Com{1}, {2}Bd, {3}-bits, parity={4}, stopBits={5}, {6}",
Name, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
string[] paramNames = new string[]
{
"Serial port number", /// 0
"Baud rate", /// 1
"Parity", /// 2
"Data bits", /// 3
"Stop bits", /// 4
"Handshake", /// 5
};
public string ParamName(int i) { return paramNames[i]; }
public int ParamsCount() { return paramNames.Length; }
public ICollection<string> ParamValues(int i)
{
switch (i)
{
case 1:
return new string[] { "150", "300", "600", "1200", "2400", "4800", "9600",
"19200", "38400", "57600", "76800", "115200"};
case 2:
return new string[] { Parity.None.ToString(), Parity.Odd.ToString(), Parity.Even.ToString() };
case 3:
return new string[] { "7", "8" };
case 4:
return new string[] { StopBits.None.ToString(),
StopBits.One.ToString(),
StopBits.OnePointFive.ToString(),
StopBits.Two.ToString() };
case 5:
return new string[] { Handshake.None.ToString(),
Handshake.XOnXOff.ToString(),
Handshake.RequestToSend.ToString(),
Handshake.RequestToSendXOnXOff.ToString() };
default:
return null;
}
}
}
public string ToString(int i)
{
switch (i)
{
case 0: return ComPortNr.ToString();
case 1: return BaudRate.ToString();
case 2: return Parity.ToString();
case 3: return DataBits.ToString();
case 4: return StopBits.ToString();
case 5: return Handshake.ToString();
default:
return string.Format("{0}: Com{1}, {2}Bd, {3}-bits, parity={4}, stopBits={5}, {6}",
Name, ComPortNr, BaudRate, DataBits, Parity, StopBits, Handshake);
}
}
public CfgUpdateFlags UpdateParam(int i, string str)
{
switch (i)
{
case 0: ComPortNr = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 1: BaudRate = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 2: Parity = TBF.Utils.GetParity(str); return CfgUpdateFlags.RestartRqrd;
case 3: DataBits = int.Parse(str); return CfgUpdateFlags.RestartRqrd;
case 4: StopBits = TBF.Utils.GetStopBits(str); return CfgUpdateFlags.RestartRqrd;
case 5: Handshake = TBF.Utils.GetHandshake(str); return CfgUpdateFlags.RestartRqrd;
default: return CfgUpdateFlags.None;
}
}
public bool ValidateParam(int i, string strValue, out string message)
{
message = string.Empty;
int idummy;
switch (i)
{
case 0:
if (int.TryParse(strValue, out idummy) && idummy > 0) return true;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
if (ParamValues(i).Contains(strValue)) return true;
break;
default:
message = "Invalid index";
return false;
}
message = ParamName(i) + " is invalid";
return false;
}
void CopyContentTo(SerialStreamCfg prms)
{
prms.ComPortNr = this.ComPortNr;
prms.BaudRate = this.BaudRate;
prms.Parity = this.Parity;
prms.DataBits = this.DataBits;
prms.StopBits = this.StopBits;
prms.Handshake = this.Handshake;
}
public Config.Entities.IParamsProvider Clone()
{
SerialStreamCfg pars = new SerialStreamCfg();
CopyContentTo(pars);
return pars;
}
public bool UpdateEmbeddedDbEntity()
{
return true; /// =OK, do nothing
}
}
}
@@ -1,171 +0,0 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
using System;
using System.Windows.Forms;
using System.IO.Ports;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Resources;
namespace TBF.Rig.RegisterReaders.SerialStream
{
public partial class SerialStreamCfgCtrl : UserControl, IComponentCfgCtrl
{
public bool ShowMore { get { return false; } }
SerialStreamCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as SerialStreamCfg;
Redraw();
}
}
public SerialStreamCfgCtrl()
{
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 ModbusCfgCtrl_Load(object sender, EventArgs e)
{
nameLabel.Text = Strings.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;
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;
comPortNrTextBox.Enabled = true;
baudRateTextBox.Enabled = true;
parityComboBox.Enabled = true;
dataBitsTextBox.Enabled = true;
stopBitsComboBox.Enabled = true;
handshakeComboBox.Enabled = true;
}
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.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;
}
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";
}
return flags;
}
}
}
@@ -1,229 +0,0 @@
///
/// Copyright (c) 2018 Sensus Slovensko a.s.
///
namespace TBF.Rig.RegisterReaders.SerialStream
{
partial class SerialStreamCfgCtrl
{
/// <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.comPortNrTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.baudRateLabel = new System.Windows.Forms.Label();
this.baudRateTextBox = new System.Windows.Forms.TextBox();
this.partityLabel = new System.Windows.Forms.Label();
this.dataBitsLabel = new System.Windows.Forms.Label();
this.dataBitsTextBox = new System.Windows.Forms.TextBox();
this.stopBitsLabel = new System.Windows.Forms.Label();
this.handshakeLabel = new System.Windows.Forms.Label();
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.parityComboBox = new System.Windows.Forms.ComboBox();
this.stopBitsComboBox = new System.Windows.Forms.ComboBox();
this.handshakeComboBox = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comPortNrTextBox
//
this.comPortNrTextBox.Enabled = false;
this.comPortNrTextBox.Location = new System.Drawing.Point(140, 52);
this.comPortNrTextBox.Name = "comPortNrTextBox";
this.comPortNrTextBox.Size = new System.Drawing.Size(34, 20);
this.comPortNrTextBox.TabIndex = 4;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(29, 55);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(98, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Serial Port Number:";
//
// baudRateLabel
//
this.baudRateLabel.AutoSize = true;
this.baudRateLabel.Location = new System.Drawing.Point(29, 79);
this.baudRateLabel.Name = "baudRateLabel";
this.baudRateLabel.Size = new System.Drawing.Size(58, 13);
this.baudRateLabel.TabIndex = 5;
this.baudRateLabel.Text = "Baud Rate";
//
// baudRateTextBox
//
this.baudRateTextBox.Enabled = false;
this.baudRateTextBox.Location = new System.Drawing.Point(140, 76);
this.baudRateTextBox.Name = "baudRateTextBox";
this.baudRateTextBox.Size = new System.Drawing.Size(130, 20);
this.baudRateTextBox.TabIndex = 6;
//
// partityLabel
//
this.partityLabel.AutoSize = true;
this.partityLabel.Location = new System.Drawing.Point(29, 103);
this.partityLabel.Name = "partityLabel";
this.partityLabel.Size = new System.Drawing.Size(33, 13);
this.partityLabel.TabIndex = 7;
this.partityLabel.Text = "Parity";
//
// dataBitsLabel
//
this.dataBitsLabel.AutoSize = true;
this.dataBitsLabel.Location = new System.Drawing.Point(29, 127);
this.dataBitsLabel.Name = "dataBitsLabel";
this.dataBitsLabel.Size = new System.Drawing.Size(50, 13);
this.dataBitsLabel.TabIndex = 9;
this.dataBitsLabel.Text = "Data Bits";
//
// dataBitsTextBox
//
this.dataBitsTextBox.Enabled = false;
this.dataBitsTextBox.Location = new System.Drawing.Point(140, 124);
this.dataBitsTextBox.Name = "dataBitsTextBox";
this.dataBitsTextBox.Size = new System.Drawing.Size(34, 20);
this.dataBitsTextBox.TabIndex = 10;
//
// stopBitsLabel
//
this.stopBitsLabel.AutoSize = true;
this.stopBitsLabel.Location = new System.Drawing.Point(29, 151);
this.stopBitsLabel.Name = "stopBitsLabel";
this.stopBitsLabel.Size = new System.Drawing.Size(49, 13);
this.stopBitsLabel.TabIndex = 11;
this.stopBitsLabel.Text = "Stop Bits";
//
// handshakeLabel
//
this.handshakeLabel.AutoSize = true;
this.handshakeLabel.Location = new System.Drawing.Point(29, 175);
this.handshakeLabel.Name = "handshakeLabel";
this.handshakeLabel.Size = new System.Drawing.Size(62, 13);
this.handshakeLabel.TabIndex = 13;
this.handshakeLabel.Text = "Handshake";
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(140, 28);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(30, 31);
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(137, 7);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
this.classNameLabel.Text = "ComonentName";
//
// parityComboBox
//
this.parityComboBox.Enabled = false;
this.parityComboBox.FormattingEnabled = true;
this.parityComboBox.Location = new System.Drawing.Point(140, 100);
this.parityComboBox.Name = "parityComboBox";
this.parityComboBox.Size = new System.Drawing.Size(130, 21);
this.parityComboBox.TabIndex = 8;
//
// stopBitsComboBox
//
this.stopBitsComboBox.Enabled = false;
this.stopBitsComboBox.FormattingEnabled = true;
this.stopBitsComboBox.Location = new System.Drawing.Point(140, 148);
this.stopBitsComboBox.Name = "stopBitsComboBox";
this.stopBitsComboBox.Size = new System.Drawing.Size(130, 21);
this.stopBitsComboBox.TabIndex = 12;
//
// handshakeComboBox
//
this.handshakeComboBox.Enabled = false;
this.handshakeComboBox.FormattingEnabled = true;
this.handshakeComboBox.Location = new System.Drawing.Point(140, 172);
this.handshakeComboBox.Name = "handshakeComboBox";
this.handshakeComboBox.Size = new System.Drawing.Size(130, 21);
this.handshakeComboBox.TabIndex = 14;
//
// AmbientCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
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 = "AmbientCfgCtrl";
this.Size = new System.Drawing.Size(300, 240);
this.Load += new System.EventHandler(this.ModbusCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox comPortNrTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label baudRateLabel;
private System.Windows.Forms.TextBox baudRateTextBox;
private System.Windows.Forms.Label partityLabel;
private System.Windows.Forms.Label dataBitsLabel;
private System.Windows.Forms.TextBox dataBitsTextBox;
private System.Windows.Forms.Label stopBitsLabel;
private System.Windows.Forms.Label handshakeLabel;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.ComboBox parityComboBox;
private System.Windows.Forms.ComboBox stopBitsComboBox;
private System.Windows.Forms.ComboBox handshakeComboBox;
}
}
@@ -1,120 +0,0 @@
<?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>
+1 -4
View File
@@ -268,10 +268,7 @@ namespace TBF.Rig.Sequences
///
foreach (var cmpnt in StateMachine.Components)
{
if (cmpnt is TestMethods.iPerlCommunication.iPerlHead.IperlHead)
{
(cmpnt as TestMethods.iPerlCommunication.iPerlHead.IperlHead).ClearData();
}
if (cmpnt is IHasClearSessionData) (cmpnt as IHasClearSessionData).ClearSessionData();
}
IsQ2PreCorrectionCalculated = false;
+1
View File
@@ -114,6 +114,7 @@ namespace TBF.Rig
Factories.Add(new RegisterReaders.PulsesFromUniCB.Factory()); /// 'RegisterReader'
Factories.Add(new RegisterReaders.StandingStartStop.Factory()); /// 'RegisterReader for standing start/stop'
Factories.Add(new TestMethods.iPerlCommunication.iPerlHead.Factory()); /// 'RegisterReader for iPerl'
Factories.Add(new RegisterReaders.S640Stream.Factory()); /// 'RegisterReader for S640'
Factories.Add(new RegisterReaders.SerialStream.Factory()); /// 'RegisterReader for generic serial stream'
Factories.Add(new RegisterReaders.KPackE.RegisterReader.Factory()); /// KPackE register reader
Factories.Add(new RegisterReaders.KPackE.Radio.Factory()); /// Radio for KPackE register readers
@@ -176,18 +176,6 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
TestStartTime = DateTime.Now;
foreach (var rr in sensPath.RegisterReaders)
{
GenericDevices.IHasTestName readerWithTstName = rr as GenericDevices.IHasTestName;
if (readerWithTstName != null)
{
readerWithTstName.TestName = test.Name;
readerWithTstName.TestRepeats = test.Repeats;
readerWithTstName.RepetitionNr = repetitionNr;
}
}
//------------------------------------------------
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
//------------------------------------------------
@@ -427,6 +415,26 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
temperature_set:
///
/// Prepare datastream read operations
///
IList<IOperation> readDatastreamOps = new List<IOperation>();
if (sensPath != null && sensPath.RegisterReaders != null)
{
foreach (var rr in sensPath.RegisterReaders)
{
var rrWithTestName = rr as GenericDevices.IHasTestName;
if (rrWithTestName != null)
{
rrWithTestName.TestName = test.Name;
rrWithTestName.TestRepeats = test.Repeats;
rrWithTestName.RepetitionNr = repetitionNr;
}
var datastreamRR = rr as GenericDevices.IRegReaderDatastream;
if (datastreamRR != null) readDatastreamOps.Add(datastreamRR.ReadDatastreamOp());
}
}
///
/// Prepare cameras, ROI-s and measurementOperations
@@ -459,7 +467,10 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
/// Prepare measurementOperations
IList<IOperation> cameraMeasurementOps = new List<IOperation>();
foreach (var camera in cameras) cameraMeasurementOps.Add(camera.MeasurementOp());
foreach (var camera in cameras)
{
cameraMeasurementOps.Add(camera.MeasurementOp());
}
if (drainTheTank)
@@ -549,6 +560,7 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
State.Create(string.Format("{0}({1}) : FlyingStartStopTestWithDivOp is running", test.Method, test.Name))
.AddOperation(checkUiOp)
.AddOperations(readTempPressOps)
.AddOperations(readDatastreamOps)
.AddOperations(cameraMeasurementOps)
.AddOperation(cBrd.FlyingStartStopTestOp(test, test.Qfrom, test.Qto, totalPulses, true, false, 0, true, DiverterStart, DiverterEnd))
.AddOperation(processDataLoggingOp)
@@ -7,6 +7,7 @@ using System.IO.Ports;
using log4net;
using Config.Entities;
using TBF.Rig.Generic;
using TBF.Rig.GenericDevices;
using TBF.Rig.Output;
namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
@@ -14,7 +15,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <summary>
/// This component = instance of this class is a placeholder for a combined main watermeter
/// </summary>
public class IperlHead : ComponentBase, IDevice, GenericDevices.IRegReaderDatastream, GenericDevices.IHasTestName, IOperation
public class IperlHead : ComponentBase, IDevice, IRegReaderDatastream, IHasTestName, IHasClearSessionData, IOperation
{
private static readonly ILog log = LogManager.GetLogger(typeof(IperlHead));
public override string ToString() { return string.Format("{0}({1})", ClassName, Cfg.ToString(-1)); }
@@ -372,7 +373,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
public override void Initialize()
{
ClearData();
ClearSessionData();
optoSerialPortParsingEnabled = false;
flowDirectionDetection = new FlowDirectionDetection();
@@ -406,7 +407,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// <summary>
/// Clear data related to a specific water meter
/// </summary>
public void ClearData()
public void ClearSessionData()
{
resultCode = 0;
@@ -509,7 +510,7 @@ namespace TBF.Rig.TestMethods.iPerlCommunication.iPerlHead
/// Events: Event.ReadRegisterDone, Event.Error
/// </summary>
/// <returns>ReadWaterMeter instance reference casted to IOperaton</returns>
public IOperation ReadRegisterOp()
public IOperation ReadDatastreamOp()
{
return this;
}