Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33ef914984 | ||
|
|
3eb0b87f0d | ||
|
|
711dfc03ef | ||
|
|
93459ccfab | ||
|
|
009aefb7c9 | ||
|
|
d2e18d615d | ||
|
|
69b475eb77 | ||
|
|
2210bb8240 | ||
|
|
65ab19290f | ||
|
|
94c7279da1 | ||
|
|
2136695b80 | ||
|
|
c0f9b0ffa0 | ||
|
|
c4ef22436f | ||
|
|
0b73871518 | ||
|
|
f7dc6fee5e | ||
|
|
ba848a167d | ||
|
|
dcb0bf9a88 | ||
|
|
f6433134c1 | ||
|
|
7e3df77b5b | ||
|
|
08dff1272b | ||
|
|
d5c8fd1c8f | ||
|
|
a34740e838 | ||
|
|
836ba5a41f | ||
|
|
23c83ab452 | ||
|
|
bc9e583c29 |
@@ -19,6 +19,9 @@ using System.Runtime.InteropServices;
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//Visibility to TBFTests internal classes
|
||||
[assembly: InternalsVisibleTo("TBFTests")]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2c13538e-15ee-48b2-af0f-2c95afb67186")]
|
||||
|
||||
@@ -29,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("3.9.3013.1")]
|
||||
[assembly: AssemblyFileVersion("3.9.3013.1")]
|
||||
[assembly: AssemblyVersion("3.9.3056.1")]
|
||||
[assembly: AssemblyFileVersion("3.9.3056.1")]
|
||||
|
||||
Generated
+9
-1
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -6270,6 +6269,15 @@ namespace TBF.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test in calculation.
|
||||
/// </summary>
|
||||
internal static string Test_in_calculation {
|
||||
get {
|
||||
return ResourceManager.GetString("Test_in_calculation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Test in progress.
|
||||
/// </summary>
|
||||
|
||||
Generated
+5012
File diff suppressed because it is too large
Load Diff
@@ -1764,4 +1764,7 @@
|
||||
<data name="Units" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Test_in_calculation" xml:space="preserve">
|
||||
<value>Probíhá výpočet</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -2482,4 +2482,7 @@
|
||||
<data name="Units" xml:space="preserve">
|
||||
<value>Units</value>
|
||||
</data>
|
||||
<data name="Test_in_calculation" xml:space="preserve">
|
||||
<value>Test in calculation</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -259,4 +259,7 @@
|
||||
<data name="Units" xml:space="preserve">
|
||||
<value />
|
||||
</data>
|
||||
<data name="Test_in_calculation" xml:space="preserve">
|
||||
<value>Prebieha výpočet</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -111,6 +111,7 @@ namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
|
||||
public void TurnOff()
|
||||
{
|
||||
log.DebugFormat("{0}.TurnOff()", Name);
|
||||
if ((pumpFm1 != null) && (pumpFm2 != null))
|
||||
{
|
||||
pumpFm1.TurnOff();
|
||||
@@ -120,6 +121,7 @@ namespace TBF.Rig.BuiltIn.PumpTandem
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
log.DebugFormat("DONE {0}.TurnOff()", Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -332,6 +332,8 @@ namespace TBF.Rig.Danfoss.VLT2800
|
||||
Telegram.UpdateTelegramChecksum(msg);
|
||||
}
|
||||
SendData(msg);
|
||||
|
||||
log.DebugFormat("DONE {0}.TurnOff()", Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -264,6 +264,8 @@ namespace TBF.Rig.Modbus.PumpFM.DanfossVLT
|
||||
|
||||
modbus.SendMessage(msg, Name);
|
||||
}
|
||||
|
||||
log.DebugFormat("DONE {0}.TurnOff()", Name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -416,6 +416,8 @@ namespace TBF.Rig.Modbus.PumpFM.Grundfoss
|
||||
// --- DIAGNOSTIKA ---
|
||||
LiveLogDiag.Log1("GF TurnOff msg = " + BitConverter.ToString(msg));
|
||||
}
|
||||
|
||||
log.DebugFormat("DONE {0}.TurnOff()", Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -16,8 +16,6 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
{
|
||||
return new GenesisCfgCtrl();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Serialized parameters
|
||||
@@ -31,8 +29,10 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
public int MuxBoardNr; /// 0 = use RfidComPort(Nr), otherwise mux. board nr. 1 .. 4
|
||||
public int Group; /// Number written to QuidoRS to connct the watermeter to RfidComPort, 1 .. 10
|
||||
public CommunicationInterface CommunicationInterface; /// Communication Interface: RFID or NFC
|
||||
///
|
||||
public bool EnableShowChanels;
|
||||
public int IBeginDataFlush;
|
||||
|
||||
|
||||
|
||||
/// <summary> Procedure parameters </summary>
|
||||
[XmlIgnore]
|
||||
@@ -56,6 +56,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
ProcParams = CreateProcParamsProvider() as ProcParams;
|
||||
CommunicationInterface = CommunicationInterface.RFID;
|
||||
HeadCommunicationComPortNr = 0;
|
||||
EnableShowChanels = false;
|
||||
IBeginDataFlush = 2000;
|
||||
}
|
||||
|
||||
public GenesisCfg(IComponentFactory factory)
|
||||
@@ -67,7 +69,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
|
||||
public string ToString(int i)
|
||||
{
|
||||
return $"{Name} Group1 (mux#)={MuxBoardNr}, Group2={Group}, Opto=Com{OptoComPortNr}, {CommunicationInterface}=Com{RfidComPortNr}";
|
||||
return $"{Name} Group1 (mux#)={MuxBoardNr}, Group2={Group}, Opto=Com{OptoComPortNr}, {CommunicationInterface}=Com{RfidComPortNr}, EnableShowChanels={EnableShowChanels}, IBeginDataFlush={IBeginDataFlush}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
muxBoardNrTextBox.Text = config.MuxBoardNr.ToString();
|
||||
groupTextBox.Text = config.Group.ToString();
|
||||
comboBoxCommunicationInterface.SelectedItem = config.CommunicationInterface.ToString();
|
||||
tBBeginDataFlush.Text = config.IBeginDataFlush.ToString();
|
||||
checkBox_EnableShowChanels.Checked = config.EnableShowChanels;
|
||||
|
||||
tabPage2.Controls.Add(new GenesisHeadTestCtrl(config));
|
||||
}
|
||||
|
||||
@@ -74,6 +77,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
muxBoardNrTextBox.Enabled = true;
|
||||
groupTextBox.Enabled = true;
|
||||
comboBoxCommunicationInterface.Enabled = true;
|
||||
tBBeginDataFlush.Enabled = true;
|
||||
checkBox_EnableShowChanels.Enabled = true;
|
||||
}
|
||||
|
||||
public CfgUpdateFlags VerifyCfg(ref string message)
|
||||
@@ -129,6 +134,12 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, groupLabel.Text);
|
||||
}
|
||||
|
||||
if (!int.TryParse(tBBeginDataFlush.Text, out dummy) || dummy < 0 || dummy > 10000)
|
||||
{
|
||||
flags |= CfgUpdateFlags.Error;
|
||||
message += Environment.NewLine + string.Format(Strings.Invalid_0, tBBeginDataFlush.Text);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
@@ -158,6 +169,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
config.Group = int.Parse(groupTextBox.Text);
|
||||
config.CommunicationInterface = (CommunicationInterface)comboBoxCommunicationInterface.SelectedIndex;
|
||||
config.HeadCommunicationComPortNr = int.Parse(headPortNrTextBox.Text);
|
||||
config.IBeginDataFlush = int.Parse(tBBeginDataFlush.Text);
|
||||
config.EnableShowChanels = checkBox_EnableShowChanels.Checked;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
+421
-376
@@ -25,388 +25,433 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.comboBoxCommunicationInterface = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.rfidPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.rfidSerialPortNrLabel = new System.Windows.Forms.Label();
|
||||
this.optoDataGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.tcpipPortLabel = new System.Windows.Forms.Label();
|
||||
this.tcpipPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ipAddressLabel = new System.Windows.Forms.Label();
|
||||
this.ipAddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.radioButton1 = new System.Windows.Forms.RadioButton();
|
||||
this.radioButton2 = new System.Windows.Forms.RadioButton();
|
||||
this.optoSerialPortLabel = new System.Windows.Forms.Label();
|
||||
this.optoSerialPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupLabel = new System.Windows.Forms.Label();
|
||||
this.muxBoardNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.muxBoardNrLabel = 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.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.headPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.optoDataGroupBox.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Location = new System.Drawing.Point(3, 3);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(611, 432);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.groupBox2);
|
||||
this.tabPage1.Controls.Add(this.label4);
|
||||
this.tabPage1.Controls.Add(this.label3);
|
||||
this.tabPage1.Controls.Add(this.groupBox1);
|
||||
this.tabPage1.Controls.Add(this.optoDataGroupBox);
|
||||
this.tabPage1.Controls.Add(this.groupTextBox);
|
||||
this.tabPage1.Controls.Add(this.groupLabel);
|
||||
this.tabPage1.Controls.Add(this.muxBoardNrTextBox);
|
||||
this.tabPage1.Controls.Add(this.muxBoardNrLabel);
|
||||
this.tabPage1.Controls.Add(this.nameTextBox);
|
||||
this.tabPage1.Controls.Add(this.nameLabel);
|
||||
this.tabPage1.Controls.Add(this.classNameLabel);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 25);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(603, 403);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Config";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(208, 101);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(40, 16);
|
||||
this.label4.TabIndex = 25;
|
||||
this.label4.Text = "1 .. 10";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(208, 72);
|
||||
this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(33, 16);
|
||||
this.label3.TabIndex = 24;
|
||||
this.label3.Text = "1 .. 4";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.comboBoxCommunicationInterface);
|
||||
this.groupBox1.Controls.Add(this.label1);
|
||||
this.groupBox1.Controls.Add(this.rfidPortNrTextBox);
|
||||
this.groupBox1.Controls.Add(this.rfidSerialPortNrLabel);
|
||||
this.groupBox1.Location = new System.Drawing.Point(10, 259);
|
||||
this.groupBox1.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Padding = new System.Windows.Forms.Padding(4);
|
||||
this.groupBox1.Size = new System.Drawing.Size(552, 68);
|
||||
this.groupBox1.TabIndex = 23;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "RFID / NFC communication (in case mux. board is not used)";
|
||||
//
|
||||
// comboBoxCommunicationInterface
|
||||
//
|
||||
this.comboBoxCommunicationInterface.Enabled = false;
|
||||
this.comboBoxCommunicationInterface.FormattingEnabled = true;
|
||||
this.comboBoxCommunicationInterface.Items.AddRange(new object[] {
|
||||
"RFID",
|
||||
"NFC"});
|
||||
this.comboBoxCommunicationInterface.Location = new System.Drawing.Point(201, 27);
|
||||
this.comboBoxCommunicationInterface.Name = "comboBoxCommunicationInterface";
|
||||
this.comboBoxCommunicationInterface.Size = new System.Drawing.Size(71, 24);
|
||||
this.comboBoxCommunicationInterface.TabIndex = 9;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(41, 30);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(153, 16);
|
||||
this.label1.TabIndex = 8;
|
||||
this.label1.Text = "Communication Interface";
|
||||
//
|
||||
// rfidPortNrTextBox
|
||||
//
|
||||
this.rfidPortNrTextBox.Enabled = false;
|
||||
this.rfidPortNrTextBox.Location = new System.Drawing.Point(439, 26);
|
||||
this.rfidPortNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.rfidPortNrTextBox.Name = "rfidPortNrTextBox";
|
||||
this.rfidPortNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||
this.rfidPortNrTextBox.TabIndex = 7;
|
||||
//
|
||||
// rfidSerialPortNrLabel
|
||||
//
|
||||
this.rfidSerialPortNrLabel.AutoSize = true;
|
||||
this.rfidSerialPortNrLabel.Location = new System.Drawing.Point(321, 30);
|
||||
this.rfidSerialPortNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.rfidSerialPortNrLabel.Name = "rfidSerialPortNrLabel";
|
||||
this.rfidSerialPortNrLabel.Size = new System.Drawing.Size(88, 16);
|
||||
this.rfidSerialPortNrLabel.TabIndex = 6;
|
||||
this.rfidSerialPortNrLabel.Text = "Serial port nr.:";
|
||||
//
|
||||
// optoDataGroupBox
|
||||
//
|
||||
this.optoDataGroupBox.Controls.Add(this.tcpipPortLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.tcpipPortTextBox);
|
||||
this.optoDataGroupBox.Controls.Add(this.ipAddressLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.ipAddressTextBox);
|
||||
this.optoDataGroupBox.Controls.Add(this.radioButton1);
|
||||
this.optoDataGroupBox.Controls.Add(this.radioButton2);
|
||||
this.optoDataGroupBox.Controls.Add(this.optoSerialPortLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.optoSerialPortTextBox);
|
||||
this.optoDataGroupBox.Location = new System.Drawing.Point(10, 131);
|
||||
this.optoDataGroupBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.optoDataGroupBox.Name = "optoDataGroupBox";
|
||||
this.optoDataGroupBox.Padding = new System.Windows.Forms.Padding(4);
|
||||
this.optoDataGroupBox.Size = new System.Drawing.Size(552, 119);
|
||||
this.optoDataGroupBox.TabIndex = 18;
|
||||
this.optoDataGroupBox.TabStop = false;
|
||||
this.optoDataGroupBox.Text = "Opto-data";
|
||||
//
|
||||
// tcpipPortLabel
|
||||
//
|
||||
this.tcpipPortLabel.AutoSize = true;
|
||||
this.tcpipPortLabel.Location = new System.Drawing.Point(41, 87);
|
||||
this.tcpipPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.tcpipPortLabel.Name = "tcpipPortLabel";
|
||||
this.tcpipPortLabel.Size = new System.Drawing.Size(54, 16);
|
||||
this.tcpipPortLabel.TabIndex = 4;
|
||||
this.tcpipPortLabel.Text = "Port nr..:";
|
||||
//
|
||||
// tcpipPortTextBox
|
||||
//
|
||||
this.tcpipPortTextBox.Enabled = false;
|
||||
this.tcpipPortTextBox.Location = new System.Drawing.Point(143, 84);
|
||||
this.tcpipPortTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.tcpipPortTextBox.Name = "tcpipPortTextBox";
|
||||
this.tcpipPortTextBox.Size = new System.Drawing.Size(51, 22);
|
||||
this.tcpipPortTextBox.TabIndex = 5;
|
||||
//
|
||||
// ipAddressLabel
|
||||
//
|
||||
this.ipAddressLabel.AutoSize = true;
|
||||
this.ipAddressLabel.Location = new System.Drawing.Point(41, 59);
|
||||
this.ipAddressLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.ipAddressLabel.Name = "ipAddressLabel";
|
||||
this.ipAddressLabel.Size = new System.Drawing.Size(78, 16);
|
||||
this.ipAddressLabel.TabIndex = 2;
|
||||
this.ipAddressLabel.Text = "IP address.:";
|
||||
//
|
||||
// ipAddressTextBox
|
||||
//
|
||||
this.ipAddressTextBox.Enabled = false;
|
||||
this.ipAddressTextBox.Location = new System.Drawing.Point(143, 55);
|
||||
this.ipAddressTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.ipAddressTextBox.Name = "ipAddressTextBox";
|
||||
this.ipAddressTextBox.Size = new System.Drawing.Size(129, 22);
|
||||
this.ipAddressTextBox.TabIndex = 3;
|
||||
//
|
||||
// radioButton1
|
||||
//
|
||||
this.radioButton1.AutoSize = true;
|
||||
this.radioButton1.Checked = true;
|
||||
this.radioButton1.Enabled = false;
|
||||
this.radioButton1.Location = new System.Drawing.Point(29, 23);
|
||||
this.radioButton1.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.radioButton1.Name = "radioButton1";
|
||||
this.radioButton1.Size = new System.Drawing.Size(99, 20);
|
||||
this.radioButton1.TabIndex = 0;
|
||||
this.radioButton1.TabStop = true;
|
||||
this.radioButton1.Text = "Use TCP/IP";
|
||||
this.radioButton1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// radioButton2
|
||||
//
|
||||
this.radioButton2.AutoSize = true;
|
||||
this.radioButton2.Enabled = false;
|
||||
this.radioButton2.Location = new System.Drawing.Point(312, 23);
|
||||
this.radioButton2.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.radioButton2.Name = "radioButton2";
|
||||
this.radioButton2.Size = new System.Drawing.Size(115, 20);
|
||||
this.radioButton2.TabIndex = 1;
|
||||
this.radioButton2.Text = "Use serial port";
|
||||
this.radioButton2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// optoSerialPortLabel
|
||||
//
|
||||
this.optoSerialPortLabel.AutoSize = true;
|
||||
this.optoSerialPortLabel.Location = new System.Drawing.Point(321, 55);
|
||||
this.optoSerialPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.optoSerialPortLabel.Name = "optoSerialPortLabel";
|
||||
this.optoSerialPortLabel.Size = new System.Drawing.Size(88, 16);
|
||||
this.optoSerialPortLabel.TabIndex = 6;
|
||||
this.optoSerialPortLabel.Text = "Serial port nr.:";
|
||||
//
|
||||
// optoSerialPortTextBox
|
||||
//
|
||||
this.optoSerialPortTextBox.Enabled = false;
|
||||
this.optoSerialPortTextBox.Location = new System.Drawing.Point(439, 52);
|
||||
this.optoSerialPortTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.optoSerialPortTextBox.Name = "optoSerialPortTextBox";
|
||||
this.optoSerialPortTextBox.Size = new System.Drawing.Size(44, 22);
|
||||
this.optoSerialPortTextBox.TabIndex = 7;
|
||||
//
|
||||
// groupTextBox
|
||||
//
|
||||
this.groupTextBox.Enabled = false;
|
||||
this.groupTextBox.Location = new System.Drawing.Point(153, 97);
|
||||
this.groupTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.groupTextBox.Name = "groupTextBox";
|
||||
this.groupTextBox.Size = new System.Drawing.Size(44, 22);
|
||||
this.groupTextBox.TabIndex = 22;
|
||||
//
|
||||
// groupLabel
|
||||
//
|
||||
this.groupLabel.AutoSize = true;
|
||||
this.groupLabel.Location = new System.Drawing.Point(6, 101);
|
||||
this.groupLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.groupLabel.Name = "groupLabel";
|
||||
this.groupLabel.Size = new System.Drawing.Size(54, 16);
|
||||
this.groupLabel.TabIndex = 21;
|
||||
this.groupLabel.Text = "Group 2";
|
||||
//
|
||||
// muxBoardNrTextBox
|
||||
//
|
||||
this.muxBoardNrTextBox.Enabled = false;
|
||||
this.muxBoardNrTextBox.Location = new System.Drawing.Point(153, 69);
|
||||
this.muxBoardNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.muxBoardNrTextBox.Name = "muxBoardNrTextBox";
|
||||
this.muxBoardNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||
this.muxBoardNrTextBox.TabIndex = 20;
|
||||
//
|
||||
// muxBoardNrLabel
|
||||
//
|
||||
this.muxBoardNrLabel.AutoSize = true;
|
||||
this.muxBoardNrLabel.Location = new System.Drawing.Point(6, 72);
|
||||
this.muxBoardNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.muxBoardNrLabel.Name = "muxBoardNrLabel";
|
||||
this.muxBoardNrLabel.Size = new System.Drawing.Size(131, 16);
|
||||
this.muxBoardNrLabel.TabIndex = 19;
|
||||
this.muxBoardNrLabel.Text = "Group 1 (mux. board)";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(153, 40);
|
||||
this.nameTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(160, 22);
|
||||
this.nameTextBox.TabIndex = 17;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(6, 44);
|
||||
this.nameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(44, 16);
|
||||
this.nameLabel.TabIndex = 16;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(149, 11);
|
||||
this.classNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(78, 16);
|
||||
this.classNameLabel.TabIndex = 15;
|
||||
this.classNameLabel.Text = "ClassName";
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 25);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(603, 403);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Test";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.headPortNrTextBox);
|
||||
this.groupBox2.Controls.Add(this.label2);
|
||||
this.groupBox2.Location = new System.Drawing.Point(10, 335);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(552, 50);
|
||||
this.groupBox2.TabIndex = 26;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Head Communication";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(321, 18);
|
||||
this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(88, 16);
|
||||
this.label2.TabIndex = 7;
|
||||
this.label2.Text = "Serial port nr.:";
|
||||
//
|
||||
// headPortNrTextBox
|
||||
//
|
||||
this.headPortNrTextBox.Enabled = false;
|
||||
this.headPortNrTextBox.Location = new System.Drawing.Point(439, 15);
|
||||
this.headPortNrTextBox.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.headPortNrTextBox.Name = "headPortNrTextBox";
|
||||
this.headPortNrTextBox.Size = new System.Drawing.Size(44, 22);
|
||||
this.headPortNrTextBox.TabIndex = 8;
|
||||
//
|
||||
// IperlHeadCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Margin = new System.Windows.Forms.Padding(4);
|
||||
this.Name = "GenesisCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(617, 438);
|
||||
this.Load += new System.EventHandler(this.WaterMeterCfgCtrl_Load);
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.optoDataGroupBox.ResumeLayout(false);
|
||||
this.optoDataGroupBox.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.headPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.comboBoxCommunicationInterface = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.rfidPortNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.rfidSerialPortNrLabel = new System.Windows.Forms.Label();
|
||||
this.optoDataGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.checkBox_EnableShowChanels = new System.Windows.Forms.CheckBox();
|
||||
this.tBBeginDataFlush = new System.Windows.Forms.TextBox();
|
||||
this.labelFlush = new System.Windows.Forms.Label();
|
||||
this.tcpipPortLabel = new System.Windows.Forms.Label();
|
||||
this.tcpipPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.ipAddressLabel = new System.Windows.Forms.Label();
|
||||
this.ipAddressTextBox = new System.Windows.Forms.TextBox();
|
||||
this.radioButton1 = new System.Windows.Forms.RadioButton();
|
||||
this.radioButton2 = new System.Windows.Forms.RadioButton();
|
||||
this.optoSerialPortLabel = new System.Windows.Forms.Label();
|
||||
this.optoSerialPortTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupTextBox = new System.Windows.Forms.TextBox();
|
||||
this.groupLabel = new System.Windows.Forms.Label();
|
||||
this.muxBoardNrTextBox = new System.Windows.Forms.TextBox();
|
||||
this.muxBoardNrLabel = 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.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.optoDataGroupBox.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Location = new System.Drawing.Point(3, 4);
|
||||
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(687, 540);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.Controls.Add(this.groupBox2);
|
||||
this.tabPage1.Controls.Add(this.label4);
|
||||
this.tabPage1.Controls.Add(this.label3);
|
||||
this.tabPage1.Controls.Add(this.groupBox1);
|
||||
this.tabPage1.Controls.Add(this.optoDataGroupBox);
|
||||
this.tabPage1.Controls.Add(this.groupTextBox);
|
||||
this.tabPage1.Controls.Add(this.groupLabel);
|
||||
this.tabPage1.Controls.Add(this.muxBoardNrTextBox);
|
||||
this.tabPage1.Controls.Add(this.muxBoardNrLabel);
|
||||
this.tabPage1.Controls.Add(this.nameTextBox);
|
||||
this.tabPage1.Controls.Add(this.nameLabel);
|
||||
this.tabPage1.Controls.Add(this.classNameLabel);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 29);
|
||||
this.tabPage1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tabPage1.Size = new System.Drawing.Size(679, 507);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Config";
|
||||
this.tabPage1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.headPortNrTextBox);
|
||||
this.groupBox2.Controls.Add(this.label2);
|
||||
this.groupBox2.Location = new System.Drawing.Point(11, 450);
|
||||
this.groupBox2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.groupBox2.Size = new System.Drawing.Size(621, 52);
|
||||
this.groupBox2.TabIndex = 26;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Head Communication";
|
||||
//
|
||||
// headPortNrTextBox
|
||||
//
|
||||
this.headPortNrTextBox.Enabled = false;
|
||||
this.headPortNrTextBox.Location = new System.Drawing.Point(494, 19);
|
||||
this.headPortNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.headPortNrTextBox.Name = "headPortNrTextBox";
|
||||
this.headPortNrTextBox.Size = new System.Drawing.Size(49, 26);
|
||||
this.headPortNrTextBox.TabIndex = 8;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(361, 22);
|
||||
this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(107, 20);
|
||||
this.label2.TabIndex = 7;
|
||||
this.label2.Text = "Serial port nr.:";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(234, 126);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(52, 20);
|
||||
this.label4.TabIndex = 25;
|
||||
this.label4.Text = "1 .. 10";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(234, 90);
|
||||
this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(43, 20);
|
||||
this.label3.TabIndex = 24;
|
||||
this.label3.Text = "1 .. 4";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.comboBoxCommunicationInterface);
|
||||
this.groupBox1.Controls.Add(this.label1);
|
||||
this.groupBox1.Controls.Add(this.rfidPortNrTextBox);
|
||||
this.groupBox1.Controls.Add(this.rfidSerialPortNrLabel);
|
||||
this.groupBox1.Location = new System.Drawing.Point(11, 363);
|
||||
this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.groupBox1.Size = new System.Drawing.Size(621, 85);
|
||||
this.groupBox1.TabIndex = 23;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "RFID / NFC communication (in case mux. board is not used)";
|
||||
//
|
||||
// comboBoxCommunicationInterface
|
||||
//
|
||||
this.comboBoxCommunicationInterface.Enabled = false;
|
||||
this.comboBoxCommunicationInterface.FormattingEnabled = true;
|
||||
this.comboBoxCommunicationInterface.Items.AddRange(new object[] { "RFID", "NFC" });
|
||||
this.comboBoxCommunicationInterface.Location = new System.Drawing.Point(226, 34);
|
||||
this.comboBoxCommunicationInterface.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.comboBoxCommunicationInterface.Name = "comboBoxCommunicationInterface";
|
||||
this.comboBoxCommunicationInterface.Size = new System.Drawing.Size(79, 28);
|
||||
this.comboBoxCommunicationInterface.TabIndex = 9;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(46, 38);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(187, 20);
|
||||
this.label1.TabIndex = 8;
|
||||
this.label1.Text = "Communication Interface";
|
||||
//
|
||||
// rfidPortNrTextBox
|
||||
//
|
||||
this.rfidPortNrTextBox.Enabled = false;
|
||||
this.rfidPortNrTextBox.Location = new System.Drawing.Point(494, 32);
|
||||
this.rfidPortNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.rfidPortNrTextBox.Name = "rfidPortNrTextBox";
|
||||
this.rfidPortNrTextBox.Size = new System.Drawing.Size(49, 26);
|
||||
this.rfidPortNrTextBox.TabIndex = 7;
|
||||
//
|
||||
// rfidSerialPortNrLabel
|
||||
//
|
||||
this.rfidSerialPortNrLabel.AutoSize = true;
|
||||
this.rfidSerialPortNrLabel.Location = new System.Drawing.Point(361, 38);
|
||||
this.rfidSerialPortNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.rfidSerialPortNrLabel.Name = "rfidSerialPortNrLabel";
|
||||
this.rfidSerialPortNrLabel.Size = new System.Drawing.Size(107, 20);
|
||||
this.rfidSerialPortNrLabel.TabIndex = 6;
|
||||
this.rfidSerialPortNrLabel.Text = "Serial port nr.:";
|
||||
//
|
||||
// optoDataGroupBox
|
||||
//
|
||||
this.optoDataGroupBox.Controls.Add(this.checkBox_EnableShowChanels);
|
||||
this.optoDataGroupBox.Controls.Add(this.tBBeginDataFlush);
|
||||
this.optoDataGroupBox.Controls.Add(this.labelFlush);
|
||||
this.optoDataGroupBox.Controls.Add(this.tcpipPortLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.tcpipPortTextBox);
|
||||
this.optoDataGroupBox.Controls.Add(this.ipAddressLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.ipAddressTextBox);
|
||||
this.optoDataGroupBox.Controls.Add(this.radioButton1);
|
||||
this.optoDataGroupBox.Controls.Add(this.radioButton2);
|
||||
this.optoDataGroupBox.Controls.Add(this.optoSerialPortLabel);
|
||||
this.optoDataGroupBox.Controls.Add(this.optoSerialPortTextBox);
|
||||
this.optoDataGroupBox.Location = new System.Drawing.Point(11, 164);
|
||||
this.optoDataGroupBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.optoDataGroupBox.Name = "optoDataGroupBox";
|
||||
this.optoDataGroupBox.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.optoDataGroupBox.Size = new System.Drawing.Size(621, 189);
|
||||
this.optoDataGroupBox.TabIndex = 18;
|
||||
this.optoDataGroupBox.TabStop = false;
|
||||
this.optoDataGroupBox.Text = "Opto-data";
|
||||
//
|
||||
// checkBox_EnableShowChanels
|
||||
//
|
||||
this.checkBox_EnableShowChanels.Checked = true;
|
||||
this.checkBox_EnableShowChanels.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.checkBox_EnableShowChanels.Enabled = false;
|
||||
this.checkBox_EnableShowChanels.Location = new System.Drawing.Point(351, 147);
|
||||
this.checkBox_EnableShowChanels.Name = "checkBox_EnableShowChanels";
|
||||
this.checkBox_EnableShowChanels.Size = new System.Drawing.Size(238, 24);
|
||||
this.checkBox_EnableShowChanels.TabIndex = 10;
|
||||
this.checkBox_EnableShowChanels.Text = "Enable Show Channels";
|
||||
this.checkBox_EnableShowChanels.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tBBeginDataFlush
|
||||
//
|
||||
this.tBBeginDataFlush.Enabled = false;
|
||||
this.tBBeginDataFlush.Location = new System.Drawing.Point(474, 105);
|
||||
this.tBBeginDataFlush.MaxLength = 8;
|
||||
this.tBBeginDataFlush.Name = "tBBeginDataFlush";
|
||||
this.tBBeginDataFlush.Size = new System.Drawing.Size(69, 26);
|
||||
this.tBBeginDataFlush.TabIndex = 9;
|
||||
this.tBBeginDataFlush.Text = "2000";
|
||||
this.tBBeginDataFlush.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||
//
|
||||
// labelFlush
|
||||
//
|
||||
this.labelFlush.Location = new System.Drawing.Point(328, 109);
|
||||
this.labelFlush.Name = "labelFlush";
|
||||
this.labelFlush.Size = new System.Drawing.Size(140, 22);
|
||||
this.labelFlush.TabIndex = 8;
|
||||
this.labelFlush.Text = "Begin Data Flush:";
|
||||
//
|
||||
// tcpipPortLabel
|
||||
//
|
||||
this.tcpipPortLabel.AutoSize = true;
|
||||
this.tcpipPortLabel.Location = new System.Drawing.Point(46, 109);
|
||||
this.tcpipPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.tcpipPortLabel.Name = "tcpipPortLabel";
|
||||
this.tcpipPortLabel.Size = new System.Drawing.Size(68, 20);
|
||||
this.tcpipPortLabel.TabIndex = 4;
|
||||
this.tcpipPortLabel.Text = "Port nr..:";
|
||||
//
|
||||
// tcpipPortTextBox
|
||||
//
|
||||
this.tcpipPortTextBox.Enabled = false;
|
||||
this.tcpipPortTextBox.Location = new System.Drawing.Point(161, 105);
|
||||
this.tcpipPortTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.tcpipPortTextBox.Name = "tcpipPortTextBox";
|
||||
this.tcpipPortTextBox.Size = new System.Drawing.Size(57, 26);
|
||||
this.tcpipPortTextBox.TabIndex = 5;
|
||||
//
|
||||
// ipAddressLabel
|
||||
//
|
||||
this.ipAddressLabel.AutoSize = true;
|
||||
this.ipAddressLabel.Location = new System.Drawing.Point(46, 74);
|
||||
this.ipAddressLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.ipAddressLabel.Name = "ipAddressLabel";
|
||||
this.ipAddressLabel.Size = new System.Drawing.Size(93, 20);
|
||||
this.ipAddressLabel.TabIndex = 2;
|
||||
this.ipAddressLabel.Text = "IP address.:";
|
||||
//
|
||||
// ipAddressTextBox
|
||||
//
|
||||
this.ipAddressTextBox.Enabled = false;
|
||||
this.ipAddressTextBox.Location = new System.Drawing.Point(161, 69);
|
||||
this.ipAddressTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.ipAddressTextBox.Name = "ipAddressTextBox";
|
||||
this.ipAddressTextBox.Size = new System.Drawing.Size(145, 26);
|
||||
this.ipAddressTextBox.TabIndex = 3;
|
||||
//
|
||||
// radioButton1
|
||||
//
|
||||
this.radioButton1.AutoSize = true;
|
||||
this.radioButton1.Checked = true;
|
||||
this.radioButton1.Enabled = false;
|
||||
this.radioButton1.Location = new System.Drawing.Point(33, 29);
|
||||
this.radioButton1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.radioButton1.Name = "radioButton1";
|
||||
this.radioButton1.Size = new System.Drawing.Size(109, 24);
|
||||
this.radioButton1.TabIndex = 0;
|
||||
this.radioButton1.TabStop = true;
|
||||
this.radioButton1.Text = "Use TCP/IP";
|
||||
this.radioButton1.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// radioButton2
|
||||
//
|
||||
this.radioButton2.AutoSize = true;
|
||||
this.radioButton2.Enabled = false;
|
||||
this.radioButton2.Location = new System.Drawing.Point(351, 29);
|
||||
this.radioButton2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.radioButton2.Name = "radioButton2";
|
||||
this.radioButton2.Size = new System.Drawing.Size(129, 24);
|
||||
this.radioButton2.TabIndex = 1;
|
||||
this.radioButton2.Text = "Use serial port";
|
||||
this.radioButton2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// optoSerialPortLabel
|
||||
//
|
||||
this.optoSerialPortLabel.AutoSize = true;
|
||||
this.optoSerialPortLabel.Location = new System.Drawing.Point(361, 69);
|
||||
this.optoSerialPortLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.optoSerialPortLabel.Name = "optoSerialPortLabel";
|
||||
this.optoSerialPortLabel.Size = new System.Drawing.Size(107, 20);
|
||||
this.optoSerialPortLabel.TabIndex = 6;
|
||||
this.optoSerialPortLabel.Text = "Serial port nr.:";
|
||||
//
|
||||
// optoSerialPortTextBox
|
||||
//
|
||||
this.optoSerialPortTextBox.Enabled = false;
|
||||
this.optoSerialPortTextBox.Location = new System.Drawing.Point(494, 65);
|
||||
this.optoSerialPortTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.optoSerialPortTextBox.Name = "optoSerialPortTextBox";
|
||||
this.optoSerialPortTextBox.Size = new System.Drawing.Size(49, 26);
|
||||
this.optoSerialPortTextBox.TabIndex = 7;
|
||||
//
|
||||
// groupTextBox
|
||||
//
|
||||
this.groupTextBox.Enabled = false;
|
||||
this.groupTextBox.Location = new System.Drawing.Point(172, 121);
|
||||
this.groupTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.groupTextBox.Name = "groupTextBox";
|
||||
this.groupTextBox.Size = new System.Drawing.Size(49, 26);
|
||||
this.groupTextBox.TabIndex = 22;
|
||||
//
|
||||
// groupLabel
|
||||
//
|
||||
this.groupLabel.AutoSize = true;
|
||||
this.groupLabel.Location = new System.Drawing.Point(7, 126);
|
||||
this.groupLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.groupLabel.Name = "groupLabel";
|
||||
this.groupLabel.Size = new System.Drawing.Size(67, 20);
|
||||
this.groupLabel.TabIndex = 21;
|
||||
this.groupLabel.Text = "Group 2";
|
||||
//
|
||||
// muxBoardNrTextBox
|
||||
//
|
||||
this.muxBoardNrTextBox.Enabled = false;
|
||||
this.muxBoardNrTextBox.Location = new System.Drawing.Point(172, 86);
|
||||
this.muxBoardNrTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.muxBoardNrTextBox.Name = "muxBoardNrTextBox";
|
||||
this.muxBoardNrTextBox.Size = new System.Drawing.Size(49, 26);
|
||||
this.muxBoardNrTextBox.TabIndex = 20;
|
||||
//
|
||||
// muxBoardNrLabel
|
||||
//
|
||||
this.muxBoardNrLabel.AutoSize = true;
|
||||
this.muxBoardNrLabel.Location = new System.Drawing.Point(7, 90);
|
||||
this.muxBoardNrLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.muxBoardNrLabel.Name = "muxBoardNrLabel";
|
||||
this.muxBoardNrLabel.Size = new System.Drawing.Size(159, 20);
|
||||
this.muxBoardNrLabel.TabIndex = 19;
|
||||
this.muxBoardNrLabel.Text = "Group 1 (mux. board)";
|
||||
//
|
||||
// nameTextBox
|
||||
//
|
||||
this.nameTextBox.Enabled = false;
|
||||
this.nameTextBox.Location = new System.Drawing.Point(172, 50);
|
||||
this.nameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.nameTextBox.Name = "nameTextBox";
|
||||
this.nameTextBox.Size = new System.Drawing.Size(180, 26);
|
||||
this.nameTextBox.TabIndex = 17;
|
||||
//
|
||||
// nameLabel
|
||||
//
|
||||
this.nameLabel.AutoSize = true;
|
||||
this.nameLabel.Location = new System.Drawing.Point(7, 55);
|
||||
this.nameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.nameLabel.Name = "nameLabel";
|
||||
this.nameLabel.Size = new System.Drawing.Size(51, 20);
|
||||
this.nameLabel.TabIndex = 16;
|
||||
this.nameLabel.Text = "Name";
|
||||
//
|
||||
// classNameLabel
|
||||
//
|
||||
this.classNameLabel.AutoSize = true;
|
||||
this.classNameLabel.Location = new System.Drawing.Point(168, 14);
|
||||
this.classNameLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.classNameLabel.Name = "classNameLabel";
|
||||
this.classNameLabel.Size = new System.Drawing.Size(90, 20);
|
||||
this.classNameLabel.TabIndex = 15;
|
||||
this.classNameLabel.Text = "ClassName";
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 29);
|
||||
this.tabPage2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tabPage2.Size = new System.Drawing.Size(679, 507);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "Test";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// GenesisCfgCtrl
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||
this.Name = "GenesisCfgCtrl";
|
||||
this.Size = new System.Drawing.Size(694, 548);
|
||||
this.Load += new System.EventHandler(this.WaterMeterCfgCtrl_Load);
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.optoDataGroupBox.ResumeLayout(false);
|
||||
this.optoDataGroupBox.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
private System.Windows.Forms.CheckBox checkBox_EnableShowChanels;
|
||||
|
||||
private System.Windows.Forms.Label labelFlush;
|
||||
private System.Windows.Forms.TextBox tBBeginDataFlush;
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Globalization;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis.DataPackages.MeasurementRecords;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis.Protocols.StreamingProtocol;
|
||||
|
||||
using Xylem.Common.Metrology.Measurements;
|
||||
|
||||
|
||||
namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
@@ -25,6 +25,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
public static readonly int Length = 42;
|
||||
private static CultureInfo culture;
|
||||
|
||||
public MeasurementRecord data;
|
||||
|
||||
///
|
||||
/// Strobed value
|
||||
@@ -124,11 +125,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
}
|
||||
|
||||
|
||||
// -------- TIMESTAMP (seconds) --------
|
||||
private const double TS_RANGE = StreamingDecoder.CpuTimeOverflowS;
|
||||
|
||||
// -------- VOLUME (liters) --------
|
||||
private const double VOL_RANGE = StreamingDecoder.DefaultAccuDutOverflowVolumeCm * 1000;
|
||||
|
||||
/// <summary>
|
||||
/// update data by CalibrationRecord
|
||||
@@ -149,7 +146,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
if (data == null)
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
|
||||
UpdateData( data.Channel, data.VolumeCm, data.TimeS, counter, refFlow, ref volumeRawExtLast, ref timestampExtLast);
|
||||
this.data = data;
|
||||
UpdateData( data.Channel, data.VolumeCm, data.OverflowVolumeCm, data.TimeS, data.OverflowTimeS, counter, refFlow, ref volumeRawExtLast, ref timestampExtLast);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,8 +168,8 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
|
||||
UpdateData( data.Channel, data.VolumeCm, data.TimeS, counter, refFlow, ref volumeRawExtLast, ref timestampExtLast);
|
||||
this.data = data;
|
||||
UpdateData( data.Channel, data.VolumeCm, data.OverflowVolumeCm, data.TimeS, data.OverflowTimeS, counter, refFlow, ref volumeRawExtLast, ref timestampExtLast);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -187,7 +185,9 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
private void UpdateData(
|
||||
int channel,
|
||||
double volumeCm,
|
||||
double OverflowVolumeCm,
|
||||
double timeS,
|
||||
double OverflowTimeS,
|
||||
int counter,
|
||||
float refFlow,
|
||||
ref double volumeRawExtLast,
|
||||
@@ -200,29 +200,30 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
Flags = OptoTelegramFlags.OK;
|
||||
|
||||
FlowRaw = 0;
|
||||
VolumeRaw = volumeCm * 1000.0; // liters
|
||||
double nV = NormalizeByOverflow(volumeCm, OverflowVolumeCm);
|
||||
VolumeRaw = nV * 1000.0; // liters
|
||||
CheckSum = 0;
|
||||
Impedance = 0;
|
||||
EmfRaw = 0;
|
||||
MagneticFieldRaw = 0;
|
||||
|
||||
double ts = NormalizeTimestamp(timeS);
|
||||
double ts = NormalizeByOverflow(timeS, OverflowTimeS);
|
||||
Timestamp = ts;
|
||||
|
||||
VolumeRawExt = UnwrapVolume(VolumeRaw, ref volumeRawExtLast);
|
||||
TimestampExt = UnwrapTimestamp(ts, ref timestampExtLast);
|
||||
VolumeRawExt = UnwrapVolume(VolumeRaw,OverflowVolumeCm * 1000, ref volumeRawExtLast);
|
||||
TimestampExt = UnwrapTimestamp(ts,OverflowTimeS, ref timestampExtLast);
|
||||
}
|
||||
|
||||
private static double NormalizeTimestamp(double timeS)
|
||||
private static double NormalizeByOverflow(double value, double overfValue = 0)
|
||||
{
|
||||
double ts = timeS % TS_RANGE;
|
||||
if (ts < 0)
|
||||
ts += TS_RANGE;
|
||||
double nValue = value % overfValue;
|
||||
if (nValue < 0)
|
||||
nValue += overfValue;
|
||||
|
||||
return ts;
|
||||
return nValue;
|
||||
}
|
||||
|
||||
private static double UnwrapVolume(double currentVolume, ref double volumeRawExtLast)
|
||||
private static double UnwrapVolume(double currentVolume, double overfValue, ref double volumeRawExtLast)
|
||||
{
|
||||
double result;
|
||||
|
||||
@@ -232,16 +233,25 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
}
|
||||
else
|
||||
{
|
||||
result = currentVolume < volumeRawExtLast
|
||||
? currentVolume + VOL_RANGE
|
||||
: currentVolume;
|
||||
double lastMod = volumeRawExtLast % overfValue;
|
||||
if (lastMod < 0)
|
||||
lastMod += overfValue;
|
||||
|
||||
double delta = currentVolume - lastMod;
|
||||
|
||||
if (delta < -overfValue / 2.0)
|
||||
delta += overfValue;
|
||||
else if (delta > overfValue / 2.0)
|
||||
delta -= overfValue;
|
||||
|
||||
result = volumeRawExtLast + delta;
|
||||
}
|
||||
|
||||
volumeRawExtLast = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static double UnwrapTimestamp(double currentTimestamp, ref double timestampExtLast)
|
||||
private static double UnwrapTimestamp(double currentTimestamp,double overfValue, ref double timestampExtLast)
|
||||
{
|
||||
double result;
|
||||
|
||||
@@ -251,16 +261,16 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
}
|
||||
else
|
||||
{
|
||||
double lastMod = timestampExtLast % TS_RANGE;
|
||||
double lastMod = timestampExtLast % overfValue;
|
||||
if (lastMod < 0)
|
||||
lastMod += TS_RANGE;
|
||||
lastMod += overfValue;
|
||||
|
||||
double delta = currentTimestamp - lastMod;
|
||||
|
||||
if (delta < -TS_RANGE / 2.0)
|
||||
delta += TS_RANGE;
|
||||
else if (delta > TS_RANGE / 2.0)
|
||||
delta -= TS_RANGE;
|
||||
if (delta < -overfValue / 2.0)
|
||||
delta += overfValue;
|
||||
else if (delta > overfValue / 2.0)
|
||||
delta -= overfValue;
|
||||
|
||||
result = timestampExtLast + delta;
|
||||
}
|
||||
@@ -349,5 +359,33 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.common
|
||||
Label());
|
||||
}
|
||||
}
|
||||
|
||||
public void Copy(OptoTelegramRaw optoTelegramRaw)
|
||||
{
|
||||
this.Flags = optoTelegramRaw.Flags;
|
||||
this.DateTime = optoTelegramRaw.DateTime;
|
||||
this.RefFlow = optoTelegramRaw.RefFlow;
|
||||
this.Counter = optoTelegramRaw.Counter;
|
||||
this.EmfRaw = optoTelegramRaw.EmfRaw;
|
||||
this.MagneticFieldRaw = optoTelegramRaw.MagneticFieldRaw;
|
||||
this.FlowRaw = optoTelegramRaw.FlowRaw;
|
||||
this.VolumeRaw = optoTelegramRaw.VolumeRaw;
|
||||
this.VolumeRawExt = optoTelegramRaw.VolumeRawExt;
|
||||
this.Impedance = optoTelegramRaw.Impedance;
|
||||
this.Timestamp = optoTelegramRaw.Timestamp;
|
||||
this.TimestampExt = optoTelegramRaw.TimestampExt;
|
||||
this.CheckSum = optoTelegramRaw.CheckSum;
|
||||
this.iChannel = optoTelegramRaw.iChannel;
|
||||
}
|
||||
|
||||
public string rawDataToString()
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
return string.Format("Channel: {0}, VolumeCm:{1}, OverflowVolumeCm:{2}, TimeS: {3}, OverflowTimeS:{4} ",
|
||||
data.Channel, data.VolumeCm, data.OverflowVolumeCm, data.TimeS, data.OverflowTimeS);
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +227,20 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.communication.Utils
|
||||
return _serialPort.ReadExisting();
|
||||
}
|
||||
|
||||
public void ResetInputBuffer()
|
||||
{
|
||||
if (!IsOpen)
|
||||
throw new InvalidOperationException("Serial port not open");
|
||||
_serialPort.DiscardInBuffer();
|
||||
}
|
||||
|
||||
public void ResetOutputBuffer()
|
||||
{
|
||||
if (!IsOpen)
|
||||
throw new InvalidOperationException("Serial port not open");
|
||||
_serialPort.DiscardOutBuffer();
|
||||
}
|
||||
|
||||
public Encoding Encoding => _serialPort?.Encoding ?? _encoding;
|
||||
|
||||
public int BytesToRead => (_serialPort != null && _serialPort.IsOpen) ? _serialPort.BytesToRead : 0;
|
||||
|
||||
@@ -110,6 +110,7 @@ namespace TBF.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
Flush = 0,
|
||||
ProcessAndSave,
|
||||
CalculateStoredData,
|
||||
}
|
||||
|
||||
public enum CommunicationInterface
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -678,7 +678,8 @@ namespace TBF.Rig.Sequences
|
||||
/// On error or when STOP pressed
|
||||
///
|
||||
foreach (var fmPump in PumpsWithFM) fmPump.TurnOff();
|
||||
|
||||
log.Debug("STOP or ERROR: Pumps with FM stopped!");
|
||||
|
||||
if (inPath != null)
|
||||
{
|
||||
///
|
||||
@@ -1275,22 +1276,49 @@ namespace TBF.Rig.Sequences
|
||||
|
||||
var smryItems = DEItem.GetSummaryColumns();
|
||||
|
||||
for (int i = 0; i < BatchRslts.WMPositionsCount; i++)
|
||||
for (int i = 0; i < BatchRslts.Batch.WaterMeters.Count; i++)
|
||||
{
|
||||
if (BatchRslts.Batch.WaterMeters != null &&
|
||||
if (BatchRslts.Batch.WaterMeters != null &&
|
||||
BatchRslts.Batch.WaterMeters.Count > i &&
|
||||
BatchRslts.Batch.WaterMeters[i] != null &&
|
||||
!BatchRslts.Batch.WaterMeters[i].Disabled)
|
||||
BatchRslts.Batch.WaterMeters[i] != null)
|
||||
{
|
||||
bool Disabled = BatchRslts.Batch.WaterMeters[i].Disabled;
|
||||
bool bChanel = false;
|
||||
if (Disabled &&
|
||||
BatchRslts.Batch.WaterMeters[i].SerialNr != null &&
|
||||
BatchRslts.Batch.WaterMeters[i].SerialNr.Contains("_CH")) //write channels
|
||||
{
|
||||
Disabled = false;
|
||||
bChanel = true;
|
||||
}
|
||||
|
||||
if (Disabled)
|
||||
continue;
|
||||
|
||||
var wm = BatchRslts.Batch.WaterMeters[i];
|
||||
|
||||
if (!wm.Compound() && !wm.HeatMeter())
|
||||
{
|
||||
/// If this is a single meter
|
||||
|
||||
Results.Entities.MeterTestRslt mtrRslt = ProcessData.BatchRslts.GetMeterTestRslt(tstRslt.Name(), i, CompoundMeterId.Single);
|
||||
Results.Entities.MeterTestRslt mtrRslt = null;
|
||||
bool wmDisabled = wm.Disabled;
|
||||
try
|
||||
{
|
||||
wm.Disabled = false;
|
||||
if (!bChanel)
|
||||
mtrRslt = ProcessData.BatchRslts.GetMeterTestRslt(tstRslt.Name(), i, CompoundMeterId.Single);
|
||||
else
|
||||
{
|
||||
mtrRslt = wm.GetMeterTestRslt(tstRslt.Name(), CompoundMeterId.Single);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
finally
|
||||
{
|
||||
wm.Disabled = wmDisabled;
|
||||
}
|
||||
|
||||
if (mtrRslt != null)
|
||||
if (mtrRslt != null)
|
||||
{
|
||||
bool isCamera = (mtrRslt.RegReaderType == (int)RegisterReaderType.Camera);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ using TBF.Rig.GenericDevices;
|
||||
using TBF.Boxes;
|
||||
using TBF.Resources;
|
||||
using TBF.Rig.TestMethods.GenesisCommunication.GenesisHead;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||
using TBF.UiBridge;
|
||||
|
||||
namespace TBF.Rig.TestMethods.FlyingStart
|
||||
@@ -329,6 +330,9 @@ namespace TBF.Rig.TestMethods.FlyingStart
|
||||
|
||||
temperature_set:
|
||||
|
||||
|
||||
|
||||
|
||||
//TODO genesis - check with genesis switch
|
||||
if (atleastOneGenesis)
|
||||
{
|
||||
@@ -379,18 +383,26 @@ namespace TBF.Rig.TestMethods.FlyingStart
|
||||
IList<IOperation> cameraMeasurementOps = new List<IOperation>();
|
||||
foreach (var camera in cameras) cameraMeasurementOps.Add(camera.MeasurementOp());
|
||||
|
||||
foreach (var rr in sensPath.RegisterReaders)
|
||||
{
|
||||
if (rr is IRegReaderDatastream)
|
||||
(rr as IRegReaderDatastream).TestIsGoingToStartSoon(test, repetitionNr);
|
||||
|
||||
if (rr is GenesisHead) // Genesis - CORDONEL head
|
||||
(rr as GenesisHead).StartRead(test.Name, BatchRslts.Batch.BatchNr, repetitionNr);
|
||||
|
||||
}
|
||||
/// Prepare datastream read operations
|
||||
IList<IOperation> readDatastreamOps = new List<IOperation>();
|
||||
if (sensPath != null && sensPath.RegisterReaders != null)
|
||||
{
|
||||
foreach (var rr in sensPath.RegisterReaders)
|
||||
{
|
||||
if (rr is IRegReaderDatastream datastreamRR)
|
||||
{
|
||||
(datastreamRR).TestIsGoingToStartSoon(test, repetitionNr);
|
||||
readDatastreamOps.Add(datastreamRR.ReadDatastreamOp());
|
||||
}
|
||||
|
||||
if (rr is GenesisHead) // Genesis - CORDONEL head
|
||||
(rr as GenesisHead).StartRead(test.Name, BatchRslts.Batch.BatchNr, repetitionNr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
//------------------------------------------------
|
||||
Bridge.OnActivity(this, Strings.Test_in_progress);
|
||||
//------------------------------------------------
|
||||
|
||||
@@ -403,6 +415,7 @@ namespace TBF.Rig.TestMethods.FlyingStart
|
||||
State.Create(string.Format("{0}({1}) : FlyingStartStopTestOp is running", test.Method, test.Name))
|
||||
.AddOperation(checkUiOp)
|
||||
.AddOperations(readTempPressOps)
|
||||
.AddOperations(readDatastreamOps)
|
||||
.AddOperations(cameraMeasurementOps)
|
||||
.AddOperation(cBrd.FlyingStartStopTestOp(test, test.QfromM3ph(), test.QtoM3ph(), totalPulses))
|
||||
.AddOperation(processDataLoggingOp)
|
||||
@@ -454,6 +467,21 @@ namespace TBF.Rig.TestMethods.FlyingStart
|
||||
|
||||
/// Measurement loop end
|
||||
StopRecordingStatistics();
|
||||
|
||||
/// call StopDataStreamProcessing
|
||||
if (sensPath != null && sensPath.RegisterReaders != null)
|
||||
{
|
||||
foreach (var rr in sensPath.RegisterReaders)
|
||||
{
|
||||
var datastreamRR = rr as ISmartReader;
|
||||
if (datastreamRR != null)
|
||||
{
|
||||
datastreamRR.StopDataStreamProcessing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO genesis - check with genesis switch
|
||||
if (atleastOneGenesis)
|
||||
|
||||
@@ -8,11 +8,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml.Serialization;
|
||||
using Results.Entities;
|
||||
using TBF.Boxes;
|
||||
using TBF.Resources;
|
||||
using TBF.Rig;
|
||||
using TBF.Rig.GenericDevices;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
using TBF.Rig.RegisterReaders.PoseidonReader;
|
||||
using TBF.Rig.RegisterReaders.PoseidonReader.implementations;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||
@@ -170,8 +173,8 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
string testName = Results.Utils.GetTestName(test.Name, test.Repeats, repetitionNr);
|
||||
TestStartTime = DateTime.Now;
|
||||
|
||||
bool atleastOneGenesis = false;
|
||||
atleastOneGenesis = GenesisHeadBatch.Start(sensPath.RegisterReaders, Program.LocalSettings.LastSNTexts);
|
||||
// bool atleastOneGenesis = false;
|
||||
// atleastOneGenesis = GenesisHeadBatch.Start(sensPath.RegisterReaders, Program.LocalSettings.LastSNTexts);
|
||||
|
||||
//------------------------------------------------
|
||||
Bridge.OnActivity(this, Strings.Checking_tank_capacity);
|
||||
@@ -452,23 +455,23 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
}
|
||||
}
|
||||
|
||||
if (atleastOneGenesis)
|
||||
{
|
||||
log.Info($"Genesis - Starting... Test Name:{test.Name.ToLower()}.");
|
||||
if (test.Name.ToLower().Contains("calib"))
|
||||
{
|
||||
log.Info("Genesis - Calibration starting.");
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersLogin();
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersInitCalibration();
|
||||
|
||||
}
|
||||
if (test.Name.ToLower().Contains("init"))
|
||||
{
|
||||
log.Info("Genesis - init starting.");
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersLogin();
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersInitMeasurement();
|
||||
}
|
||||
}
|
||||
// if (atleastOneGenesis)
|
||||
// {
|
||||
// log.Info($"Genesis - Starting... Test Name:{test.Name.ToLower()}.");
|
||||
// if (test.Name.ToLower().Contains("calib"))
|
||||
// {
|
||||
// log.Info("Genesis - Calibration starting.");
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersLogin();
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersInitCalibration();
|
||||
//
|
||||
// }
|
||||
// if (test.Name.ToLower().Contains("init"))
|
||||
// {
|
||||
// log.Info("Genesis - init starting.");
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersLogin();
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersInitMeasurement();
|
||||
// }
|
||||
// }
|
||||
|
||||
if (drainTheTank)
|
||||
{
|
||||
@@ -607,22 +610,40 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
}
|
||||
while (!e.Contains(Event.TestCompleted) && !e.Contains(Event.Next)); /// 'Next' button is enabled in Debug version only
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------
|
||||
Bridge.OnActivity(this, Strings.Test_in_calculation);
|
||||
//------------------------------------------------
|
||||
/// Measurement loop end
|
||||
StopRecordingStatistics();
|
||||
|
||||
if (atleastOneGenesis)
|
||||
{
|
||||
if (test.Name.ToLower().Contains("calib"))
|
||||
{
|
||||
log.Info("Genesis - Calibration stopped.");
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersStopCalibration();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Info("Genesis - Init measurement stopped.");
|
||||
GenesisHeadBatch.BatchHolder.Value.MetersStopMeasurement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sensPath != null && sensPath.RegisterReaders != null)
|
||||
{
|
||||
foreach (var rr in sensPath.RegisterReaders)
|
||||
{
|
||||
var datastreamRR = rr as ISmartReader;
|
||||
if (datastreamRR != null)
|
||||
{
|
||||
datastreamRR.StopDataStreamProcessing();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (atleastOneGenesis)
|
||||
// {
|
||||
// if (test.Name.ToLower().Contains("calib"))
|
||||
// {
|
||||
// log.Info("Genesis - Calibration stopped.");
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersStopCalibration();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// log.Info("Genesis - Init measurement stopped.");
|
||||
// GenesisHeadBatch.BatchHolder.Value.MetersStopMeasurement();
|
||||
// }
|
||||
// }
|
||||
|
||||
///
|
||||
/// (Berlin:) Water is stopped immediately after the test and before the 2nd mass measurement in case:
|
||||
@@ -955,6 +976,7 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bUpgradeCountOfMeters = false;
|
||||
///
|
||||
/// Single meters
|
||||
///
|
||||
@@ -969,6 +991,7 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
TestMethods.iPerlCommunication.iPerlHead.IperlHead iPerl = regReader as TestMethods.iPerlCommunication.iPerlHead.IperlHead;
|
||||
GenericDevices.IRegReaderLiveCamera cameraRoi = regReader as GenericDevices.IRegReaderLiveCamera;
|
||||
TestMethods.GenesisCommunication.GenesisHead.GenesisHead Genesis = regReader as TestMethods.GenesisCommunication.GenesisHead.GenesisHead;
|
||||
TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader GenesisSmart = regReader as TBF.Rig.RegisterReaders.GenesisRegReader.implementations.GenesisSmartReader;
|
||||
|
||||
if (meterRslt != null && regReader != null)
|
||||
{
|
||||
@@ -1057,6 +1080,23 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
var calError = Formulas.ErrorFromVolumes(meterRslt.VolumeMeter, meterRslt.VolumeRef);
|
||||
Genesis.Log(" MeterError = " + calError.ToString() + " %");
|
||||
|
||||
}
|
||||
else if (GenesisSmart != null)
|
||||
{
|
||||
log.Debug("GenesisSmart - store data on end!");
|
||||
bUpgradeCountOfMeters = true;
|
||||
int CH1=0, CH2=1, CH3=2;
|
||||
|
||||
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH1 + 1]
|
||||
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH2 + 1]
|
||||
//BatchRslts.Batch.WaterMeters.Add(ch1WaterMeter); //[i + BatchRslts.WMPositionsCount + CH3 + 1]
|
||||
|
||||
CalculateMeterResults(meterRslt, GenesisSmart, tstRslt,GenesisSmart.TimestampSecStart, GenesisSmart.TimestampSecEnd, GenesisSmart.VolumeLtrStart, GenesisSmart.VolumeLtrEnd);
|
||||
|
||||
WaterMeterParentCopy(i, CH1,testName,meterRslt,GenesisSmart,tstRslt);
|
||||
WaterMeterParentCopy(i, CH2,testName,meterRslt,GenesisSmart,tstRslt);
|
||||
WaterMeterParentCopy(i, CH3,testName,meterRslt,GenesisSmart,tstRslt);
|
||||
|
||||
}
|
||||
else if (dstrReader != null)
|
||||
{
|
||||
@@ -1241,7 +1281,15 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (bUpgradeCountOfMeters)
|
||||
{
|
||||
//TODO remove test!!
|
||||
//BatchRslts.WMPositionsCount = BatchRslts.WMPositionsCount + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
tstRslt.Components = Results.Entities.Components.UpdateList(BatchRslts.ComponentsList,
|
||||
new Results.Entities.Components((BenchInfo != null) ? BenchInfo.TestBenchId : 1,
|
||||
@@ -1300,6 +1348,98 @@ namespace TBF.Rig.TestMethods.FlyingStartMassCollection
|
||||
return new List<Event> { retVal };
|
||||
}
|
||||
|
||||
private const int CountCh = 3;
|
||||
private static void WaterMeterParentCopy(int i, int iCH, string testName, MeterTestRslt meterRslt,
|
||||
GenesisSmartReader genesisSmart,
|
||||
TestRslt tstRslt)
|
||||
{
|
||||
WaterMeter waterMeterParent = BatchRslts.Batch.WaterMeters[i];
|
||||
int wmNrChX = (i*CountCh) + BatchRslts.WMPositionsCount + iCH + 1;
|
||||
String sSerialNr = waterMeterParent.SerialNr + "_CH" + (iCH + 1);
|
||||
WaterMeter chXWaterMeter = null;
|
||||
//------ add new water meter to batch ------
|
||||
if (BatchRslts.Batch.WaterMeters.Count < wmNrChX || BatchRslts.Batch.WaterMeters[wmNrChX-1] == null)
|
||||
{
|
||||
log.Debug("add new water meter to batch, CH = " + (iCH + 1) + " CH = " + wmNrChX);
|
||||
chXWaterMeter = new WaterMeter()
|
||||
{
|
||||
Batch = BatchRslts.Batch,
|
||||
WaterMeterData = waterMeterParent.WaterMeterData,
|
||||
MeterTestRslts = new List<MeterTestRslt>(),
|
||||
SerialNr = sSerialNr,
|
||||
WMPosition = wmNrChX,
|
||||
YearOfProduction = 0,
|
||||
Disabled = false,
|
||||
};
|
||||
chXWaterMeter.CopyContentFrom(waterMeterParent);
|
||||
|
||||
chXWaterMeter.SerialNr = sSerialNr;
|
||||
chXWaterMeter.WMPosition = wmNrChX;
|
||||
chXWaterMeter.YearOfProduction = waterMeterParent.YearOfProduction;
|
||||
chXWaterMeter.Disabled = false;
|
||||
|
||||
BatchRslts.Batch.WaterMeters.Add(chXWaterMeter);
|
||||
}
|
||||
else
|
||||
{
|
||||
chXWaterMeter = BatchRslts.Batch.WaterMeters[wmNrChX-1];
|
||||
}
|
||||
//~------ add new water meter to batch ------~
|
||||
|
||||
//create copy of meterRslt and add to additionalResultsByChannel
|
||||
MeterTestRslt meterTestRsltChX = new MeterTestRslt(chXWaterMeter, meterRslt.TestRslt, (CompoundMeterId)meterRslt.CompoundMeterId);
|
||||
chXWaterMeter.MeterTestRslts.Add(meterTestRsltChX);
|
||||
MeterTestRslt chanelXMeterRslt = BatchRslts.GetMeterTestRslt(testName, wmNrChX-1, Common.CompoundMeterId.Single);
|
||||
|
||||
if (chanelXMeterRslt != null)
|
||||
{
|
||||
chanelXMeterRslt?.CopyContentFrom(meterRslt);
|
||||
if (iCH == 0)
|
||||
{
|
||||
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartCh1,
|
||||
genesisSmart.TimestampSecEndCh1, genesisSmart.VolumeLtrStartCh1, genesisSmart.VolumeLtrEndCh1);
|
||||
}
|
||||
else if (iCH == 1)
|
||||
{
|
||||
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartCh2,
|
||||
genesisSmart.TimestampSecEndCh2, genesisSmart.VolumeLtrStartCh2, genesisSmart.VolumeLtrEndCh2);
|
||||
}
|
||||
else if (iCH == 2)
|
||||
{
|
||||
CalculateMeterResults(chanelXMeterRslt, genesisSmart, tstRslt, genesisSmart.TimestampSecStartCh3,
|
||||
genesisSmart.TimestampSecEndCh3, genesisSmart.VolumeLtrStartCh3, genesisSmart.VolumeLtrEndCh3);
|
||||
}
|
||||
|
||||
if (!genesisSmart.EnableShowChanels)
|
||||
{
|
||||
chXWaterMeter.Disabled = !genesisSmart.EnableShowChanels;
|
||||
meterTestRsltChX.TestDone = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
meterTestRsltChX.TestDone = true;
|
||||
}
|
||||
|
||||
meterTestRsltChX.Passed = meterRslt.Passed;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CalculateMeterResults(MeterTestRslt meterRslt, IRegReaderDatastream dstrReader, TestRslt tstRslt, double dstrReaderTimestampSecStart, double dstrReaderTimestampSecEnd, double dstrReaderVolumeLtrStart, double dstrReaderVolumeLtrEnd)
|
||||
{
|
||||
meterRslt.TimestampStart = dstrReaderTimestampSecStart;
|
||||
meterRslt.TimestampEnd = !dstrReader.NoSamples
|
||||
? dstrReaderTimestampSecEnd
|
||||
: (dstrReaderTimestampSecStart + tstRslt.TestTime);
|
||||
meterRslt.TestTime = meterRslt.TimestampEnd - meterRslt.TimestampStart;
|
||||
meterRslt.VolumeStart = dstrReaderVolumeLtrStart; /// liter
|
||||
meterRslt.VolumeEnd = dstrReaderVolumeLtrEnd; /// liter
|
||||
meterRslt.VolumeMeter =
|
||||
Math.Abs(dstrReaderVolumeLtrEnd - dstrReaderVolumeLtrStart);
|
||||
meterRslt.VolumeRef = tstRslt.TestTime==0? tstRslt.VolumeCTV : tstRslt.VolumeCTV * meterRslt.TestTime / tstRslt.TestTime;
|
||||
meterRslt.PulsesMaster = tstRslt.TestTime == 0? tstRslt.PulsesMaster :
|
||||
tstRslt.PulsesMaster * meterRslt.TestTime / tstRslt.TestTime;
|
||||
}
|
||||
|
||||
|
||||
IList<Event> Simulate1(Config.Entities.Test test, int repetitionNr, bool isLastRepetition,
|
||||
Compound.CombinedTestParams compoundTestParams,
|
||||
|
||||
@@ -15,8 +15,7 @@ using Xylem.Common.Metrology.Measurements;
|
||||
using Xylem.Common.Metrology.Measurements.Consts;
|
||||
using Common;
|
||||
using System.IO.Ports;
|
||||
using GenesisMeter = TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis.GenesisCore.GenesisMeter;
|
||||
using MeterBatch = TBF.Rig.RegisterReaders.GenesisRegReader.communication.Genesis.WaterMeterCore.MeterBatch;
|
||||
|
||||
|
||||
namespace TBF.Rig.TestMethods.GenesisCommunication.GenesisHead
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
///
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Common;
|
||||
using log4net;
|
||||
using Config.Entities;
|
||||
using TBF.Rig.ControlBoard.Uni;
|
||||
@@ -200,6 +201,11 @@ namespace TBF.Rig.Uni.RegValve
|
||||
public Event Run()
|
||||
{
|
||||
log.DebugFormat("Op.Run() opState={0}", opState);
|
||||
|
||||
if (this.uniCB?.DebugLevel == DebugMode.Simulate)
|
||||
{
|
||||
return Event.FlowReached;
|
||||
}
|
||||
|
||||
if (StateMachine.Time > expireTime) return Event.RegulValveTimeOut;
|
||||
|
||||
|
||||
@@ -1293,6 +1293,7 @@
|
||||
<Compile Include="Rig\RegisterReaders\DataStream\Reader\ReaderCfg.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\common\HexFormatter.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\common\OptoTelegramRaw.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\ChannelAverages.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\Genesis\Crc16Ccitt.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\Genesis\DataPackages\EventArguments\BaseDataEventArgs.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\communication\Genesis\DataPackages\EventArguments\BendDetectDataEventArgs.cs" />
|
||||
|
||||
@@ -12,13 +12,17 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.common
|
||||
private static CalibrationRecord CreateCalibrationRecord(
|
||||
int channel = 1,
|
||||
double volumeCm = 1.234,
|
||||
double timeS = 12.5)
|
||||
double overflowVolumeCm = 8.38860799804687,
|
||||
double timeS = 12.5,
|
||||
double overflowTimeS = 65536.0)
|
||||
{
|
||||
return new CalibrationRecord
|
||||
{
|
||||
Channel = channel,
|
||||
VolumeCm = volumeCm,
|
||||
TimeS = timeS
|
||||
OverflowVolumeCm = overflowVolumeCm,
|
||||
TimeS = timeS,
|
||||
OverflowTimeS = overflowTimeS
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +30,12 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.common
|
||||
public void UpdateFromSmart_FirstSample_ShouldInitializeFields()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
var data = CreateCalibrationRecord(channel: 2, volumeCm: 2.5, timeS: 100.0);
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 2,
|
||||
volumeCm: 2.5,
|
||||
overflowVolumeCm: 8.38860799804687,
|
||||
timeS: 100.0,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
double lastVolume = double.NaN;
|
||||
double lastTimestamp = double.NaN;
|
||||
@@ -54,32 +63,479 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.common
|
||||
Assert.AreEqual(0, telegram.MagneticFieldRaw);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_RealGenesisDecodedSample_ShouldMapExpectedValues()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 2,
|
||||
volumeCm: 0.48025591796875,
|
||||
overflowVolumeCm: 8.38860799804687,
|
||||
timeS: 62727.8408813477,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
double lastVolume = double.NaN;
|
||||
double lastTimestamp = double.NaN;
|
||||
|
||||
telegram.UpdateFromSmart(data, counter: 1, refFlow: 0.0f, ref lastVolume, ref lastTimestamp);
|
||||
|
||||
Assert.AreEqual(1, telegram.IChannel());
|
||||
Assert.AreEqual(1, telegram.Counter);
|
||||
Assert.AreEqual(0.0f, telegram.RefFlow);
|
||||
Assert.AreEqual(OptoTelegramFlags.OK, telegram.Flags);
|
||||
|
||||
Assert.AreEqual(480.25591796875, telegram.VolumeRaw, 1e-9);
|
||||
Assert.AreEqual(480.25591796875, telegram.VolumeRawExt, 1e-9);
|
||||
Assert.AreEqual(480.25591796875, lastVolume, 1e-9);
|
||||
|
||||
Assert.AreEqual(62727.8408813477, telegram.Timestamp, 1e-9);
|
||||
Assert.AreEqual(62727.8408813477, telegram.TimestampExt, 1e-9);
|
||||
Assert.AreEqual(62727.8408813477, lastTimestamp, 1e-9);
|
||||
|
||||
Assert.AreEqual(0, telegram.FlowRaw);
|
||||
Assert.AreEqual(0, telegram.CheckSum);
|
||||
Assert.AreEqual(0, telegram.Impedance);
|
||||
Assert.AreEqual(0, telegram.EmfRaw);
|
||||
Assert.AreEqual(0, telegram.MagneticFieldRaw);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_WhenVolumeDecreases_ShouldApplyVolumeRollover()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
var data = CreateCalibrationRecord(channel: 1, volumeCm: 1.0, timeS: 10.0);
|
||||
var overflowVolumeCm = 8.38860799804687;
|
||||
var overflowRaw = overflowVolumeCm * 1000.0;
|
||||
|
||||
double previousExtendedVolume = 5000.0;
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: 1.0,
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: 10.0,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
// Must be close enough to overflow so that current=1000 is interpreted as a wrap
|
||||
double previousExtendedVolume = 8000.0;
|
||||
double previousExtendedTimestamp = 10.0;
|
||||
|
||||
telegram.UpdateFromSmart(data, counter: 1, refFlow: 0.5f, ref previousExtendedVolume, ref previousExtendedTimestamp);
|
||||
telegram.UpdateFromSmart(
|
||||
data,
|
||||
counter: 1,
|
||||
refFlow: 0.5f,
|
||||
ref previousExtendedVolume,
|
||||
ref previousExtendedTimestamp);
|
||||
|
||||
double expectedVolumeRaw = 1000.0;
|
||||
double expectedExtended = expectedVolumeRaw + StreamingDecoder.DefaultAccuDutOverflowVolumeCm * 1000.0;
|
||||
double expectedExtended = expectedVolumeRaw + overflowRaw;
|
||||
|
||||
Assert.AreEqual(expectedVolumeRaw, telegram.VolumeRaw, 1e-9);
|
||||
Assert.AreEqual(expectedExtended, telegram.VolumeRawExt, 1e-6);
|
||||
Assert.AreEqual(expectedExtended, previousExtendedVolume, 1e-6);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleVolumeRollover_ShouldKeepIncreasingExtendedVolume()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double overflowVolumeCm = 8.38860799804687;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
// Safe sequence: small forward steps, natural wrap, small forward steps
|
||||
double[] samples =
|
||||
{
|
||||
7.5,
|
||||
8.0,
|
||||
0.2,
|
||||
1.0,
|
||||
1.8,
|
||||
2.6,
|
||||
3.4,
|
||||
4.2,
|
||||
5.0,
|
||||
5.8,
|
||||
6.6,
|
||||
7.4,
|
||||
8.1,
|
||||
0.3,
|
||||
1.1
|
||||
};
|
||||
|
||||
double previousExt = double.NaN;
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: samples[i],
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: i,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
double expectedRaw = samples[i] * 1000.0;
|
||||
Assert.AreEqual(expectedRaw, telegram.VolumeRaw, 1e-9, $"Raw mismatch at index {i}");
|
||||
|
||||
if (!double.IsNaN(previousExt))
|
||||
{
|
||||
Assert.IsTrue(
|
||||
telegram.VolumeRawExt >= previousExt,
|
||||
$"Volume should not decrease at index {i}. Prev={previousExt}, Current={telegram.VolumeRawExt}");
|
||||
}
|
||||
|
||||
previousExt = telegram.VolumeRawExt;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleVolumeRollover_FirstToLastDeltaShouldBePositive()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double overflowVolumeCm = 8.38860799804687;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
double[] samples =
|
||||
{
|
||||
7.5, 8.0, 0.2, 1.0, 1.8, 2.6, 3.4, 4.2, 5.0, 5.8, 6.6, 7.4, 8.1, 0.3, 1.1
|
||||
};
|
||||
|
||||
double firstExt = double.NaN;
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: samples[i],
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: i,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
if (i == 0)
|
||||
firstExt = telegram.VolumeRawExt;
|
||||
}
|
||||
|
||||
Assert.IsTrue(lastVolumeExt > firstExt,
|
||||
$"Volume should increase from first to last. First={firstExt}, Last={lastVolumeExt}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleVolumeRollover_ShouldMatchPhysicalDelta()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double overflowVolumeCm = 8.38860799804687;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
double[] samples =
|
||||
{
|
||||
7.5,
|
||||
8.0,
|
||||
0.2,
|
||||
1.0,
|
||||
1.8,
|
||||
2.6,
|
||||
3.4,
|
||||
4.2,
|
||||
5.0,
|
||||
5.8,
|
||||
6.6,
|
||||
7.4,
|
||||
8.1,
|
||||
0.3,
|
||||
1.1
|
||||
};
|
||||
|
||||
double firstExt = double.NaN;
|
||||
double lastExt = double.NaN;
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: samples[i],
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: i,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
if (i == 0)
|
||||
firstExt = telegram.VolumeRawExt;
|
||||
|
||||
if (i == samples.Length - 1)
|
||||
lastExt = telegram.VolumeRawExt;
|
||||
}
|
||||
|
||||
double start = samples[0];
|
||||
double end = samples[samples.Length - 1];
|
||||
|
||||
int wraps = 0;
|
||||
for (int i = 1; i < samples.Length; i++)
|
||||
{
|
||||
if (samples[i] < samples[i - 1])
|
||||
wraps++;
|
||||
}
|
||||
|
||||
double expectedDeltaCm = wraps * overflowVolumeCm + end - start;
|
||||
double expectedDeltaRaw = expectedDeltaCm * 1000.0;
|
||||
double actualDeltaRaw = lastExt - firstExt;
|
||||
|
||||
Assert.AreEqual(
|
||||
expectedDeltaRaw,
|
||||
actualDeltaRaw,
|
||||
1e-6,
|
||||
$"Delta mismatch. Wraps={wraps}, Expected={expectedDeltaRaw}, Actual={actualDeltaRaw}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleTimestampWrap_ShouldMatchPhysicalDelta()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
|
||||
double overflowTimeS = 65536.0;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
// Safe sequence: small forward steps, natural wrap, small forward steps, second wrap
|
||||
double[] times =
|
||||
{
|
||||
65530.0,
|
||||
65535.0,
|
||||
2.0, // wrap 1
|
||||
10.0,
|
||||
100.0,
|
||||
1000.0,
|
||||
10000.0,
|
||||
30000.0,
|
||||
50000.0,
|
||||
65534.0,
|
||||
3.0, // wrap 2
|
||||
20.0
|
||||
};
|
||||
|
||||
double firstExt = double.NaN;
|
||||
double lastExt = double.NaN;
|
||||
|
||||
for (int i = 0; i < times.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: 1.0,
|
||||
overflowVolumeCm: 8.38860799804687,
|
||||
timeS: times[i],
|
||||
overflowTimeS: overflowTimeS);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
if (i == 0)
|
||||
firstExt = telegram.TimestampExt;
|
||||
|
||||
if (i == times.Length - 1)
|
||||
lastExt = telegram.TimestampExt;
|
||||
}
|
||||
|
||||
double start = times[0];
|
||||
double end = times[times.Length - 1];
|
||||
|
||||
int wraps = 0;
|
||||
for (int i = 1; i < times.Length; i++)
|
||||
{
|
||||
if (times[i] < times[i - 1])
|
||||
wraps++;
|
||||
}
|
||||
|
||||
double expectedDelta = wraps * overflowTimeS + end - start;
|
||||
double actualDelta = lastExt - firstExt;
|
||||
|
||||
Assert.AreEqual(
|
||||
expectedDelta,
|
||||
actualDelta,
|
||||
1e-6,
|
||||
$"Timestamp delta mismatch. Wraps={wraps}, Expected={expectedDelta}, Actual={actualDelta}");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleTimestampWrap_ShouldKeepIncreasingExtendedTimestamp()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
|
||||
double overflowTimeS = 65536.0;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
double[] times =
|
||||
{
|
||||
65530.0,
|
||||
65535.0,
|
||||
2.0,
|
||||
10.0,
|
||||
100.0,
|
||||
1000.0,
|
||||
10000.0,
|
||||
30000.0,
|
||||
50000.0,
|
||||
65534.0,
|
||||
3.0,
|
||||
20.0
|
||||
};
|
||||
|
||||
double previousExt = double.NaN;
|
||||
|
||||
for (int i = 0; i < times.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: 1.0,
|
||||
overflowVolumeCm: 8.38860799804687,
|
||||
timeS: times[i],
|
||||
overflowTimeS: overflowTimeS);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
if (!double.IsNaN(previousExt))
|
||||
{
|
||||
Assert.IsTrue(
|
||||
telegram.TimestampExt >= previousExt,
|
||||
$"Timestamp should not decrease at index {i}. Prev={previousExt}, Current={telegram.TimestampExt}");
|
||||
}
|
||||
|
||||
previousExt = telegram.TimestampExt;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_MultipleVolumeRollover_ShouldProduceExpectedExtendedValues()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double overflowVolumeCm = 8.38860799804687;
|
||||
double overflowRaw = overflowVolumeCm * 1000.0;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
double[] samples =
|
||||
{
|
||||
7.5,
|
||||
8.0,
|
||||
0.2,
|
||||
0.8,
|
||||
1.4
|
||||
};
|
||||
|
||||
double[] expectedExt =
|
||||
{
|
||||
7500.0,
|
||||
8000.0,
|
||||
200.0 + overflowRaw,
|
||||
800.0 + overflowRaw,
|
||||
1400.0 + overflowRaw
|
||||
};
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: samples[i],
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: i,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
Assert.AreEqual(samples[i] * 1000.0, telegram.VolumeRaw, 1e-9, $"Raw mismatch at index {i}");
|
||||
Assert.AreEqual(expectedExt[i], telegram.VolumeRawExt, 1e-6, $"Mismatch at index {i}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_TwoVolumeRollovers_ShouldKeepExtendedVolumeIncreasing()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double overflowVolumeCm = 8.38860799804687;
|
||||
double overflowRaw = overflowVolumeCm * 1000.0;
|
||||
|
||||
double lastVolumeExt = double.NaN;
|
||||
double lastTimestampExt = double.NaN;
|
||||
|
||||
double[] samples =
|
||||
{
|
||||
6.8,
|
||||
8.1,
|
||||
0.3,
|
||||
1.2,
|
||||
2.1,
|
||||
3.0,
|
||||
4.0,
|
||||
7.5,
|
||||
8.1,
|
||||
0.4,
|
||||
1.1
|
||||
};
|
||||
|
||||
double[] expectedExt =
|
||||
{
|
||||
6800.0,
|
||||
8100.0,
|
||||
overflowRaw + 300.0,
|
||||
overflowRaw + 1200.0,
|
||||
overflowRaw + 2100.0,
|
||||
overflowRaw + 3000.0,
|
||||
overflowRaw + 4000.0,
|
||||
overflowRaw + 7500.0,
|
||||
overflowRaw + 8100.0,
|
||||
2.0 * overflowRaw + 400.0,
|
||||
2.0 * overflowRaw + 1100.0
|
||||
};
|
||||
|
||||
double previous = double.NaN;
|
||||
|
||||
for (int i = 0; i < samples.Length; i++)
|
||||
{
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: samples[i],
|
||||
overflowVolumeCm: overflowVolumeCm,
|
||||
timeS: i,
|
||||
overflowTimeS: 65536.0);
|
||||
|
||||
telegram.UpdateFromSmart(data, i, 0, ref lastVolumeExt, ref lastTimestampExt);
|
||||
|
||||
Assert.AreEqual(samples[i] * 1000.0, telegram.VolumeRaw, 1e-9, $"Raw mismatch at index {i}");
|
||||
Assert.AreEqual(expectedExt[i], telegram.VolumeRawExt, 1e-6, $"Mismatch at index {i}");
|
||||
|
||||
if (!double.IsNaN(previous))
|
||||
{
|
||||
Assert.IsTrue(
|
||||
telegram.VolumeRawExt > previous,
|
||||
$"Extended volume did not increase at index {i}. Prev={previous}, Current={telegram.VolumeRawExt}");
|
||||
}
|
||||
|
||||
previous = telegram.VolumeRawExt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateFromSmart_WhenTimestampWraps_ShouldUnwrapForward()
|
||||
{
|
||||
var telegram = new OptoTelegramRaw();
|
||||
double tsRange = StreamingDecoder.CpuTimeOverflowS;
|
||||
|
||||
var data = CreateCalibrationRecord(channel: 1, volumeCm: 1.0, timeS: 1.0);
|
||||
var data = CreateCalibrationRecord(
|
||||
channel: 1,
|
||||
volumeCm: 1.0,
|
||||
overflowVolumeCm: 8.38860799804687,
|
||||
timeS: 1.0,
|
||||
overflowTimeS: tsRange);
|
||||
|
||||
double previousExtendedVolume = 1000.0;
|
||||
double previousExtendedTimestamp = tsRange - 0.25;
|
||||
|
||||
@@ -16,10 +16,11 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
public int CloseCalls { get; private set; }
|
||||
public int DiscardInCalls { get; private set; }
|
||||
public int DiscardOutCalls { get; private set; }
|
||||
|
||||
|
||||
public Encoding Encoding { get; set; } = Encoding.ASCII;
|
||||
|
||||
public int BytesToRead => _lines.Count > 0 ? 1 : 0;
|
||||
public int BytesToRead => _isOpen && _lines.Count > 0 ? 1 : 0;
|
||||
public int BytesToWrite => 0;
|
||||
|
||||
public void EnqueueLine(string line) => _lines.Enqueue(line);
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.communication;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
using TBF.Rig.Sequences;
|
||||
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
[TestClass]
|
||||
public class GenesisReaderTests
|
||||
{
|
||||
|
||||
[TestMethod]
|
||||
public void Debug_ProcessOptoLine_FormatVariants()
|
||||
{
|
||||
var reader = new GenesisSmartReader();
|
||||
InitializeReaderForTest(reader);
|
||||
|
||||
string[] variants =
|
||||
{
|
||||
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
"@he 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
"@he\t1\t0\t0A1F59C4\t00017A43\t00115C45\t72E1596B\t00000400\t00001998\t7D91B652\t7D4F37E6\t000191E6\t0C\t062E4A9C\t5331",
|
||||
"@he \t1\t0\t0A1F59C4\t00017A43\t00115C45\t72E1596B\t00000400\t00001998\t7D91B652\t7D4F37E6\t000191E6\t0C\t062E4A9C\t5331"
|
||||
};
|
||||
|
||||
for (int i = 0; i < variants.Length; i++)
|
||||
{
|
||||
bool blockCompleted = false;
|
||||
reader.ProcessOptoLine(variants[i], DataStreamState.ProcessAndSave, out blockCompleted);
|
||||
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Console.WriteLine($"Variant {i}: {variants[i]}");
|
||||
Console.WriteLine($" blockCompleted={blockCompleted}");
|
||||
Console.WriteLine($" optoDataCount={optoDataCount}");
|
||||
Console.WriteLine("--------------------------------");
|
||||
}
|
||||
|
||||
Assert.Fail("Inspect which variant, if any, is accepted.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RealInput_ShouldCalculate_StartEndVolumes_AndTimes()
|
||||
{
|
||||
var reader = new GenesisSmartReader();
|
||||
InitializeReaderForTest(reader);
|
||||
|
||||
string[] realInputLines = LoadRealInputLines();
|
||||
Assert.IsTrue(realInputLines.Length > 0, "No test input lines were provided.");
|
||||
|
||||
int processedCount = 0;
|
||||
int firstValidIx = -1;
|
||||
int lastValidIx = -1;
|
||||
|
||||
Console.WriteLine("=== BEGIN INPUT PARSING ===");
|
||||
|
||||
for (int i = 0; i < realInputLines.Length; i++)
|
||||
{
|
||||
string line = realInputLines[i];
|
||||
|
||||
bool blockCompleted = false;
|
||||
Exception parseException = null;
|
||||
|
||||
try
|
||||
{
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out blockCompleted);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
parseException = ex;
|
||||
}
|
||||
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Console.WriteLine($"[{i}] line = {line}");
|
||||
Console.WriteLine($"[{i}] blockCompleted = {blockCompleted}");
|
||||
Console.WriteLine($"[{i}] optoDataCount = {optoDataCount}");
|
||||
|
||||
if (parseException != null)
|
||||
{
|
||||
Console.WriteLine($"[{i}] EXCEPTION = {parseException.GetType().Name}: {parseException.Message}");
|
||||
}
|
||||
|
||||
if (optoDataCount > processedCount)
|
||||
{
|
||||
if (firstValidIx < 0)
|
||||
firstValidIx = processedCount;
|
||||
|
||||
lastValidIx = optoDataCount - 1;
|
||||
processedCount = optoDataCount;
|
||||
|
||||
Console.WriteLine(
|
||||
$"[{i}] ACCEPTED -> processedCount={processedCount}, firstValidIx={firstValidIx}, lastValidIx={lastValidIx}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[{i}] NOT ACCEPTED");
|
||||
}
|
||||
|
||||
Console.WriteLine("--------------------------------------------------");
|
||||
}
|
||||
|
||||
Console.WriteLine("=== END INPUT PARSING ===");
|
||||
Console.WriteLine($"Final processedCount = {processedCount}");
|
||||
Console.WriteLine($"Final firstValidIx = {firstValidIx}");
|
||||
Console.WriteLine($"Final lastValidIx = {lastValidIx}");
|
||||
|
||||
if (processedCount <= 0)
|
||||
{
|
||||
Assert.Fail(
|
||||
"No valid calibration telegrams were parsed.\n" +
|
||||
"Check the following:\n" +
|
||||
"1. exact telegram prefix (for example @h vs @he)\n" +
|
||||
"2. exact separators (spaces vs tabs)\n" +
|
||||
"3. exact CRC / checksum\n" +
|
||||
"4. whether ProcessOptoLine expects a complete multi-line block format\n" +
|
||||
"See test output for per-line diagnostics.");
|
||||
}
|
||||
|
||||
reader.TestStartTelegramIx = firstValidIx;
|
||||
reader.TestEndTelegramIx = lastValidIx;
|
||||
|
||||
Console.WriteLine("=== BEFORE POST PROCESSING ===");
|
||||
Console.WriteLine($"TestStartTelegramIx = {reader.TestStartTelegramIx}");
|
||||
Console.WriteLine($"TestEndTelegramIx = {reader.TestEndTelegramIx}");
|
||||
|
||||
object[] markArgs = { 0, 0 };
|
||||
|
||||
try
|
||||
{
|
||||
InvokePrivate(reader, "AddTestStartEndMarksToData", markArgs);
|
||||
Console.WriteLine("AddTestStartEndMarksToData OK");
|
||||
|
||||
InvokePrivate(reader, "DataStreamPostProcessing");
|
||||
Console.WriteLine("DataStreamPostProcessing OK");
|
||||
|
||||
InvokePrivate(reader, "PrepareCalculatedChannelData");
|
||||
Console.WriteLine("PrepareCalculatedChannelData OK");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Fail(
|
||||
"Post-processing failed.\n" +
|
||||
$"Exception: {ex.GetType().Name}: {ex.Message}\n" +
|
||||
$"StackTrace:\n{ex.StackTrace}");
|
||||
}
|
||||
|
||||
Console.WriteLine("=== CALCULATED VALUES ===");
|
||||
Console.WriteLine($"NoSamples = {reader.NoSamples}");
|
||||
Console.WriteLine($"VolumeLtrStart = {reader.VolumeLtrStart}");
|
||||
Console.WriteLine($"VolumeLtrEnd = {reader.VolumeLtrEnd}");
|
||||
Console.WriteLine($"TimestampSecStart = {reader.TimestampSecStart}");
|
||||
Console.WriteLine($"TimestampSecEnd = {reader.TimestampSecEnd}");
|
||||
|
||||
Assert.IsFalse(double.IsNaN(reader.VolumeLtrStart), "VolumeLtrStart is NaN");
|
||||
Assert.IsFalse(double.IsNaN(reader.VolumeLtrEnd), "VolumeLtrEnd is NaN");
|
||||
Assert.IsFalse(double.IsNaN(reader.TimestampSecStart), "TimestampSecStart is NaN");
|
||||
Assert.IsFalse(double.IsNaN(reader.TimestampSecEnd), "TimestampSecEnd is NaN");
|
||||
|
||||
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
||||
$"Timestamp ordering invalid: start={reader.TimestampSecStart}, end={reader.TimestampSecEnd}");
|
||||
|
||||
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
||||
$"Volume ordering invalid: start={reader.VolumeLtrStart}, end={reader.VolumeLtrEnd}");
|
||||
|
||||
// When parser input is finally correct, replace these expected values:
|
||||
const double expectedVolumeStart = 0.0;
|
||||
const double expectedVolumeEnd = 0.0;
|
||||
const double expectedTimeStart = 0.0;
|
||||
const double expectedTimeEnd = 0.0;
|
||||
const double tolerance = 0.000001;
|
||||
|
||||
Console.WriteLine("=== EXPECTED VS ACTUAL ===");
|
||||
Console.WriteLine($"expectedVolumeStart = {expectedVolumeStart}, actual = {reader.VolumeLtrStart}");
|
||||
Console.WriteLine($"expectedVolumeEnd = {expectedVolumeEnd}, actual = {reader.VolumeLtrEnd}");
|
||||
Console.WriteLine($"expectedTimeStart = {expectedTimeStart}, actual = {reader.TimestampSecStart}");
|
||||
Console.WriteLine($"expectedTimeEnd = {expectedTimeEnd}, actual = {reader.TimestampSecEnd}");
|
||||
|
||||
Assert.AreEqual(expectedVolumeStart, reader.VolumeLtrStart, tolerance, "VolumeLtrStart mismatch");
|
||||
Assert.AreEqual(expectedVolumeEnd, reader.VolumeLtrEnd, tolerance, "VolumeLtrEnd mismatch");
|
||||
Assert.AreEqual(expectedTimeStart, reader.TimestampSecStart, tolerance, "TimestampSecStart mismatch");
|
||||
Assert.AreEqual(expectedTimeEnd, reader.TimestampSecEnd, tolerance, "TimestampSecEnd mismatch");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RealInput_ShouldSupport_RolloverNormalization()
|
||||
{
|
||||
var reader = new GenesisSmartReader();
|
||||
InitializeReaderForTest(reader);
|
||||
|
||||
string[] realInputLines = LoadRealInputLinesWithRollover();
|
||||
Assert.IsTrue(realInputLines.Length > 0, "No rollover input lines were provided.");
|
||||
|
||||
for (int i = 0; i < realInputLines.Length; i++)
|
||||
{
|
||||
string line = realInputLines[i];
|
||||
|
||||
bool blockCompleted;
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out blockCompleted);
|
||||
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Console.WriteLine($"[{i}] line={line}");
|
||||
Console.WriteLine($"[{i}] optoDataCount={optoDataCount}, blockCompleted={blockCompleted}");
|
||||
}
|
||||
|
||||
int finalOptoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Assert.IsTrue(
|
||||
finalOptoDataCount > 1,
|
||||
"Need at least 2 valid telegrams. Check exact telegram format / CRC in LoadRealInputLinesWithRollover().");
|
||||
|
||||
reader.TestStartTelegramIx = 0;
|
||||
reader.TestEndTelegramIx = finalOptoDataCount - 1;
|
||||
|
||||
object[] markArgs = { 0, 0 };
|
||||
InvokePrivate(reader, "AddTestStartEndMarksToData", markArgs);
|
||||
InvokePrivate(reader, "DataStreamPostProcessing");
|
||||
InvokePrivate(reader, "PrepareCalculatedChannelData");
|
||||
|
||||
Console.WriteLine($"VolumeLtrStart={reader.VolumeLtrStart}");
|
||||
Console.WriteLine($"VolumeLtrEnd={reader.VolumeLtrEnd}");
|
||||
Console.WriteLine($"TimestampSecStart={reader.TimestampSecStart}");
|
||||
Console.WriteLine($"TimestampSecEnd={reader.TimestampSecEnd}");
|
||||
|
||||
Assert.IsTrue(reader.TimestampSecEnd >= reader.TimestampSecStart,
|
||||
"Normalized end time should be >= start time");
|
||||
Assert.IsTrue(reader.VolumeLtrEnd >= reader.VolumeLtrStart,
|
||||
"Normalized end volume should be >= start volume");
|
||||
}
|
||||
|
||||
private static void InitializeReaderForTest(GenesisSmartReader reader)
|
||||
{
|
||||
const int channelCount = 3;
|
||||
|
||||
SetPrivateField(reader, "volumeRawExtLast", new double[channelCount]);
|
||||
SetPrivateField(reader, "timestampExtLast", new double[channelCount]);
|
||||
|
||||
SetPrivateField(reader, "lastTimestamp", new double[channelCount]);
|
||||
SetPrivateField(reader, "timestampSec", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||
SetPrivateField(reader, "timestampSec0", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||
|
||||
SetPrivateField(reader, "lastVolumeRaw", new double[channelCount]);
|
||||
SetPrivateField(reader, "volumeLtr", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||
SetPrivateField(reader, "volumeLtr0", Enumerable.Repeat(double.NaN, channelCount).ToArray());
|
||||
|
||||
var optoData = new OptoTelegramRaw[GenesisSmartReader.OptoDataBufferSize];
|
||||
for (int i = 0; i < optoData.Length; i++)
|
||||
optoData[i] = new OptoTelegramRaw();
|
||||
|
||||
SetPrivateField(reader, "optoData", optoData);
|
||||
SetPrivateField(reader, "optoDataCount", 0);
|
||||
SetPrivateField(reader, "toBeFlushed", new OptoTelegramRaw());
|
||||
|
||||
SetPrivateField(reader, "flowDirectionDetection", new FlowDirectionDetection());
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||
SetPrivateField(reader, "synchronized", false);
|
||||
SetPrivateField(reader, "synchronized2", false);
|
||||
SetPrivateField(reader, "partOfTelegram", string.Empty);
|
||||
SetPrivateField(reader, "startDataProcessing", true);
|
||||
|
||||
reader.TestStartTelegramIx = 0;
|
||||
reader.TestEndTelegramIx = 0;
|
||||
}
|
||||
|
||||
private static string[] LoadRealInputLines()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
// Replace these with REAL, unchanged captured telegram lines from the device.
|
||||
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
"@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
};
|
||||
}
|
||||
|
||||
private static string[] LoadRealInputLinesWithRollover()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
// Replace these with REAL, unchanged captured telegram lines spanning the rollover case.
|
||||
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
"@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
};
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object target, string fieldName, object value)
|
||||
{
|
||||
Type type = target.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var field = type.GetField(
|
||||
fieldName,
|
||||
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly);
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
field.SetValue(target, value);
|
||||
return;
|
||||
}
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
Assert.Fail($"Field '{fieldName}' not found.");
|
||||
}
|
||||
|
||||
private static T GetPrivateField<T>(object target, string fieldName)
|
||||
{
|
||||
Type type = target.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var field = type.GetField(
|
||||
fieldName,
|
||||
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly);
|
||||
|
||||
if (field != null)
|
||||
return (T)field.GetValue(target);
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
Assert.Fail($"Field '{fieldName}' not found.");
|
||||
return default;
|
||||
}
|
||||
|
||||
private static object InvokePrivate(object target, string methodName, object[] args = null)
|
||||
{
|
||||
Type type = target.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var methods = type.GetMethods(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.DeclaredOnly)
|
||||
.Where(m => m.Name == methodName)
|
||||
.ToList();
|
||||
|
||||
foreach (var method in methods)
|
||||
{
|
||||
if (args == null && method.GetParameters().Length == 0)
|
||||
return method.Invoke(target, null);
|
||||
|
||||
if (args != null && method.GetParameters().Length == args.Length)
|
||||
return method.Invoke(target, args);
|
||||
}
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
Assert.Fail($"Method '{methodName}' not found.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+192
-53
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Reflection;
|
||||
using Common;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.Generic;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
@@ -14,6 +13,12 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
private const int ChannelCount = 3;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
SetPrivateStaticField(typeof(GenesisSmartReader), "chenelsSwichCount", ChannelCount);
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object target, string fieldName, object value)
|
||||
{
|
||||
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
@@ -32,13 +37,25 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
return (T)field.GetValue(target);
|
||||
}
|
||||
|
||||
private static void InvokePrivateMethod(object target, string methodName)
|
||||
private static void SetPrivateStaticField(Type type, string fieldName, object value)
|
||||
{
|
||||
var method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (method == null)
|
||||
throw new MissingMethodException(target.GetType().FullName, methodName);
|
||||
var field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
throw new MissingFieldException(type.FullName, fieldName);
|
||||
|
||||
method.Invoke(target, null);
|
||||
field.SetValue(null, value);
|
||||
}
|
||||
|
||||
private static void InvokePrepareCalculatedChannelData(GenesisSmartReader reader)
|
||||
{
|
||||
var method = typeof(GenesisSmartReader).GetMethod(
|
||||
"PrepareCalculatedChannelData",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
if (method == null)
|
||||
throw new MissingMethodException(typeof(GenesisSmartReader).FullName, "PrepareCalculatedChannelData");
|
||||
|
||||
method.Invoke(reader, null);
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw CreateOptoRecord(int channel, double volumeRawExt, double timestampExt, int counter)
|
||||
@@ -53,8 +70,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
DateTime = DateTime.Now
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static GenesisCfg CreateCfg()
|
||||
{
|
||||
var cfg = new GenesisCfg(null);
|
||||
@@ -75,21 +91,27 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SimulatedInterleaved20x3ChannelStream_ShouldComputeStartAndEndVolumeAndTimeCorrectly()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
SetPrivateField(reader, "volumeRawExtLast", new double[3]);
|
||||
SetPrivateField(reader, "timestampExtLast", new double[3]);
|
||||
SetPrivateField(reader, "flowDirectionDetection", new FlowDirectionDetection());
|
||||
private static GenesisSmartReader CreateReaderWithOptoBuffer()
|
||||
{
|
||||
var reader = new GenesisSmartReader(CreateCfg(), null);
|
||||
|
||||
SetPrivateField(reader, "optoData", new OptoTelegramRaw[GenesisSmartReader.OptoDataBufferSize]);
|
||||
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
for (int i = 0; i < optoData.Length; i++)
|
||||
{
|
||||
optoData[i] = new OptoTelegramRaw();
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SimulatedInterleaved20x3ChannelStream_ShouldComputeRecalculatedStartAndEndVolumeAndTimeCorrectly()
|
||||
{
|
||||
var reader = CreateReaderWithOptoBuffer();
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
int index = 0;
|
||||
for (int g = 0; g < 20; g++)
|
||||
@@ -108,66 +130,83 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
reader.TestStartTelegramIx = 2;
|
||||
reader.TestEndTelegramIx = index - 1;
|
||||
|
||||
Assert.AreEqual(200.0, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(217.0, reader.VolumeLtrEnd, 1e-9);
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual(200.666666666667, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(18.0, reader.TimestampSecEnd, 1e-9);
|
||||
Assert.AreEqual(20.0, reader.TimestampSecEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(200.666666666667, reader.VolumeLtrStartRaw, 1e-9);
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEndRaw, 1e-9);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeLtrEnd_ShouldIgnoreInvalidTrailingRecords_AndUsePreviousValidPerChannelSamples()
|
||||
public void VolumeLtrEnd_ShouldRecalculateShorterChannelToLongestChannelTimeSpan()
|
||||
{
|
||||
var reader = new GenesisSmartReader(CreateCfg(), null);
|
||||
|
||||
SetPrivateField(reader, "optoData", new OptoTelegramRaw[GenesisSmartReader.OptoDataBufferSize]);
|
||||
|
||||
var reader = CreateReaderWithOptoBuffer();
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
for (int i = 0; i < optoData.Length; i++)
|
||||
optoData[i] = new OptoTelegramRaw();
|
||||
|
||||
int index = 0;
|
||||
|
||||
// Build 10 groups of valid 3-channel data
|
||||
for (int g = 0; g < 10; g++)
|
||||
{
|
||||
optoData[index++] = CreateOptoRecord(0, 100 + g, 1 + g, index);
|
||||
optoData[index++] = CreateOptoRecord(1, 200 + g, 1 + g, index);
|
||||
optoData[index++] = CreateOptoRecord(2, 300 + g, 1 + g, index);
|
||||
optoData[index] = CreateOptoRecord(0, 100 + g, 1 + g, index);
|
||||
index++;
|
||||
|
||||
optoData[index] = CreateOptoRecord(1, 200 + g, 1 + g, index);
|
||||
index++;
|
||||
|
||||
optoData[index] = CreateOptoRecord(2, 300 + g, 1 + g, index);
|
||||
index++;
|
||||
}
|
||||
|
||||
// Corrupt the last two channel-1 records
|
||||
optoData[25].Flags = OptoTelegramFlags.InvalidTelegram; // group 8, channel 1
|
||||
optoData[28].Flags = OptoTelegramFlags.InvalidTelegram; // group 9, channel 1
|
||||
// channel 1 loses its last two valid records
|
||||
// valid ch1 becomes: 200..207 with timestamps 1..8
|
||||
// longest channel deltaTime is 9 (channels 0 and 2)
|
||||
// ch1 deltaVolume = 7, deltaTime = 7 => recalculated deltaVolume = 7 * 9 / 7 = 9
|
||||
// recalculated end ch1 = 200 + 9 = 209
|
||||
optoData[25].Flags = OptoTelegramFlags.InvalidTelegram;
|
||||
optoData[28].Flags = OptoTelegramFlags.InvalidTelegram;
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", index);
|
||||
reader.TestStartTelegramIx = 2;
|
||||
reader.TestEndTelegramIx = index - 1;
|
||||
|
||||
// Start still comes from first full valid 3-channel snapshot:
|
||||
// (100 + 200 + 300) / 3 = 200
|
||||
Assert.AreEqual(200.0, reader.VolumeLtrStart, 1e-9);
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
// End with last 5 valid per channel:
|
||||
// ch0 valid last 5: 105,106,107,108,109 => avg 107
|
||||
// ch1 valid last 5: 203,204,205,206,207 => avg 205
|
||||
// because 208 and 209 were invalid
|
||||
// ch2 valid last 5: 305,306,307,308,309 => avg 307
|
||||
// total avg = (107 + 205 + 307) / 3 = 206.3333333333...
|
||||
Assert.AreEqual(206.33333333333334, reader.VolumeLtrEnd, 1e-9);
|
||||
Assert.AreEqual(200.666666666667, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(208.33333333333334, reader.VolumeLtrEnd, 1e-9);
|
||||
Assert.AreEqual(208.33333333333334, reader.VolumeLtrEndRaw, 1e-9);
|
||||
|
||||
Assert.AreEqual(101.0, reader.VolumeLtrStartCh1, 1e-9);
|
||||
Assert.AreEqual(201.0, reader.VolumeLtrStartCh2, 1e-9);
|
||||
Assert.AreEqual(300.0, reader.VolumeLtrStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(200.666666666667, reader.VolumeLtrStartRaw, 1e-9);
|
||||
|
||||
Assert.AreEqual(110.0, reader.VolumeLtrEndCh1, 1e-9);
|
||||
Assert.AreEqual(210.0, reader.VolumeLtrEndCh2, 1e-9);
|
||||
Assert.AreEqual(309.0, reader.VolumeLtrEndCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(10.0, reader.TimestampSecEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh1, 1e-9);
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh2, 1e-9);
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(10.0, reader.TimestampSecEndCh1, 1e-9);
|
||||
Assert.AreEqual(10.0, reader.TimestampSecEndCh2, 1e-9);
|
||||
Assert.AreEqual(10.0, reader.TimestampSecEndCh3, 1e-9);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeLtrStart_And_End_ShouldBeZero_WhenAllSamplesAreInvalid()
|
||||
{
|
||||
var reader = new GenesisSmartReader(CreateCfg(), null);
|
||||
|
||||
SetPrivateField(reader, "optoData", new OptoTelegramRaw[GenesisSmartReader.OptoDataBufferSize]);
|
||||
|
||||
var reader = CreateReaderWithOptoBuffer();
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
for (int i = 0; i < optoData.Length; i++)
|
||||
optoData[i] = new OptoTelegramRaw();
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
@@ -184,8 +223,108 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
reader.TestStartTelegramIx = 2;
|
||||
reader.TestEndTelegramIx = 8;
|
||||
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrEnd, 1e-9);
|
||||
Assert.AreEqual(0.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(0.0, reader.TimestampSecEnd, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SimulatedInterleaved20x3ChannelStream_ShouldComputePerChannelStartAndEndValues()
|
||||
{
|
||||
var reader = CreateReaderWithOptoBuffer();
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
int index = 0;
|
||||
for (int g = 0; g < 20; g++)
|
||||
{
|
||||
optoData[index] = CreateOptoRecord(0, 100 + g, 1 + g, index);
|
||||
index++;
|
||||
|
||||
optoData[index] = CreateOptoRecord(1, 200 + g, 1 + g, index);
|
||||
index++;
|
||||
|
||||
optoData[index] = CreateOptoRecord(2, 300 + g, 1 + g, index);
|
||||
index++;
|
||||
}
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", index);
|
||||
reader.TestStartTelegramIx = 2;
|
||||
reader.TestEndTelegramIx = index - 1;
|
||||
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual(101.0, reader.VolumeLtrStartCh1, 1e-9);
|
||||
Assert.AreEqual(201.0, reader.VolumeLtrStartCh2, 1e-9);
|
||||
Assert.AreEqual(300.0, reader.VolumeLtrStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(120.0, reader.VolumeLtrEndCh1, 1e-9);
|
||||
Assert.AreEqual(220.0, reader.VolumeLtrEndCh2, 1e-9);
|
||||
Assert.AreEqual(319.0, reader.VolumeLtrEndCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh1, 1e-9);
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh2, 1e-9);
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(20.0, reader.TimestampSecEndCh1, 1e-9);
|
||||
Assert.AreEqual(20.0, reader.TimestampSecEndCh2, 1e-9);
|
||||
Assert.AreEqual(20.0, reader.TimestampSecEndCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(101.0, reader.VolumeLtrStartCh1, 1e-9);
|
||||
Assert.AreEqual(201.0, reader.VolumeLtrStartCh2, 1e-9);
|
||||
Assert.AreEqual(300.0, reader.VolumeLtrStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(1.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(20.0, reader.TimestampSecEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(200.666666666667, reader.VolumeLtrStartRaw, 1e-9);
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEndRaw, 1e-9);
|
||||
|
||||
Assert.AreEqual(120.0, reader.VolumeLtrEndCh1, 1e-9);
|
||||
Assert.AreEqual(220.0, reader.VolumeLtrEndCh2, 1e-9);
|
||||
Assert.AreEqual(319.0, reader.VolumeLtrEndCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEnd, 1e-9);
|
||||
Assert.AreEqual(219.0, reader.VolumeLtrEndRaw, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeLtrEnd_ShouldAverageOnlyAvailableChannels()
|
||||
{
|
||||
var reader = CreateReaderWithOptoBuffer();
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
optoData[idx++] = CreateOptoRecord(0, 10 + i, 100 + i, idx);
|
||||
optoData[idx++] = CreateOptoRecord(1, 20 + i, 100 + i, idx);
|
||||
}
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", idx);
|
||||
reader.TestStartTelegramIx = 1;
|
||||
reader.TestEndTelegramIx = idx - 1;
|
||||
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual(15.5, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(19.0, reader.VolumeLtrEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(11.0, reader.VolumeLtrStartCh1, 1e-9);
|
||||
Assert.AreEqual(20.0, reader.VolumeLtrStartCh2, 1e-9);
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrStartCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(15.0, reader.VolumeLtrEndCh1, 1e-9);
|
||||
Assert.AreEqual(24.0, reader.VolumeLtrEndCh2, 1e-9);
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrEndCh3, 1e-9);
|
||||
|
||||
Assert.AreEqual(100.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(104.0, reader.TimestampSecEnd, 1e-9);
|
||||
}
|
||||
}
|
||||
}
|
||||
+511
@@ -0,0 +1,511 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
[TestClass]
|
||||
public class GenesisSmartReaderChannelTests
|
||||
{
|
||||
private GenesisSmartReader _reader;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
_reader = new GenesisSmartReader();
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw Rec(
|
||||
int channel,
|
||||
double time,
|
||||
double volume,
|
||||
OptoTelegramFlags flags = OptoTelegramFlags.OK)
|
||||
{
|
||||
return new OptoTelegramRaw
|
||||
{
|
||||
iChannel = channel,
|
||||
TimestampExt = time,
|
||||
VolumeRawExt = volume,
|
||||
Flags = flags
|
||||
};
|
||||
}
|
||||
|
||||
private object InvokePrivate(string methodName, params object[] args)
|
||||
{
|
||||
var mi = typeof(GenesisSmartReader).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
Assert.IsNotNull(mi, $"Method '{methodName}' was not found.");
|
||||
|
||||
return mi.Invoke(_reader, args);
|
||||
}
|
||||
|
||||
private static T GetPrivateField<T>(object instance, string fieldName)
|
||||
{
|
||||
var fi = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.IsNotNull(fi, $"Field '{fieldName}' was not found.");
|
||||
return (T)fi.GetValue(instance);
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object instance, string fieldName, object value)
|
||||
{
|
||||
var fi = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.IsNotNull(fi, $"Field '{fieldName}' was not found.");
|
||||
fi.SetValue(instance, value);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GroupRecordsPerChannel_Groups_Valid_Records_By_Channel()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
Rec(0, 13, 110),
|
||||
Rec(1, 14, 220),
|
||||
Rec(2, 15, 330),
|
||||
};
|
||||
|
||||
var grouped = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"GroupRecordsPerChannel",
|
||||
(object)input, 0, input.Length - 1, input.Length);
|
||||
|
||||
Assert.AreEqual(3, grouped.Length);
|
||||
|
||||
Assert.AreEqual(2, grouped[0].Length);
|
||||
Assert.AreEqual(2, grouped[1].Length);
|
||||
Assert.AreEqual(2, grouped[2].Length);
|
||||
|
||||
Assert.AreEqual(100, grouped[0][0].VolumeRawExt);
|
||||
Assert.AreEqual(110, grouped[0][1].VolumeRawExt);
|
||||
|
||||
Assert.AreEqual(200, grouped[1][0].VolumeRawExt);
|
||||
Assert.AreEqual(220, grouped[1][1].VolumeRawExt);
|
||||
|
||||
Assert.AreEqual(300, grouped[2][0].VolumeRawExt);
|
||||
Assert.AreEqual(330, grouped[2][1].VolumeRawExt);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GroupRecordsPerChannel_Ignores_Invalid_Records()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100, OptoTelegramFlags.OK),
|
||||
Rec(1, 11, 200, OptoTelegramFlags.InvalidTelegram),
|
||||
Rec(2, 12, 300, OptoTelegramFlags.OK),
|
||||
Rec(0, 13, 110, OptoTelegramFlags.SyncError),
|
||||
Rec(1, 14, 220, OptoTelegramFlags.OK),
|
||||
};
|
||||
|
||||
var grouped = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"GroupRecordsPerChannel",
|
||||
(object)input, 0, input.Length - 1, input.Length);
|
||||
|
||||
Assert.AreEqual(1, grouped[0].Length);
|
||||
Assert.AreEqual(1, grouped[1].Length);
|
||||
Assert.AreEqual(1, grouped[2].Length);
|
||||
|
||||
Assert.AreEqual(100, grouped[0][0].VolumeRawExt);
|
||||
Assert.AreEqual(220, grouped[1][0].VolumeRawExt);
|
||||
Assert.AreEqual(300, grouped[2][0].VolumeRawExt);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GroupRecordsPerChannel_Swaps_Start_And_End_When_Reversed()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(0, 12, 120),
|
||||
};
|
||||
|
||||
var grouped = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"GroupRecordsPerChannel",
|
||||
(object)input, 2, 0, input.Length);
|
||||
|
||||
Assert.AreEqual(2, grouped[0].Length);
|
||||
Assert.AreEqual(1, grouped[1].Length);
|
||||
Assert.AreEqual(0, grouped[2].Length);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GroupRecordsPerChannel_Returns_Empty_For_Invalid_Range()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
};
|
||||
|
||||
var grouped = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"GroupRecordsPerChannel",
|
||||
(object)input, -1, 1, input.Length);
|
||||
|
||||
Assert.AreEqual(3, grouped.Length);
|
||||
Assert.IsTrue(grouped.All(x => x.Length == 0));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TimeDeltaPerChannel_Computes_First_Last_Deltas()
|
||||
{
|
||||
var grouped = new[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(0, 18, 170),
|
||||
Rec(0, 15, 120)
|
||||
},
|
||||
new[]
|
||||
{
|
||||
Rec(1, 20, 500),
|
||||
Rec(1, 23, 530)
|
||||
},
|
||||
new[]
|
||||
{
|
||||
Rec(2, 30, 900)
|
||||
}
|
||||
};
|
||||
|
||||
var result = (ValueTuple<int, double?, double?>[])InvokePrivate(
|
||||
"TimeDeltaPerChannel",
|
||||
(object)grouped);
|
||||
|
||||
Assert.AreEqual(0, result[0].Item1);
|
||||
Assert.AreEqual(5, result[0].Item2);
|
||||
Assert.AreEqual(20, result[0].Item3);
|
||||
|
||||
Assert.AreEqual(1, result[1].Item1);
|
||||
Assert.AreEqual(3, result[1].Item2);
|
||||
Assert.AreEqual(30, result[1].Item3);
|
||||
|
||||
Assert.AreEqual(2, result[2].Item1);
|
||||
Assert.IsNull(result[2].Item2);
|
||||
Assert.IsNull(result[2].Item3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeStartPerChannel_Returns_Last_Seen_Value_Backward_From_Index()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(0, 12, 120),
|
||||
Rec(2, 13, 300),
|
||||
Rec(1, 14, 220),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"VolumeStartPerChannel",
|
||||
(object)input, input.Length, 4);
|
||||
|
||||
Assert.AreEqual(120, result[0]);
|
||||
Assert.AreEqual(220, result[1]);
|
||||
Assert.AreEqual(300, result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TimeStartPerChannel_Returns_Last_Seen_Time_Backward_From_Index()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(0, 12, 120),
|
||||
Rec(2, 13, 300),
|
||||
Rec(1, 14, 220),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"TimeStartPerChannel",
|
||||
(object)input, input.Length, 4);
|
||||
|
||||
Assert.AreEqual(12, result[0]);
|
||||
Assert.AreEqual(14, result[1]);
|
||||
Assert.AreEqual(13, result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeEndPerChannel_Averages_Last_N_Samples_Per_Channel()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
Rec(0, 13, 120),
|
||||
Rec(1, 14, 220),
|
||||
Rec(2, 15, 330),
|
||||
Rec(0, 16, 140),
|
||||
Rec(1, 17, 240),
|
||||
Rec(2, 18, 360),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"VolumeEndPerChannel",
|
||||
(object)input, input.Length, 8, 2);
|
||||
|
||||
Assert.AreEqual((140 + 120) / 2.0, result[0]);
|
||||
Assert.AreEqual((240 + 220) / 2.0, result[1]);
|
||||
Assert.AreEqual((360 + 330) / 2.0, result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TimeEndPerChannel_Averages_Last_N_Samples_Per_Channel()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
Rec(0, 13, 120),
|
||||
Rec(1, 14, 220),
|
||||
Rec(2, 15, 330),
|
||||
Rec(0, 16, 140),
|
||||
Rec(1, 17, 240),
|
||||
Rec(2, 18, 360),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"TimeEndPerChannel",
|
||||
(object)input, input.Length, 8, 2);
|
||||
|
||||
Assert.AreEqual((16 + 13) / 2.0, result[0]);
|
||||
Assert.AreEqual((17 + 14) / 2.0, result[1]);
|
||||
Assert.AreEqual((18 + 15) / 2.0, result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeStartPerChannel_Returns_All_Nulls_For_OutOfRange_Index()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"VolumeStartPerChannel",
|
||||
(object)input, input.Length, -1);
|
||||
|
||||
Assert.IsNull(result[0]);
|
||||
Assert.IsNull(result[1]);
|
||||
Assert.IsNull(result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TimeEndPerChannel_Uses_One_Sample_When_SamplesPerChannel_Is_Zero()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
Rec(0, 13, 120),
|
||||
Rec(1, 14, 220),
|
||||
Rec(2, 15, 330),
|
||||
};
|
||||
|
||||
var result = (double?[])InvokePrivate(
|
||||
"TimeEndPerChannel",
|
||||
(object)input, input.Length, 5, 0);
|
||||
|
||||
Assert.AreEqual(13, result[0]);
|
||||
Assert.AreEqual(14, result[1]);
|
||||
Assert.AreEqual(15, result[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Precreated_OptoData_Private_Methods_Read_Correct_Values()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
Rec(0, 13, 120),
|
||||
Rec(1, 14, 220),
|
||||
Rec(2, 15, 330),
|
||||
Rec(0, 16, 140),
|
||||
Rec(1, 17, 240),
|
||||
Rec(2, 18, 360),
|
||||
};
|
||||
|
||||
SetPrivateField(_reader, "optoData", input);
|
||||
SetPrivateField(_reader, "optoDataCount", input.Length);
|
||||
|
||||
_reader.TestStartTelegramIx = 5;
|
||||
_reader.TestEndTelegramIx = 8;
|
||||
|
||||
Assert.AreEqual(input.Length, GetPrivateField<int>(_reader, "optoDataCount"));
|
||||
|
||||
var startVolumes = (double?[])InvokePrivate(
|
||||
"VolumeStartPerChannel",
|
||||
(object)input, input.Length, 5);
|
||||
|
||||
var endVolumes = (double?[])InvokePrivate(
|
||||
"VolumeEndPerChannel",
|
||||
(object)input, input.Length, 8, 2 * GenesisSmartReader.StartEndFilterSamplesCount2 + 1);
|
||||
|
||||
var startTimes = (double?[])InvokePrivate(
|
||||
"TimeStartPerChannel",
|
||||
(object)input, input.Length, 5);
|
||||
|
||||
var endTimes = (double?[])InvokePrivate(
|
||||
"TimeEndPerChannel",
|
||||
(object)input, input.Length, 8, 2 * GenesisSmartReader.StartEndFilterSamplesCount2 + 1);
|
||||
|
||||
Assert.AreEqual(120, startVolumes[0]);
|
||||
Assert.AreEqual(220, startVolumes[1]);
|
||||
Assert.AreEqual(330, startVolumes[2]);
|
||||
|
||||
Assert.AreEqual(13, startTimes[0]);
|
||||
Assert.AreEqual(14, startTimes[1]);
|
||||
Assert.AreEqual(15, startTimes[2]);
|
||||
|
||||
Assert.AreEqual((140 + 120 + 100) / 3.0, endVolumes[0]);
|
||||
Assert.AreEqual((240 + 220 + 200) / 3.0, endVolumes[1]);
|
||||
Assert.AreEqual((360 + 330 + 300) / 3.0, endVolumes[2]);
|
||||
|
||||
Assert.AreEqual((16 + 13 + 10) / 3.0, endTimes[0]);
|
||||
Assert.AreEqual((17 + 14 + 11) / 3.0, endTimes[1]);
|
||||
Assert.AreEqual((18 + 15 + 12) / 3.0, endTimes[2]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Public_Channel_Properties_Default_To_Zero_When_NoSamples_Is_True()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 11, 200),
|
||||
Rec(2, 12, 300),
|
||||
};
|
||||
|
||||
SetPrivateField(_reader, "optoData", input);
|
||||
SetPrivateField(_reader, "optoDataCount", input.Length);
|
||||
|
||||
_reader.TestStartTelegramIx = 5;
|
||||
_reader.TestEndTelegramIx = 8;
|
||||
|
||||
Assert.IsTrue(_reader.NoSamples);
|
||||
|
||||
Assert.AreEqual(0, _reader.VolumeLtrStartCh1);
|
||||
Assert.AreEqual(0, _reader.VolumeLtrStartCh2);
|
||||
Assert.AreEqual(0, _reader.VolumeLtrStartCh3);
|
||||
|
||||
Assert.AreEqual(0, _reader.VolumeLtrEndCh1);
|
||||
Assert.AreEqual(0, _reader.VolumeLtrEndCh2);
|
||||
Assert.AreEqual(0, _reader.VolumeLtrEndCh3);
|
||||
|
||||
Assert.AreEqual(0, _reader.TimestampSecStartCh1);
|
||||
Assert.AreEqual(0, _reader.TimestampSecStartCh2);
|
||||
Assert.AreEqual(0, _reader.TimestampSecStartCh3);
|
||||
|
||||
Assert.AreEqual(0, _reader.TimestampSecEndCh1);
|
||||
Assert.AreEqual(0, _reader.TimestampSecEndCh2);
|
||||
Assert.AreEqual(0, _reader.TimestampSecEndCh3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Copy_Should_Copy_From_Source_Record()
|
||||
{
|
||||
var source = Rec(2, 123.5, 456.7, OptoTelegramFlags.OK_TestEnd);
|
||||
source.Counter = 77;
|
||||
source.RefFlow = 9.5f;
|
||||
source.FlowRaw = 111;
|
||||
source.VolumeRaw = 222;
|
||||
source.Impedance = 333;
|
||||
source.CheckSum = 44;
|
||||
|
||||
var target = new OptoTelegramRaw();
|
||||
target.Copy(source);
|
||||
|
||||
Assert.AreEqual(source.iChannel, target.iChannel);
|
||||
Assert.AreEqual(source.TimestampExt, target.TimestampExt);
|
||||
Assert.AreEqual(source.VolumeRawExt, target.VolumeRawExt);
|
||||
Assert.AreEqual(source.Flags, target.Flags);
|
||||
Assert.AreEqual(source.Counter, target.Counter);
|
||||
Assert.AreEqual(source.RefFlow, target.RefFlow);
|
||||
Assert.AreEqual(source.FlowRaw, target.FlowRaw);
|
||||
Assert.AreEqual(source.VolumeRaw, target.VolumeRaw);
|
||||
Assert.AreEqual(source.Impedance, target.Impedance);
|
||||
Assert.AreEqual(source.CheckSum, target.CheckSum);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RecalculateVolumeAndTimeDeltaPerChannel_Returns_Recalculated_Output()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(0, 20, 200),
|
||||
|
||||
Rec(1, 10, 500),
|
||||
Rec(1, 30, 560),
|
||||
|
||||
Rec(2, 10, 1000),
|
||||
Rec(2, 15, 1050),
|
||||
};
|
||||
|
||||
var result = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"RecalculateVolumeAndTimeDeltaPerChannel",
|
||||
(object)input,
|
||||
input.Length,
|
||||
0,
|
||||
input.Length - 1);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(3, result.Length);
|
||||
|
||||
for (int ch = 0; ch < 3; ch++)
|
||||
{
|
||||
Assert.IsNotNull(result[ch]);
|
||||
Assert.AreEqual(2, result[ch].Length);
|
||||
Assert.IsNotNull(result[ch][0]);
|
||||
Assert.IsNotNull(result[ch][1]);
|
||||
|
||||
Assert.AreEqual(10, result[ch][0].TimestampExt, 0.0001);
|
||||
Assert.AreEqual(30, result[ch][1].TimestampExt, 0.0001);
|
||||
}
|
||||
|
||||
Assert.AreEqual(100, result[0][0].VolumeRawExt, 0.0001);
|
||||
Assert.AreEqual(300, result[0][1].VolumeRawExt, 0.0001);
|
||||
|
||||
Assert.AreEqual(500, result[1][0].VolumeRawExt, 0.0001);
|
||||
Assert.AreEqual(560, result[1][1].VolumeRawExt, 0.0001);
|
||||
|
||||
Assert.AreEqual(1000, result[2][0].VolumeRawExt, 0.0001);
|
||||
Assert.AreEqual(1200, result[2][1].VolumeRawExt, 0.0001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RecalculateVolumeAndTimeDeltaPerChannel_Returns_Null_When_No_Channel_Has_Two_Records()
|
||||
{
|
||||
var input = new[]
|
||||
{
|
||||
Rec(0, 10, 100),
|
||||
Rec(1, 20, 200),
|
||||
Rec(2, 30, 300),
|
||||
};
|
||||
|
||||
var result = (OptoTelegramRaw[][])InvokePrivate(
|
||||
"RecalculateVolumeAndTimeDeltaPerChannel",
|
||||
(object)input,
|
||||
input.Length,
|
||||
0,
|
||||
input.Length - 1);
|
||||
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
[TestClass]
|
||||
public class GenesisSmartReaderStopTests
|
||||
{
|
||||
private const int ChannelCount = 3;
|
||||
|
||||
private static GenesisCfg CreateCfg()
|
||||
{
|
||||
Factory factory = new Factory();
|
||||
return new GenesisCfg(factory);
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object target, string fieldName, object value)
|
||||
{
|
||||
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
||||
|
||||
field.SetValue(target, value);
|
||||
}
|
||||
|
||||
private static T GetPrivateField<T>(object target, string fieldName)
|
||||
{
|
||||
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
||||
|
||||
return (T)field.GetValue(target);
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw CreateOptoRecord(int channel, double volumeRawExt, double timestampExt)
|
||||
{
|
||||
return new OptoTelegramRaw
|
||||
{
|
||||
Flags = OptoTelegramFlags.OK,
|
||||
VolumeRawExt = volumeRawExt,
|
||||
TimestampExt = timestampExt,
|
||||
iChannel = channel
|
||||
};
|
||||
}
|
||||
|
||||
private static void FillValidOptoDataForPostProcessing(GenesisSmartReader reader)
|
||||
{
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
int idx = 0;
|
||||
for (int group = 0; group < 6; group++)
|
||||
{
|
||||
optoData[idx++] = CreateOptoRecord(0, 10 + group, 100 + group);
|
||||
optoData[idx++] = CreateOptoRecord(1, 20 + group, 100 + group);
|
||||
optoData[idx++] = CreateOptoRecord(2, 30 + group, 100 + group);
|
||||
}
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", 18);
|
||||
reader.TestStartTelegramIx = 1;
|
||||
reader.TestEndTelegramIx = 17;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Stop_WhenStateIsCalculateStoredData_ShouldRunPostProcessing_AndFlushState()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
FillValidOptoDataForPostProcessing(reader);
|
||||
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.CalculateStoredData);
|
||||
SetPrivateField(reader, "startDataProcessing", false);
|
||||
SetPrivateField(reader, "_stopQueueData", true);
|
||||
|
||||
fake.Open();
|
||||
reader.optoSerialPort = fake;
|
||||
|
||||
reader.Stop();
|
||||
|
||||
var finalState = GetPrivateField<DataStreamState>(reader, "dataStreamState");
|
||||
|
||||
Assert.AreEqual(DataStreamState.Flush, finalState, "Stop() should finish in Flush state.");
|
||||
Assert.IsFalse(fake.IsOpen, "Serial port should be closed by Stop().");
|
||||
|
||||
// These values are populated only if DataStreamPostProcessing() ran.
|
||||
Assert.AreEqual((11.0 + 20.0 + 30.0) / 3.0, reader.VolumeLtrStartRaw, 1e-9,
|
||||
"Expected post-processing to prepare raw start values.");
|
||||
Assert.AreEqual((15.0 + 25.0 + 35.0) / 3.0, reader.VolumeLtrEndRaw, 1e-9,
|
||||
"Expected post-processing to prepare raw end values.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Stop_WhenStateIsProcessAndSave_ShouldNotRunPostProcessing_AndFlushState()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
FillValidOptoDataForPostProcessing(reader);
|
||||
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||
SetPrivateField(reader, "startDataProcessing", true);
|
||||
SetPrivateField(reader, "_stopQueueData", false);
|
||||
|
||||
fake.Open();
|
||||
reader.optoSerialPort = fake;
|
||||
|
||||
reader.Stop();
|
||||
|
||||
var finalState = GetPrivateField<DataStreamState>(reader, "dataStreamState");
|
||||
var stopQueueData = GetPrivateField<bool>(reader, "_stopQueueData");
|
||||
|
||||
Assert.AreEqual(DataStreamState.Flush, finalState, "Stop() should finish in Flush state.");
|
||||
Assert.IsTrue(stopQueueData, "Immediate stop path should stop queueing.");
|
||||
Assert.IsFalse(fake.IsOpen, "Serial port should be closed by Stop().");
|
||||
|
||||
// Should still be default because DataStreamPostProcessing() must NOT run.
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrStartRaw, 1e-9,
|
||||
"Post-processing should not run when previous state was ProcessAndSave.");
|
||||
Assert.AreEqual(0.0, reader.VolumeLtrEndRaw, 1e-9,
|
||||
"Post-processing should not run when previous state was ProcessAndSave.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RequestImmediateStop_ShouldNotChangeCalculateStoredDataState()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.CalculateStoredData);
|
||||
SetPrivateField(reader, "startDataProcessing", true);
|
||||
SetPrivateField(reader, "_stopQueueData", false);
|
||||
|
||||
reader.RequestImmediateStop();
|
||||
|
||||
var state = GetPrivateField<DataStreamState>(reader, "dataStreamState");
|
||||
var stopQueueData = GetPrivateField<bool>(reader, "_stopQueueData");
|
||||
var startDataProcessing = GetPrivateField<bool>(reader, "startDataProcessing");
|
||||
|
||||
Assert.AreEqual(DataStreamState.CalculateStoredData, state,
|
||||
"RequestImmediateStop() must not destroy CalculateStoredData state.");
|
||||
Assert.IsTrue(stopQueueData, "Immediate stop should stop queueing.");
|
||||
Assert.IsFalse(startDataProcessing, "Immediate stop should disable active processing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
+467
-70
@@ -1,5 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Common;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig;
|
||||
@@ -39,6 +45,18 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
return (T)field.GetValue(target);
|
||||
}
|
||||
|
||||
private static void InvokePrepareCalculatedChannelData(GenesisSmartReader reader)
|
||||
{
|
||||
var method = typeof(GenesisSmartReader).GetMethod(
|
||||
"PrepareCalculatedChannelData",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
if (method == null)
|
||||
throw new MissingMethodException(typeof(GenesisSmartReader).FullName, "PrepareCalculatedChannelData");
|
||||
|
||||
method.Invoke(reader, null);
|
||||
}
|
||||
|
||||
private static void InitializeThreeChannelState(GenesisSmartReader reader)
|
||||
{
|
||||
SetPrivateField(reader, "volumeRawExtLast", new double[ChannelCount]);
|
||||
@@ -53,6 +71,13 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
SetPrivateField(reader, "timestampSec", new[] { 0.0, 0.0, 0.0 });
|
||||
SetPrivateField(reader, "timestampSec0", new[] { 0.0, 0.0, 0.0 });
|
||||
}
|
||||
|
||||
private static void EnableProcessingLoopForTests(GenesisSmartReader reader)
|
||||
{
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||
SetPrivateField(reader, "startDataProcessing", true);
|
||||
reader.StopQueueData = false;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Start_ShouldOpenPort_AndEnableProcessing()
|
||||
@@ -65,7 +90,8 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
|
||||
Assert.IsTrue(fake.IsOpen);
|
||||
Assert.IsTrue(fake.OpenCalls >= 1);
|
||||
Assert.AreEqual(1, fake.DiscardInCalls);
|
||||
Assert.AreEqual(2, fake.DiscardInCalls);
|
||||
Assert.AreEqual(2, fake.DiscardOutCalls);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -79,11 +105,36 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
|
||||
Assert.IsTrue(fake.IsOpen);
|
||||
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
Assert.IsNotNull(optoData);
|
||||
|
||||
if (optoData[0] == null)
|
||||
optoData[0] = new OptoTelegramRaw();
|
||||
|
||||
if (optoData[1] == null)
|
||||
optoData[1] = new OptoTelegramRaw();
|
||||
|
||||
optoData[0].Flags = OptoTelegramFlags.OK;
|
||||
optoData[0].TimestampExt = 100.0;
|
||||
optoData[0].VolumeRawExt = 10.0;
|
||||
|
||||
optoData[1].Flags = OptoTelegramFlags.OK;
|
||||
optoData[1].TimestampExt = 101.0;
|
||||
optoData[1].VolumeRawExt = 11.0;
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", 2);
|
||||
SetPrivateField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||
|
||||
reader.TestStartTelegramIx = 0;
|
||||
reader.TestEndTelegramIx = 1;
|
||||
|
||||
reader.Stop();
|
||||
|
||||
Assert.IsFalse(fake.IsOpen);
|
||||
Assert.AreEqual(2, fake.CloseCalls);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void Run_ShouldCaptureStartTelegramIndex_WhenTimeReached()
|
||||
@@ -105,36 +156,39 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_ShouldIncreaseOptoDataCount()
|
||||
public void ProcessOptoLine_ShouldInsertMultipleTelegrams_WithCorrectChannels()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
|
||||
var line =
|
||||
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331";
|
||||
|
||||
reader.optoSerialPort = fake;
|
||||
fake.Open();
|
||||
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
Assert.AreEqual(1, optoDataCount);
|
||||
bool reset;
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
var optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Assert.AreEqual(3, optoDataCount);
|
||||
Assert.AreEqual(0, optoData[0].IChannel());
|
||||
Assert.AreEqual(1, optoData[1].IChannel());
|
||||
Assert.AreEqual(2, optoData[2].IChannel());
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(
|
||||
"@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
0)]
|
||||
[DataRow(
|
||||
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
1)]
|
||||
[DataRow(
|
||||
"@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
2)]
|
||||
[DataRow("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", 0)]
|
||||
[DataRow("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", 1)]
|
||||
[DataRow("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", 2)]
|
||||
public void ProcessOptoLine_ShouldUpdateExpectedChannel(string line, int expectedChannelIndex)
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
@@ -146,7 +200,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
reader.optoSerialPort = fake;
|
||||
InitializeThreeChannelState(reader);
|
||||
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out bool resetDataBuffer);
|
||||
|
||||
var volumeRawExtLast = GetPrivateField<double[]>(reader, "volumeRawExtLast");
|
||||
var timestampExtLast = GetPrivateField<double[]>(reader, "timestampExtLast");
|
||||
@@ -185,7 +239,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
var ev = reader.Run();
|
||||
|
||||
Assert.AreEqual(Event.ReadRegisterDone, ev);
|
||||
Assert.AreEqual(4.0, reader.WMVolume, 1E-6); // average of (3, 4, 5)
|
||||
Assert.AreEqual(4.0, reader.WMVolume, 1E-6);
|
||||
Assert.AreEqual(4000, reader.WMPulses);
|
||||
}
|
||||
|
||||
@@ -204,16 +258,16 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
var line =
|
||||
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD";
|
||||
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out bool resetDataBuffer);
|
||||
|
||||
int currentTelegramIx = GetPrivateField<int>(reader, "currentTelegramIx");
|
||||
Assert.AreEqual(0, currentTelegramIx);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow( "@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", 0)]
|
||||
[DataRow( "@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", 1)]
|
||||
[DataRow( "@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", 2)]
|
||||
[DataRow("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", 0)]
|
||||
[DataRow("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", 1)]
|
||||
[DataRow("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", 2)]
|
||||
public void ProcessOptoLine_ShouldInsertTelegramAndUpdateExpectedChannel(string line, int expectedChannelIndex)
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
@@ -223,7 +277,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave);
|
||||
reader.ProcessOptoLine(line, DataStreamState.ProcessAndSave, out bool resetDataBuffer);
|
||||
|
||||
var volumeRawExtLast = GetPrivateField<double[]>(reader, "volumeRawExtLast");
|
||||
var timestampExtLast = GetPrivateField<double[]>(reader, "timestampExtLast");
|
||||
@@ -267,30 +321,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_ShouldInsertMultipleTelegrams_WithCorrectChannels()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
|
||||
reader.ProcessOptoLine( "@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", DataStreamState.ProcessAndSave);
|
||||
reader.ProcessOptoLine( "@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", DataStreamState.ProcessAndSave);
|
||||
reader.ProcessOptoLine( "@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", DataStreamState.ProcessAndSave);
|
||||
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
var optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Assert.AreEqual(3, optoDataCount);
|
||||
Assert.AreEqual(0, optoData[0].IChannel());
|
||||
Assert.AreEqual(1, optoData[1].IChannel());
|
||||
Assert.AreEqual(2, optoData[2].IChannel());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeLtrStart_And_VolumeLtrEnd_ShouldUsePerChannelAverages()
|
||||
public void VolumeLtrStart_And_VolumeLtrEnd_ShouldUsePreparedCachedChannelData()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
@@ -298,14 +329,6 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
// Build 18 records: 6 groups of channels 0,1,2
|
||||
// Start group average = (10 + 20 + 30)/3 = 20
|
||||
// Last 5 per channel:
|
||||
// ch0: 11,12,13,14,15 => avg 13
|
||||
// ch1: 21,22,23,24,25 => avg 23
|
||||
// ch2: 31,32,33,34,35 => avg 33
|
||||
// final average = (13 + 23 + 33)/3 = 23
|
||||
|
||||
int idx = 0;
|
||||
for (int group = 0; group < 6; group++)
|
||||
{
|
||||
@@ -315,11 +338,19 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
}
|
||||
|
||||
SetPrivateField(reader, "optoDataCount", 18);
|
||||
reader.TestStartTelegramIx = 2; // first full 3-channel group
|
||||
reader.TestEndTelegramIx = 17; // last record
|
||||
reader.TestStartTelegramIx = 1;
|
||||
reader.TestEndTelegramIx = 17;
|
||||
|
||||
Assert.AreEqual(20.0, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(23.0, reader.VolumeLtrEnd, 1e-9);
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual((11.0 + 20.0 + 30.0) / 3.0, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual((15.0 + 25.0 + 35.0) / 3.0, reader.VolumeLtrEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual(100.0, reader.TimestampSecStart, 1e-9);
|
||||
Assert.AreEqual(105.0, reader.TimestampSecEnd, 1e-9);
|
||||
|
||||
Assert.AreEqual((11.0 + 20.0 + 30.0) / 3.0, reader.VolumeLtrStartRaw, 1e-9);
|
||||
Assert.AreEqual((15.0 + 25.0 + 35.0) / 3.0, reader.VolumeLtrEndRaw, 1e-9);
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw CreateOptoRecord(int channel, double volumeRawExt, double timestampExt)
|
||||
@@ -332,7 +363,7 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
iChannel = channel
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void VolumeLtrEnd_ShouldAverageOnlyAvailableChannels()
|
||||
{
|
||||
@@ -344,7 +375,6 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
|
||||
int idx = 0;
|
||||
|
||||
// only channels 0 and 1
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
optoData[idx++] = CreateOptoRecord(0, 10 + i, 100 + i);
|
||||
@@ -355,8 +385,375 @@ namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
reader.TestStartTelegramIx = 1;
|
||||
reader.TestEndTelegramIx = idx - 1;
|
||||
|
||||
// ch0 avg = 12, ch1 avg = 22 => total avg = 17
|
||||
Assert.AreEqual(17.0, reader.VolumeLtrEnd, 1e-9);
|
||||
InvokePrepareCalculatedChannelData(reader);
|
||||
|
||||
Assert.AreEqual(15.5, reader.VolumeLtrStart, 1e-9);
|
||||
Assert.AreEqual(19.0, reader.VolumeLtrEnd, 1e-9);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_Block_f_h1_h2_h3_f_ShouldResetBuffersOnlyAfterLastF()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 1;
|
||||
|
||||
bool reset;
|
||||
|
||||
reader.ProcessOptoLine("@f AA754B 4D0CEE78 5D89", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen on the first @f.");
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h 1.");
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h 2.");
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen immediately after @h 3.");
|
||||
|
||||
reader.ProcessOptoLine("@f AA7C01 4D0CFE76 B08F", DataStreamState.ProcessAndSave, out reset);
|
||||
//now some cycles must be runing, so reset must happen.
|
||||
//Assert.IsTrue(reset, "Reset must happen after trailing @f that closes the h1/h2/h3 block.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReadOptoData_FullBlock_ShouldDiscardBuffersAfterClosingF()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
|
||||
fake.EnqueueLine("@f AA754B 4D0CEE78 5D89");
|
||||
fake.EnqueueLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331");
|
||||
fake.EnqueueLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD");
|
||||
fake.EnqueueLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E");
|
||||
fake.EnqueueLine("@f AA7C01 4D0CFE76 B08F");
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
|
||||
fake.Open();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 1;
|
||||
|
||||
var readMethod = typeof(GenesisSmartReader).GetMethod(
|
||||
"ReadOptoData",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic,
|
||||
null,
|
||||
new[] { typeof(DataStreamState) },
|
||||
null);
|
||||
|
||||
Assert.IsNotNull(readMethod);
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
readMethod.Invoke(reader, new object[] { DataStreamState.ProcessAndSave });
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, fake.DiscardInCalls, "Input buffer should be discarded once after completed block.");
|
||||
Assert.AreEqual(1, fake.DiscardOutCalls, "Output buffer should be discarded once after completed block.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_LastF_AfterH3_ShouldRequestBufferReset()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 1;
|
||||
|
||||
bool reset;
|
||||
|
||||
reader.ProcessOptoLine("@f AA754B 4D0CEE78 5D89", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Opening @f must not reset buffers.");
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@f AA7C01 4D0CFE76 B08F", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsTrue(reset, "Closing @f after @h 3 must request reset.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_LastF_AfterH3_ShouldNotRequestReset_WhenRepetitionCountIsGreaterThanOne()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 3;
|
||||
|
||||
bool reset;
|
||||
|
||||
reader.ProcessOptoLine("@f AA754B 4D0CEE78 5D89", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset);
|
||||
|
||||
reader.ProcessOptoLine("@f AA7C01 4D0CFE76 B08F", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after the first completed block when repetition count is 3.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_ShouldResetOnlyAfterThirdCompletedBlock()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 3;
|
||||
|
||||
bool reset;
|
||||
|
||||
for (int repetition = 1; repetition <= 3; repetition++)
|
||||
{
|
||||
reader.ProcessOptoLine("@f AA754B 4D0CEE78 5D89", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen on opening @f, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h1, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h2, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h3, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@f AA7C01 4D0CFE76 B08F", DataStreamState.ProcessAndSave, out reset);
|
||||
|
||||
if (repetition < 3)
|
||||
Assert.IsFalse(reset, "Reset must not happen before third full block.");
|
||||
else
|
||||
Assert.IsTrue(reset, "Reset must happen on third full block.");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessOptoLine_ShouldResetOnlyAfterFifthCompletedBlock()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Open();
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
reader.Initialize();
|
||||
reader.optoSerialPort = fake;
|
||||
reader.ResetAfterBlockRepetitions = 5;
|
||||
|
||||
bool reset;
|
||||
|
||||
for (int repetition = 1; repetition <= 5; repetition++)
|
||||
{
|
||||
reader.ProcessOptoLine("@f AA754B 4D0CEE78 5D89", DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen on opening @f, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h1, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h2, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E",
|
||||
DataStreamState.ProcessAndSave, out reset);
|
||||
Assert.IsFalse(reset, "Reset must not happen after @h3, repetition " + repetition);
|
||||
|
||||
reader.ProcessOptoLine("@f AA7C01 4D0CFE76 B08F", DataStreamState.ProcessAndSave, out reset);
|
||||
|
||||
if (repetition < 5)
|
||||
Assert.IsFalse(reset, "Reset must not happen before fifth full block.");
|
||||
else
|
||||
Assert.IsTrue(reset, "Reset must happen on fifth full block.");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessingLoop_Should_Keep_FIFO_Order_For_Enqueued_Items()
|
||||
{
|
||||
var reader = new GenesisSmartReader();
|
||||
|
||||
var expected = Enumerable.Range(1, 200)
|
||||
.Select(i => $"LINE_{i:D4}")
|
||||
.ToList();
|
||||
|
||||
var actual = new List<string>();
|
||||
var sync = new object();
|
||||
var allProcessed = new CountdownEvent(expected.Count);
|
||||
|
||||
reader.TestProcessLineOverride = line => true;
|
||||
EnableProcessingLoopForTests(reader);
|
||||
|
||||
reader.TestLineProcessed = line =>
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
actual.Add(line);
|
||||
}
|
||||
|
||||
allProcessed.Signal();
|
||||
};
|
||||
|
||||
reader.StartProcessingLoop();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var line in expected)
|
||||
{
|
||||
reader.TestEnqueueLine(line);
|
||||
}
|
||||
|
||||
bool completed = allProcessed.Wait(TimeSpan.FromSeconds(10));
|
||||
Assert.IsTrue(completed, "Timed out waiting for all queued items to be processed.");
|
||||
|
||||
CollectionAssert.AreEqual(expected, actual,
|
||||
"Dequeued/processed order does not match enqueued order.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.StopProcessingLoop();
|
||||
allProcessed.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessingLoop_Should_Keep_FIFO_Order_With_Concurrent_Producers()
|
||||
{
|
||||
var reader = new GenesisSmartReader();
|
||||
|
||||
const int producerCount = 4;
|
||||
const int itemsPerProducer = 100;
|
||||
int totalItems = producerCount * itemsPerProducer;
|
||||
|
||||
var expected = new List<string>();
|
||||
var processed = new List<string>();
|
||||
|
||||
var expectedLock = new object();
|
||||
var processedLock = new object();
|
||||
int sequence = 0;
|
||||
|
||||
var allProcessed = new CountdownEvent(totalItems);
|
||||
|
||||
try
|
||||
{
|
||||
reader.TestProcessLineOverride = line => true;
|
||||
EnableProcessingLoopForTests(reader);
|
||||
|
||||
reader.TestLineProcessed = line =>
|
||||
{
|
||||
lock (processedLock)
|
||||
{
|
||||
processed.Add(line);
|
||||
}
|
||||
|
||||
allProcessed.Signal();
|
||||
};
|
||||
|
||||
reader.StartProcessingLoop();
|
||||
|
||||
var tasks = new List<Task>();
|
||||
|
||||
for (int p = 0; p < producerCount; p++)
|
||||
{
|
||||
int producerId = p;
|
||||
|
||||
tasks.Add(Task.Run(() =>
|
||||
{
|
||||
for (int i = 0; i < itemsPerProducer; i++)
|
||||
{
|
||||
int seq = Interlocked.Increment(ref sequence);
|
||||
string line = string.Format("{0:D6}|P{1}|I{2:D4}", seq, producerId, i);
|
||||
|
||||
lock (expectedLock)
|
||||
{
|
||||
expected.Add(line);
|
||||
reader.TestEnqueueLine(line);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
bool completed = allProcessed.Wait(TimeSpan.FromSeconds(15));
|
||||
Assert.IsTrue(completed, "Timed out waiting for all concurrent items to be processed.");
|
||||
|
||||
CollectionAssert.AreEqual(expected, processed,
|
||||
"Processed order does not match actual enqueue order under concurrent producers.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.StopProcessingLoop();
|
||||
allProcessed.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void PrepareCalculatedChannelData_SimulateMode_ReturnsExpectedFakeValues()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
|
||||
sut.PrepareCalculatedChannelDataSimulationForTest();
|
||||
|
||||
Assert.IsFalse(sut.NoSamples);
|
||||
|
||||
Assert.AreEqual(100.0, sut.VolumeLtrStartCh1, 0.0001);
|
||||
Assert.AreEqual(105.0, sut.VolumeLtrStartCh2, 0.0001);
|
||||
Assert.AreEqual(110.0, sut.VolumeLtrStartCh3, 0.0001);
|
||||
|
||||
Assert.AreEqual(150.0, sut.VolumeLtrEndCh1, 0.0001);
|
||||
Assert.AreEqual(157.0, sut.VolumeLtrEndCh2, 0.0001);
|
||||
Assert.AreEqual(164.0, sut.VolumeLtrEndCh3, 0.0001);
|
||||
|
||||
Assert.AreEqual(10.0, sut.TimestampSecStartCh1, 0.0001);
|
||||
Assert.AreEqual(10.0, sut.TimestampSecStartCh2, 0.0001);
|
||||
Assert.AreEqual(10.0, sut.TimestampSecStartCh3, 0.0001);
|
||||
|
||||
Assert.AreEqual(20.0, sut.TimestampSecEndCh1, 0.0001);
|
||||
Assert.AreEqual(20.0, sut.TimestampSecEndCh2, 0.0001);
|
||||
Assert.AreEqual(20.0, sut.TimestampSecEndCh3, 0.0001);
|
||||
|
||||
Assert.AreEqual(105.0, sut.VolumeLtrStartRaw, 0.0001);
|
||||
Assert.AreEqual(157.0, sut.VolumeLtrEndRaw, 0.0001);
|
||||
|
||||
Assert.AreEqual(10.0, sut.TimestampSecStart, 0.0001);
|
||||
Assert.AreEqual(20.0, sut.TimestampSecEnd, 0.0001);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void METHOD()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
[TestClass]
|
||||
public class GenesisSmartReaderThreadedReadTests
|
||||
{
|
||||
private const int ChannelCount = 3;
|
||||
|
||||
private static GenesisCfg CreateCfg()
|
||||
{
|
||||
var cfg = new GenesisCfg(null);
|
||||
cfg.OptoComPortNr = 7;
|
||||
cfg.RfidComPortNr = 8;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object target, string fieldName, object value)
|
||||
{
|
||||
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
||||
|
||||
field.SetValue(target, value);
|
||||
}
|
||||
|
||||
private static T GetPrivateField<T>(object target, string fieldName)
|
||||
{
|
||||
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (field == null)
|
||||
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
||||
|
||||
return (T)field.GetValue(target);
|
||||
}
|
||||
|
||||
private static bool WaitUntil(Func<bool> condition, int timeoutMs = 1500, int pollMs = 20)
|
||||
{
|
||||
var start = Environment.TickCount;
|
||||
|
||||
while (Environment.TickCount - start < timeoutMs)
|
||||
{
|
||||
if (condition())
|
||||
return true;
|
||||
|
||||
Thread.Sleep(pollMs);
|
||||
}
|
||||
|
||||
return condition();
|
||||
}
|
||||
|
||||
private static void InitializeThreeChannelState(GenesisSmartReader reader)
|
||||
{
|
||||
SetPrivateField(reader, "volumeRawExtLast", new double[ChannelCount]);
|
||||
SetPrivateField(reader, "timestampExtLast", new double[ChannelCount]);
|
||||
|
||||
SetPrivateField(reader, "lastVolumeRaw", new double[ChannelCount]);
|
||||
SetPrivateField(reader, "lastTimestamp", new double[ChannelCount]);
|
||||
|
||||
SetPrivateField(reader, "volumeLtr", new[] { 0.0, 0.0, 0.0 });
|
||||
SetPrivateField(reader, "volumeLtr0", new[] { 0.0, 0.0, 0.0 });
|
||||
|
||||
SetPrivateField(reader, "timestampSec", new[] { 0.0, 0.0, 0.0 });
|
||||
SetPrivateField(reader, "timestampSec0", new[] { 0.0, 0.0, 0.0 });
|
||||
}
|
||||
|
||||
private static FieldInfo GetAnyField(object target, string fieldName)
|
||||
{
|
||||
var field = target.GetType().GetField(
|
||||
fieldName,
|
||||
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (field == null)
|
||||
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private static void SetField(object target, string fieldName, object value)
|
||||
{
|
||||
GetAnyField(target, fieldName).SetValue(target, value);
|
||||
}
|
||||
|
||||
private static T GetField<T>(object target, string fieldName)
|
||||
{
|
||||
return (T)GetAnyField(target, fieldName).GetValue(target);
|
||||
}
|
||||
|
||||
private static void WaitForStartupFlushToFinish(GenesisSmartReader reader, int timeoutMs = 3000)
|
||||
{
|
||||
bool finished = WaitUntil(() =>
|
||||
{
|
||||
return !GetPrivateField<bool>(reader, "_startupFlushActive");
|
||||
}, timeoutMs);
|
||||
|
||||
Assert.IsTrue(finished, "Startup flush did not finish in time.");
|
||||
}
|
||||
|
||||
private static void ForceProcessingEnabled(GenesisSmartReader reader)
|
||||
{
|
||||
SetField(reader, "_startupFlushActive", false);
|
||||
SetField(reader, "_stopQueueData", false);
|
||||
SetField(reader, "dataStreamState", DataStreamState.ProcessAndSave);
|
||||
SetField(reader, "startDataProcessing", true);
|
||||
|
||||
var signal = GetField<AutoResetEvent>(reader, "_queueSignal");
|
||||
signal.Set();
|
||||
}
|
||||
|
||||
private static void EnqueueIncomingLine(GenesisSmartReader reader, string line)
|
||||
{
|
||||
var queue = GetField<System.Collections.Concurrent.ConcurrentQueue<(DateTime Timestamp, string Line)>>(
|
||||
reader, "_receivedLines");
|
||||
|
||||
var signal = GetField<AutoResetEvent>(reader, "_queueSignal");
|
||||
|
||||
queue.Enqueue((DateTime.UtcNow, line));
|
||||
signal.Set();
|
||||
}
|
||||
|
||||
private static void InstallSuccessfulProcessingOverride(GenesisSmartReader reader)
|
||||
{
|
||||
Func<string, bool> handler = line =>
|
||||
{
|
||||
var optoData = GetField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
int count = GetField<int>(reader, "optoDataCount");
|
||||
|
||||
optoData[count].Counter = count;
|
||||
optoData[count].SetFlags(OptoTelegramFlags.OK);
|
||||
|
||||
SetField(reader, "optoDataCount", count + 1);
|
||||
return true;
|
||||
};
|
||||
|
||||
SetField(reader, "TestProcessLineOverride", handler);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Start_ShouldOpenPort_AndStartBackgroundReadLoop()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
reader.Start();
|
||||
|
||||
Assert.IsTrue(fake.IsOpen);
|
||||
Assert.IsTrue(fake.OpenCalls >= 1);
|
||||
|
||||
var readLoopTask = GetPrivateField<System.Threading.Tasks.Task>(reader, "_readLoopTask");
|
||||
Assert.IsNotNull(readLoopTask);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessingLoop_ShouldConsumeQueuedLine()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
|
||||
ForceProcessingEnabled(reader);
|
||||
InstallSuccessfulProcessingOverride(reader);
|
||||
|
||||
EnqueueIncomingLine(reader, "TEST_LINE_1");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetField<int>(reader, "optoDataCount");
|
||||
return optoDataCount == 1;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Expected processing loop to consume queued line.");
|
||||
|
||||
int finalCount = GetField<int>(reader, "optoDataCount");
|
||||
Assert.AreEqual(1, finalCount);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessingLoop_ShouldConsumeQueuedLine_AndInsertTelegram()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
fake.Encoding = System.Text.Encoding.ASCII;
|
||||
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
|
||||
ForceProcessingEnabled(reader);
|
||||
|
||||
EnqueueIncomingLine(reader,
|
||||
"@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
return optoDataCount >= 1;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Expected processing loop to consume queued line.");
|
||||
|
||||
int finalCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
var optoData = GetPrivateField<OptoTelegramRaw[]>(reader, "optoData");
|
||||
|
||||
Assert.AreEqual(1, finalCount);
|
||||
Assert.AreEqual(1, optoData[0].IChannel());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProcessingLoop_ShouldConsumeAllQueuedLines()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
|
||||
ForceProcessingEnabled(reader);
|
||||
InstallSuccessfulProcessingOverride(reader);
|
||||
|
||||
EnqueueIncomingLine(reader, "TEST_LINE_1");
|
||||
EnqueueIncomingLine(reader, "TEST_LINE_2");
|
||||
EnqueueIncomingLine(reader, "TEST_LINE_3");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetField<int>(reader, "optoDataCount");
|
||||
return optoDataCount == 3;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Expected all queued lines to be processed.");
|
||||
|
||||
int finalCount = GetField<int>(reader, "optoDataCount");
|
||||
var queueAfter = GetField<System.Collections.Concurrent.ConcurrentQueue<(DateTime Timestamp, string Line)>>(
|
||||
reader, "_receivedLines");
|
||||
|
||||
Assert.AreEqual(3, finalCount);
|
||||
Assert.IsTrue(queueAfter.IsEmpty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IncomingLines_ShouldBeProcessedByBackgroundProcessingLoop()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
WaitForStartupFlushToFinish(reader);
|
||||
|
||||
fake.EnqueueLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
return optoDataCount >= 1;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Expected background processing loop to process line.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StopDataStreamProcessing_ShouldStopReadAndProcessingLoops()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
|
||||
reader.StopDataStreamProcessing();
|
||||
|
||||
var readLoopTask = GetPrivateField<System.Threading.Tasks.Task>(reader, "_readLoopTask");
|
||||
var readLoopCts = GetPrivateField<CancellationTokenSource>(reader, "_readLoopCts");
|
||||
var processLoopTask = GetPrivateField<System.Threading.Tasks.Task>(reader, "_processLoopTask");
|
||||
var processLoopCts = GetPrivateField<CancellationTokenSource>(reader, "_processLoopCts");
|
||||
|
||||
Assert.IsNull(readLoopTask);
|
||||
Assert.IsNull(readLoopCts);
|
||||
Assert.IsNull(processLoopTask);
|
||||
Assert.IsNull(processLoopCts);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IncomingLine_AfterStop_ShouldNotBeProcessed()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
|
||||
reader.StopDataStreamProcessing();
|
||||
|
||||
int before = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
fake.EnqueueLine("@h 1 0 0A1F59C4 00017A43 00115C45 72E1596B 00000400 00001998 7D91B652 7D4F37E6 000191E6 0C 062E4A9C 5331");
|
||||
|
||||
Thread.Sleep(300);
|
||||
|
||||
int after = GetPrivateField<int>(reader, "optoDataCount");
|
||||
|
||||
Assert.AreEqual(before, after, "No new telegram should be processed after stop.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvalidLine_ShouldNotCrashProcessingLoop()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
reader.Start();
|
||||
WaitForStartupFlushToFinish(reader);
|
||||
|
||||
fake.EnqueueLine("INVALID_LINE_THAT_WILL_NOT_PARSE");
|
||||
fake.EnqueueLine("@h 3 0 0A1DF1D5 00017EA8 00118037 741F80F3 00000400 00001998 7E58A62E 7CC2C606 000191E6 0C 062E5BAE D40E");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
return optoDataCount >= 1;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Processing loop should survive invalid input and continue.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StartStop_StartAgain_ShouldStillProcessData()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
InitializeThreeChannelState(reader);
|
||||
|
||||
reader.Start();
|
||||
reader.StopDataStreamProcessing();
|
||||
|
||||
reader.Start();
|
||||
WaitForStartupFlushToFinish(reader);
|
||||
|
||||
fake.EnqueueLine("@h 2 0 0A1B1FE8 00017B7F 00116B56 72B77427 00000400 0000199A 7DC09688 7B570006 000191E6 0C 062E5326 95BD");
|
||||
|
||||
bool processed = WaitUntil(() =>
|
||||
{
|
||||
int optoDataCount = GetPrivateField<int>(reader, "optoDataCount");
|
||||
return optoDataCount >= 1;
|
||||
}, 3000);
|
||||
|
||||
Assert.IsTrue(processed, "Reader should still process data after restart.");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Start_ShouldOpenPort_AndStartBothBackgroundLoops()
|
||||
{
|
||||
var fake = new FakeSerialDriver();
|
||||
var reader = new GenesisSmartReader(CreateCfg(), () => fake);
|
||||
|
||||
reader.Initialize();
|
||||
reader.Start();
|
||||
|
||||
Assert.IsTrue(fake.IsOpen);
|
||||
Assert.IsTrue(fake.OpenCalls >= 1);
|
||||
|
||||
var readLoopTask = GetPrivateField<System.Threading.Tasks.Task>(reader, "_readLoopTask");
|
||||
var processLoopTask = GetPrivateField<System.Threading.Tasks.Task>(reader, "_processLoopTask");
|
||||
|
||||
Assert.IsNotNull(readLoopTask);
|
||||
Assert.IsNotNull(processLoopTask);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+195
@@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.common;
|
||||
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
|
||||
|
||||
namespace TBFTests.Rig.RegisterReaders.GenesisRegReader.implementations
|
||||
{
|
||||
[TestClass]
|
||||
public class GenesisSmartReader_Q3Test
|
||||
{
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldReturnInvalid_WhenRawDataIsNull()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
InitializeReaderForQ3Test(sut);
|
||||
|
||||
SetPrivateField(sut, "_rawStartEndByChannel", null);
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 1000.0, refTime: 120.0, initCalibFactor: 15625.0);
|
||||
|
||||
Assert.IsFalse(sut.Q3CalibValid);
|
||||
Assert.AreEqual(0.0, sut.Q3CalibValue, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldReturnInvalid_WhenNoSamplesConditionIsTrue()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
InitializeReaderForQ3Test(sut);
|
||||
|
||||
SetPrivateField(sut, "_rawStartEndByChannel", CreateMinimalStartEndData());
|
||||
|
||||
Assert.IsTrue(sut.NoSamples, "Expected NoSamples to be true for this test.");
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 1000.0, refTime: 120.0, initCalibFactor: 15625.0);
|
||||
|
||||
Assert.IsFalse(sut.Q3CalibValid);
|
||||
Assert.AreEqual(0.0, sut.Q3CalibValue, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldReturnInvalid_WhenRefVolumeIsZero()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
|
||||
InvokePrivateByName(sut, "PrepareCalculatedChannelDataForTest", true);
|
||||
|
||||
Assert.IsFalse(sut.NoSamples, "Prepared data should produce valid samples.");
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 0.0, refTime: 120.0, initCalibFactor: 15625.0);
|
||||
|
||||
Assert.IsFalse(sut.Q3CalibValid);
|
||||
Assert.AreEqual(0.0, sut.Q3CalibValue, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldReturnInvalid_WhenRefTimeIsZero()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
|
||||
InvokePrivateByName(sut, "PrepareCalculatedChannelDataForTest", true);
|
||||
|
||||
Assert.IsFalse(sut.NoSamples, "Prepared data should produce valid samples.");
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 1000.0, refTime: 0.0, initCalibFactor: 15625.0);
|
||||
|
||||
Assert.IsFalse(sut.Q3CalibValid);
|
||||
Assert.AreEqual(0.0, sut.Q3CalibValue, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldReturnInvalid_WhenInitCalibFactorIsZero()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
|
||||
InvokePrivateByName(sut, "PrepareCalculatedChannelDataForTest", true);
|
||||
|
||||
Assert.IsFalse(sut.NoSamples, "Prepared data should produce valid samples.");
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 1000.0, refTime: 120.0, initCalibFactor: 0.0);
|
||||
|
||||
Assert.IsFalse(sut.Q3CalibValid);
|
||||
Assert.AreEqual(0.0, sut.Q3CalibValue, 0.000001);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetQ3Calibration_ShouldProduceNonNegativeResult_WithPreparedSimulationData()
|
||||
{
|
||||
var sut = new GenesisSmartReader();
|
||||
|
||||
InvokePrivateByName(sut, "PrepareCalculatedChannelDataForTest", true);
|
||||
|
||||
Assert.IsFalse(sut.NoSamples, "Prepared data should produce valid samples.");
|
||||
|
||||
sut.GetQ3Calibration(refVolume: 1.0, refTime: 120.0, initCalibFactor: 15625.0);
|
||||
|
||||
Assert.IsTrue(sut.Q3CalibValue >= 0.0);
|
||||
}
|
||||
|
||||
private static void InitializeReaderForQ3Test(GenesisSmartReader reader)
|
||||
{
|
||||
SetPrivateField(reader, "_rawStartEndByChannel", null);
|
||||
SetPrivateField(reader, "_recalculatedStartEndByChannel", null);
|
||||
SetPrivateField(reader, "optoDataCount", 0);
|
||||
|
||||
reader.TestStartTelegramIx = -1;
|
||||
reader.TestEndTelegramIx = -1;
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw[][] CreateMinimalStartEndData()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
CreateRecord(0.0, 0.0),
|
||||
CreateRecord(15625.0, 120.0)
|
||||
},
|
||||
new OptoTelegramRaw[2],
|
||||
new OptoTelegramRaw[2]
|
||||
};
|
||||
}
|
||||
|
||||
private static OptoTelegramRaw CreateRecord(double volumeRawExt, double timestampExt)
|
||||
{
|
||||
return new OptoTelegramRaw
|
||||
{
|
||||
VolumeRawExt = volumeRawExt,
|
||||
TimestampExt = timestampExt
|
||||
};
|
||||
}
|
||||
|
||||
private static object InvokePrivateByName(object target, string methodName, params object[] args)
|
||||
{
|
||||
Type type = target.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var candidates = type.GetMethods(
|
||||
BindingFlags.Instance |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic |
|
||||
BindingFlags.DeclaredOnly)
|
||||
.Where(m => m.Name == methodName)
|
||||
.ToList();
|
||||
|
||||
foreach (var method in candidates)
|
||||
{
|
||||
var parameters = method.GetParameters();
|
||||
|
||||
if (parameters.Length != (args?.Length ?? 0))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
return method.Invoke(target, args);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
Assert.Fail($"Method '{methodName}' not found or no matching overload accepted the provided arguments.");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SetPrivateField(object target, string fieldName, object value)
|
||||
{
|
||||
Type type = target.GetType();
|
||||
|
||||
while (type != null)
|
||||
{
|
||||
var field = type.GetField(
|
||||
fieldName,
|
||||
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly);
|
||||
|
||||
if (field != null)
|
||||
{
|
||||
field.SetValue(target, value);
|
||||
return;
|
||||
}
|
||||
|
||||
type = type.BaseType;
|
||||
}
|
||||
|
||||
Assert.Fail($"Field '{fieldName}' not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,8 +108,13 @@
|
||||
<Compile Include="Rig\Output\FileWriters\Enhanced\WriterTest.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\common\OptoTelegramRawTest.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\FakeSerialDriver.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisReaderTests.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReaderChannelAveragingTests.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReaderChannelTests.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReaderStopTests.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReaderTest.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReaderThreadedReadTests.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\GenesisRegReader\implementations\GenesisSmartReader_Q3Test.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\diagnosticLed\DiagnosticLedParserTest.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\hexLogger\HexFormatterTest.cs" />
|
||||
<Compile Include="Rig\RegisterReaders\iPerlASICReader\communication\C4\IperlHatProtocol\IperlHatFrameBuilderTests.cs" />
|
||||
|
||||
Reference in New Issue
Block a user