iPerl component updated + interface change: ulong DigitalInputs (it was uint), iPerlCommunication test method added, etc, version 1.5.75.

This commit is contained in:
Milan Hanajik 2015-08-11 08:50:32 +02:00
parent 40a43e46b4
commit e569a80ec2
27 changed files with 2742 additions and 38 deletions

View File

@ -56,7 +56,7 @@ namespace TBF.BenchControl.Elde
public float RValvePosition(int rvNr1) { return controlCom.RValvePosition(rvNr1); }
public float DivSamples(int ms) { return controlCom.DivSamples(ms); }
public int ScopeSamples(int i, int j, int k) { return controlCom.ScopeSamples(i, j, k); }
public uint DigitalInputs { get { return controlCom.DigitalInputs; } }
public ulong DigitalInputs { get { return controlCom.DigitalInputs; } }
public float AnalogInput(int adcNr0) { return controlCom.AnalogInput(adcNr0); }
public uint AnalogInputRaw(int adcNr0, int bank) { return controlCom.AnalogInputRaw(adcNr0, bank); } /// adcNr0: 0=RV1, 1=RV2,... bank: 0=RV, 1=Temp
public float ReferenceVolume { get { return controlCom.ReferenceVolume; } }

View File

@ -63,7 +63,7 @@ namespace TBF.BenchControl.Elde
public float RValvePosition(int rvNr1) { return 0; }
public float DivSamples(int ms) { return 0; }
public int ScopeSamples(int i, int j, int k) { return 0; }
public uint DigitalInputs { get { return 0; } }
public ulong DigitalInputs { get { return 0; } }
public float AnalogInput(int adcNr0) { return 0; }
public uint AnalogInputRaw(int adcNr0, int bank) { return 0; } /// bank0=RV, bank1=Temp
public float ReferenceVolume { get { return 0; } }

View File

@ -51,7 +51,7 @@ namespace TBF.BenchControl.Elde
}
public float DivSamples(int ms) { return ctrlBrdComponent.DIVSamples[ms, 0]; }
public int ScopeSamples(int i, int j, int k) { return ctrlBrdComponent.ScopeSamples[i, j, k]; }
public uint DigitalInputs { get { return ctrlBrdComponent.Vstupy; } }
public ulong DigitalInputs { get { return (ulong)ctrlBrdComponent.Vstupy; } }
public float AnalogInput(int adcNr0) { return ctrlBrdComponent.Analogy[adcNr0]; }
public uint AnalogInputRaw(int adcNr0, int bank) { return ctrlBrdComponent.AnalogyRaw[adcNr0, bank]; } /// bank0=RV, bank1=Temp
public float ReferenceVolume { get { return ctrlBrdComponent.ReferenceVolume; } }

View File

@ -25,7 +25,7 @@ namespace TBF.BenchControl.Elde
float RValvePosition(int rvNr1);
float DivSamples(int ms);
int ScopeSamples(int i, int j, int k);
uint DigitalInputs { get; }
ulong DigitalInputs { get; }
float AnalogInput(int adcNr0);
uint AnalogInputRaw(int adcNr0, int bank);
float ReferenceVolume { get; }

View File

@ -42,7 +42,8 @@ namespace TBF.BenchControl
Factories.Add(new Cameras.IdcCamera.IdcCameraFactory());
Factories.Add(new WaterMeters.iPerl.WaterMeterFactory()); /// iPerl
Factories.Add(new TestMethods.iPerlAdjustment.TestMethodFactory()); /// iPerlAdjustment
Factories.Add(new TestMethods.LeakTest.TestMethodFactory());
Factories.Add(new TestMethods.iPerlCommunication.TestMethodFactory()); /// iPerlCommunication
Factories.Add(new TestMethods.LeakTest.TestMethodFactory());
Factories.Add(new MettlerToledo.Standard.BalanceFactory()); /// MettlerToledo Balance
Factories.Add(new MettlerToledo.Standard.BalanceNewFactory()); /// MettlerToledoBalanceSN
Factories.Add(new MettlerToledo.Multi.BalanceFactory()); /// MettlerToledo-Multi

View File

@ -13,9 +13,9 @@ using TBF.BenchControl.WaterMeters.iPerl;
namespace TBF.BenchControl.TestMethods.iPerlAdjustment
{
public partial class iPerlCommunicationForm : Form, GenericDevices.IHasCompleted
public partial class iPerlAdjustmentForm : Form, GenericDevices.IHasCompleted
{
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm));
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlAdjustmentForm));
[DllImport("libRfid.dll", EntryPoint = "getDllVersion")]
@ -92,7 +92,7 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
/// <summary> Parameterless constructor for 3 watermeters </summary>
public iPerlCommunicationForm()
public iPerlAdjustmentForm()
{
InitializeComponent();
@ -151,7 +151,7 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
/// Constructor
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm(IList<GenericDevices.IWaterMeter> waterMeters)
public iPerlAdjustmentForm(IList<GenericDevices.IWaterMeter> waterMeters)
: this()
{
this.WaterMetersCount = waterMeters.Count;
@ -322,8 +322,6 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
private void readConfigBtn_Click(object sender, EventArgs e)
{
byte[] data;
int i = 0;
for (int group = 1; group <= 10; group++)
@ -336,23 +334,35 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
foreach (var wm in WaterMeters)
{
if (wm.DebugLevel == Entities.DebugMode.Normal && wm.Group == group)
if (wm.Group == group)
{
int r1 = openPort((uint)wm.RfidComPortNr);
int r2 = ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out data, 1000);
int r3 = closePort();
Text = string.Format("WM={0} Group={1}", wm.Name, group);
if (wm.DebugLevel == Entities.DebugMode.Normal)
{
byte[] data = null;
bool success = false;
int r1 = openPort((uint)wm.RfidComPortNr);
for (int j = 0; j < 3; j++)
{
if (0 == ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out data, 1000))
{
success = true;
break;
}
}
closePort();
if (r1==0 && r2==0 && r3==0)
{
errors[i++].Text = ConfigStruct.FromByteArray(data).ToString();
if (r1 == 0 && success && data != null)
{
errors[i].Text = ConfigStruct.FromByteArray(data).ToString(1);
}
else
{
errors[i].Text = "Cannot read configuration";
}
}
else
{
errors[i++].Text = "Cannot read configuration";
}
}
else
i++;
}
}
}
}

View File

@ -3,7 +3,7 @@
///
namespace TBF.BenchControl.TestMethods.iPerlAdjustment
{
partial class iPerlCommunicationForm
partial class iPerlAdjustmentForm
{
/// <summary>
/// Required designer variable.

View File

@ -20,9 +20,9 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
///
delegate void ErrorsFormDlgt(iPerlAdjustmentSeq myRef);
///
void OpenWMErrorsForm(iPerlAdjustmentSeq myRef)
void OpenIPerlCommForm(iPerlAdjustmentSeq myRef)
{
myRef.modelessDlg = new iPerlCommunicationForm(WaterMeters);
myRef.modelessDlg = new iPerlAdjustmentForm(WaterMeters);
modelessDlg.Show();
}
@ -75,7 +75,7 @@ namespace TBF.BenchControl.TestMethods.iPerlAdjustment
///
/// Show the modeless dialog with error indication
///
Program.MainWnd.Invoke(new ErrorsFormDlgt(OpenWMErrorsForm), this);
Program.MainWnd.Invoke(new ErrorsFormDlgt(OpenIPerlCommForm), this);
loop:

View File

@ -0,0 +1,18 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class AllCompletedEventArgs : EventArgs
{
public string CommMessage;
public AllCompletedEventArgs(string commMessage)
{
this.CommMessage = commMessage;
}
}
}

View File

@ -0,0 +1,22 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class CommCompletedEventArgs : EventArgs
{
public int ThreadId;
public int WMNr;
public string CommMessage;
public CommCompletedEventArgs(int threadId, int wmNr, string commMessage)
{
this.ThreadId = threadId;
this.WMNr = wmNr;
this.CommMessage = commMessage;
}
}
}

View File

@ -0,0 +1,39 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;
using log4net;
using TBF.BenchControl;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class TestMethod : ComponentBase, GenericDevices.ITestMethod
{
private static readonly ILog log = LogManager.GetLogger(typeof(TestMethod));
public override string ToString() { return string.Format("TestMethods.Adjustment({0})", Cfg.ToString(1)); }
readonly TestMethodCfg testMethodCfg;
public bool Evaluate { get { return false; } }
public bool Publish { get { return false; } }
public bool CanTest(Entities.MetersKind meters) { return meters == Entities.MetersKind.Single; }
public TestMethod()
{
}
public TestMethod(TestMethodCfg cfg)
: base(cfg)
{
testMethodCfg = cfg;
log.Debug(this.ToString());
}
public IList<Event> Execute(Entities.Test test)
{
return (new iPerlCommunicationSeq()).Execute(test, testMethodCfg.TestParams);
}
}
}

View File

@ -0,0 +1,48 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class TestMethodCfg : ComponentCfgBase, Generic.IComponentCfg
{
public IComponent GetComponent(IList<IComponent> components) { return new TestMethod(this); }
public IComponentCfgCtrl GetControl() { return new TestMethodCfgCtrl(); }
/// <summary> Test parameters </summary>
[XmlIgnore]
public iPerlCommunicationParams TestParams;
public override IParamsProvider GetTestParams() { return TestParams; }
public override IParamsProvider CreateTestParams(Entities.Test test)
{
iPerlCommunicationParams testParams = new iPerlCommunicationParams();
testParams.UpdateTestParams(Name, test);
return testParams;
}
/// Private parameterless constructor invoked by all other (public) constructors
TestMethodCfg()
{
Name = "iPerlCommunication";
ParentName = string.Empty;
TestParams = new iPerlCommunicationParams();
}
public TestMethodCfg(IComponentFactory factory)
: this()
{
this.Factory = factory;
}
public string ToString(int i)
{
return string.Format("Name={0}", Name);
}
}
}

View File

@ -0,0 +1,72 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Windows.Forms;
using log4net;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public partial class TestMethodCfgCtrl : UserControl, IComponentCfgCtrl
{
static readonly ILog log = LogManager.GetLogger(typeof(TestMethodCfgCtrl));
public bool ShowMore { get { return false; } }
TestMethodCfg config;
public IComponentCfg Config
{
get { return config as IComponentCfg; }
set
{
config = value as TestMethodCfg;
Redraw();
}
}
public TestMethodCfgCtrl()
{
InitializeComponent();
}
private void EntryFormCfgCtrl_Load(object sender, EventArgs e)
{
Redraw();
}
public void Closing()
{
}
void Redraw()
{
if (config == null) return; /// Control was not loaded, settings were not changed
classNameLabel.Text = config.Factory.ClassName;
nameTextBox.Text = config.Name;
}
public void Unlock()
{
nameTextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
{
CfgUpdateFlags flags = CfgUpdateFlags.None;
return flags;
}
public CfgUpdateFlags UpdateCfg()
{
CfgUpdateFlags flags = CfgUpdateFlags.RestartRqrd;
if (config == null) return CfgUpdateFlags.Error; /// Control was not loaded, settings were not changed
config.Name = nameTextBox.Text;
return flags;
}
}
}

View File

@ -0,0 +1,87 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
partial class TestMethodCfgCtrl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.nameTextBox = new System.Windows.Forms.TextBox();
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(137, 57);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 5;
//
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(27, 60);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 4;
this.nameLabel.Text = "Name";
//
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(134, 33);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 3;
this.classNameLabel.Text = "ComonentName";
//
// BasicPrinterCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.nameTextBox);
this.Controls.Add(this.nameLabel);
this.Controls.Add(this.classNameLabel);
this.Name = "BasicPrinterCfgCtrl";
this.Size = new System.Drawing.Size(300, 200);
this.Load += new System.EventHandler(this.EntryFormCfgCtrl_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,24 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class TestMethodFactory : IComponentFactory
{
public string ClassName { get { return "iPerlCommunication"; } }
public void ResetStaticProperties() { TestMethod.ResetStaticProperties(); }
public IComponent DummyComponent() { return new TestMethod(); }
public IComponentCfg DefaultConfig() { return new TestMethodCfg(this); }
public IComponentCfg CmpntCfgFromCmpntEntity(Entities.Component component)
{
return ComponentCfgBase.CreateFromDbEntity(typeof(TestMethodCfg), component, this);
}
}
}

View File

@ -0,0 +1,546 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using log4net;
using TBF.Resources;
using TBF.BenchControl.WaterMeters.iPerl;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public partial class iPerlCommunicationForm : Form, GenericDevices.IHasCompleted
{
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationForm));
#region DLL_Interface
[DllImport("libRfid.dll", EntryPoint = "getDllVersion")]
public static extern unsafe int getDllVersion();
[DllImport("libRfid.dll", EntryPoint = "openPort")]
static extern unsafe int openPort(int comPort);
[DllImport("libRfid.dll", EntryPoint = "closePort")]
static extern unsafe int closePort();
[DllImport("libRfid.dll", EntryPoint = "readRequestPort")]
static extern unsafe int readRequestPort(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms);
[DllImport("libRfid.dll", EntryPoint = "writeRequestPort")]
static extern unsafe int writeRequestPort(MessageID messageId, int offset, int lenght, byte* ptr, int timeout_ms);
/// <summary>
/// Wrapper function with safe interface adn unsafe body
/// </summary>
/// <returns>Value returned by readRequestPort(...)</returns>
public static unsafe int ReadRequestPort(MessageID messageID, int offset, int lenght, out byte[] buffer, int timeout)
{
byte[] buf = new byte[1000];
int retv;
fixed (byte* pBuf = buf)
{
retv = readRequestPort(messageID, offset, lenght, pBuf, timeout);
buffer = new byte[lenght];
for (int i = 0; i < lenght; i++) buffer[i] = buf[i];
}
return retv;
}
/// <summary>
/// Wrapper function with safe interface adn unsafe body
/// </summary>
/// <returns>Value returned by writeRequestPort(...)</returns>
public static unsafe int WriteRequestPort(MessageID messageID, int offset, int lenght, byte[] buffer, int timeout)
{
int retv;
fixed (byte* pBuf = buffer)
{
retv = writeRequestPort(messageID, offset, lenght, pBuf, timeout);
}
return retv;
}
#endregion DLL_Interface
const int CommTimeout = 500;
const int MaxCommRetries = 3;
// Set to 'true' when the form closes
public bool Completed { get { return formCompleted; } }
bool formCompleted;
/// <summary> Number of text boxes for serial numbers </summary>
public readonly int WaterMetersCount;
readonly bool[] disabled;
Entities.TestResult tr;
int textBoxesCount;
Label[] labels;
TextBox[] messages;
static IList<WaterMeters.iPerl.WaterMeter> waterMeters;
Modbus.QuidoRS.QuidoRS quido;
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
static string activity;
static int currentGroup; /// form -> worker thread (0 = none)
static int lastGroup;
static IList<Thread> workerThreads;
static IList<int> rfidPortNrs;
static IList<bool> stopWorkerThreads; /// form -> worker thread
/// <summary> Parameterless constructor for 3 watermeters </summary>
public iPerlCommunicationForm()
{
InitializeComponent();
textBoxesCount = 48;
labels = new Label[48]
{
wmLabel1, wmLabel2, wmLabel3, wmLabel4, wmLabel5,
wmLabel6, wmLabel7, wmLabel8, wmLabel9, wmLabel10,
wmLabel11, wmLabel12, wmLabel13, wmLabel14, wmLabel15,
wmLabel16, wmLabel17, wmLabel18, wmLabel19, wmLabel20,
wmLabel21, wmLabel22, wmLabel23, wmLabel24, wmLabel25,
wmLabel26, wmLabel27, wmLabel28, wmLabel29, wmLabel30,
wmLabel31, wmLabel32, wmLabel33, wmLabel34, wmLabel35,
wmLabel36, wmLabel37, wmLabel38, wmLabel39, wmLabel40,
wmLabel41, wmLabel42, wmLabel43, wmLabel44, wmLabel45,
wmLabel46, wmLabel47, wmLabel48,
};
messages = new TextBox[48]
{
wmTextBox1, wmTextBox2, wmTextBox3, wmTextBox4, wmTextBox5,
wmTextBox6, wmTextBox7, wmTextBox8, wmTextBox9, wmTextBox10,
wmTextBox11, wmTextBox12, wmTextBox13, wmTextBox14, wmTextBox15,
wmTextBox16, wmTextBox17, wmTextBox18, wmTextBox19, wmTextBox20,
wmTextBox21, wmTextBox22, wmTextBox23, wmTextBox24, wmTextBox25,
wmTextBox26, wmTextBox27, wmTextBox28, wmTextBox29, wmTextBox30,
wmTextBox31, wmTextBox32, wmTextBox33, wmTextBox34, wmTextBox35,
wmTextBox36, wmTextBox37, wmTextBox38, wmTextBox39, wmTextBox40,
wmTextBox41, wmTextBox42, wmTextBox43, wmTextBox44, wmTextBox45,
wmTextBox46, wmTextBox47, wmTextBox48,
};
currentGroup = 0;
lastGroup = 0; /// group numbers are >=1, lastGroup == 0 means no group
workerThreads = new List<Thread>();
rfidPortNrs = new List<int>();
stopWorkerThreads = new List<bool>();
formCompleted = false;
tr = null;
/// Find QuidoRS
foreach (var comp in StateMachine.Components)
{
if (comp is Modbus.QuidoRS.QuidoRS)
{
quido = comp as Modbus.QuidoRS.QuidoRS;
break;
}
}
/// Attach to 'CommCompleted' handler
CommCompletedHandler += delegate(object sender, CommCompletedEventArgs args)
{
if (InvokeRequired)
{
Invoke(new EventHandler<CommCompletedEventArgs>(DoOnCommCompleted), sender, args);
}
else DoOnCommCompleted(sender, args);
};
/// Attach to 'AllCompleted' handler
AllCompletedHandler += delegate(object sender, AllCompletedEventArgs args)
{
if (InvokeRequired)
{
Invoke(new EventHandler<AllCompletedEventArgs>(DoOnAllCompleted), sender, args);
}
else DoOnAllCompleted(sender, args);
};
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm(IList<GenericDevices.IWaterMeter> waterMeters, string activity)
: this()
{
iPerlCommunicationForm.activity = activity;
this.WaterMetersCount = waterMeters.Count;
iPerlCommunicationForm.waterMeters = new List<WaterMeters.iPerl.WaterMeter>();
foreach (var wm in waterMeters)
{
WaterMeters.iPerl.WaterMeter iPerlWM = wm as WaterMeters.iPerl.WaterMeter;
iPerlCommunicationForm.waterMeters.Add(iPerlWM);
if (iPerlWM.Group > lastGroup) lastGroup = iPerlWM.Group;
if (!rfidPortNrs.Contains(iPerlWM.RfidComPortNr))
{
rfidPortNrs.Add(iPerlWM.RfidComPortNr);
if (workerThreads.Count < 1)
{
Thread thread = new Thread(iPerlCommunicationForm.Worker);
workerThreads.Add(thread);
stopWorkerThreads.Add(false);
thread.Start(); /// TODO: start with arguments: thread.Start(workerThreads.Count - 1);
}
}
}
activityLabel.Text = activity;
ShuffleTextBoxes(this.WaterMetersCount, Program.LineSize);
disabled = new bool[this.WaterMetersCount];
}
/// <summary>
/// Make sure the layout of labels/text boxes on the screen
/// corresponds to the layout of watermeters of the test bench.
/// </summary>
/// <param name="wmsCount">Number of watermeters</param>
/// <param name="lineSize">Number of watermeters in one line</param>
void ShuffleTextBoxes(int wmsCount, int lineSize)
{
if (wmsCount < textBoxesCount && lineSize > 0)
{
int nrLines = (wmsCount + lineSize - 1) / lineSize;
int gap = (textBoxesCount - wmsCount) / nrLines;
int dest = 0;
for (int l = 0; l < nrLines; l++)
{
for (int i = 0; i < lineSize; i++)
{
labels[dest] = labels[l * lineSize + l * gap + i];
messages[dest] = messages[l * lineSize + l * gap + i];
dest++;
}
}
textBoxesCount = wmsCount;
}
}
void Localize()
{
Text = Strings.Water_Meter_States;
for (int i = 0; i < textBoxesCount; i++)
{
labels[i].Text = string.Format("iPerl{0}", i + 1);
}
}
private void iPerlCommunicationForm_Load(object sender, EventArgs e)
{
Localize();
//Height = 50 + 90 * WaterMetersCount;
for (int i = 0; i < textBoxesCount; i++)
{
if (disabled != null && i < disabled.Length && disabled[i])
{
labels[i].Visible = messages[i].Visible = false;
}
else
{
labels[i].Visible = messages[i].Visible = true;
messages[i].Text = "---";
}
}
///
/// Set QuidoRS outputs and start the whole communication process
/// by incrementing 'currentGroup'.
///
if (quido != null)
{
quido.SetOutputs((ushort)(16 - currentGroup - 1));
Thread.Sleep(200);
}
currentGroup++;
}
private void NormalClose()
{
CommCompletedHandler = null;
AllCompletedHandler = null;
formCompleted = true;
DialogResult = DialogResult.OK;
Close();
}
void OnAdjustmentInProgress(object sender, UiBridge.AdjustmentInProgressEventArgs args)
{
tr = args.TestResult;
Redraw();
}
void Redraw()
{
if (tr != null)
{
for (int i = 0; i < textBoxesCount; i++)
{
messages[i].Text = tr.Meters[i].VolumeErrorPct.ToString("F1");
}
}
}
private void WMErrorsForm_Paint(object sender, PaintEventArgs e)
{
//if (tr != null)
//{
// System.Drawing.Graphics graphics = this.CreateGraphics();
// for (int i = 0; i < WaterMetersCount; i++)
// {
// PaintOne(graphics, rects[i], tr.Meters[i].VolumeErrorPct, tr.ErrLimLo, tr.ErrLimHi);
// }
//}
}
#region Forced close handling
public void StartForceCloseHandler()
{
UiBridge.Bridge.CloseModelessFormHandler += delegate(object sender, EventArgs args)
{
if (InvokeRequired) { Invoke(new EventHandler<EventArgs>(OnForceClose), sender, args); }
else OnForceClose(sender, args);
};
}
void OnForceClose(object sender, EventArgs args)
{
CommCompletedHandler = null;
AllCompletedHandler = null;
DialogResult = DialogResult.Cancel;
Close();
}
#endregion
static void Worker()
{
int threadId = 0;
int rfidPortNr = rfidPortNrs[threadId];
for (int group = 1; group <= lastGroup; group++)
{
while (currentGroup != group && !stopWorkerThreads[threadId]) Thread.Sleep(50);
if (stopWorkerThreads[threadId]) break;
int wmNr = 0;
foreach (var wm in waterMeters)
{
if ((wm.RfidComPortNr == rfidPortNr) && (wm.Group == group))
{
if (wm.DebugLevel == Entities.DebugMode.Normal)
{
if (activity.Equals("Read configuration")) ReadConfig(wm, threadId, wmNr);
else if (activity.Equals("Set to test mode")) SetToTestMode(wm, threadId, wmNr);
else if (activity.Equals("Set to active mode")) SetToActiveMode(wm, threadId, wmNr);
else OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Invalid activity"));
}
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Simulation"));
}
break;
}
wmNr++;
}
}
}
static void ReadConfig(WaterMeters.iPerl.WaterMeter wm, int threadId, int wmNr)
{
bool success = (0 == openPort(wm.RfidComPortNr)); /// Open RFID port
byte[] cfg = null;
if (success)
{
success = false;
/// Read configuration
for (int j = 0; j < MaxCommRetries; j++)
{
if (0 == ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out cfg, CommTimeout)) { success = true; break; }
}
}
closePort(); /// Close RFID port
if (success)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, ConfigStruct.FromByteArray(cfg).ToString(1)));
}
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Cannot read configuration"));
}
}
static void SetToTestMode(WaterMeters.iPerl.WaterMeter wm, int threadId, int wmNr)
{
bool success = (openPort(wm.RfidComPortNr) == 0); /// Open RFID port
if (success)
{
success = false;
/// Switch to test mode
byte[] cmd = new byte[1] { (byte)7 };
for (int j = 0; j < MaxCommRetries; j++)
{
if (0 == WriteRequestPort(MessageID.Command, 0, 1, cmd, CommTimeout)) { success = true; break; }
}
}
byte[] cfg = null;
if (success)
{
success = false;
/// Read configuration
for (int j = 0; j < MaxCommRetries; j++)
{
if (0 == ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out cfg, CommTimeout)) { success = true; break; }
}
}
closePort(); /// Close RFID port
if (success)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, ConfigStruct.FromByteArray(cfg).ToString(1)));
}
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Cannot switch to test mode"));
}
}
static void SetToActiveMode(WaterMeters.iPerl.WaterMeter wm, int threadId, int wmNr)
{
bool success = (openPort(wm.RfidComPortNr) == 0); /// Open RFID port
if (success)
{
success = false;
/// Switch to active mode
byte[] cmd = new byte[1] { (byte)6 };
for (int j = 0; j < MaxCommRetries; j++)
{
if (0 == WriteRequestPort(MessageID.Command, 0, 1, cmd, CommTimeout)) { success = true; break; }
}
}
byte[] cfg = null;
if (success)
{
success = false;
/// Read configuration
for (int j = 0; j < MaxCommRetries; j++)
{
if (0 == ReadRequestPort(MessageID.Configuration, 0, ConfigStruct.Length, out cfg, CommTimeout)) { success = true; break; }
}
}
closePort(); /// Close RFID port
if (success)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, ConfigStruct.FromByteArray(cfg).ToString(1)));
}
else
{
OnCommCompleted(null, new CommCompletedEventArgs(threadId, wmNr, "Cannot switch to active mode"));
}
}
/// <summary>
/// Called when communication with one watermeter is completed
/// </summary>
public static void OnCommCompleted(object sender, CommCompletedEventArgs data)
{
if (CommCompletedHandler == null) return;
try { CommCompletedHandler(sender, data); }
catch (Exception e) { log.Error("CommCompletedHandler(...) failed", e); }
}
public static event EventHandler<CommCompletedEventArgs> CommCompletedHandler;
void DoOnCommCompleted(object sender, CommCompletedEventArgs data)
{
messages[data.WMNr].Text = data.CommMessage;
if (currentGroup < lastGroup)
{
if (quido != null)
{
quido.SetOutputs((ushort)(16 - currentGroup - 1));
Thread.Sleep(200);
}
currentGroup++;
}
else
{
workerThreads[data.ThreadId].Join(2000);
NormalClose();
}
}
/// <summary>
/// Called when communication with all watermeters is completed
/// </summary>
public static void OnAllCompleted(object sender, AllCompletedEventArgs data)
{
if (AllCompletedHandler == null) return;
try { AllCompletedHandler(sender, data); }
catch (Exception e) { log.Error("AllCompletedHandler(...) failed", e); }
}
public static event EventHandler<AllCompletedEventArgs> AllCompletedHandler;
void DoOnAllCompleted(object sender, AllCompletedEventArgs data)
{
Text = data.CommMessage;
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,96 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
using TBF.Resources;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class iPerlCommunicationParams : TestParamsBase, IParamsProvider, ITestParams
{
public string Activity; /// Communication activity
public override void InitializeAll()
{
Activity = "Read Configuration";
}
string[] paramNames = new string[]
{
Strings.Activity,
};
public override string ParamName(int i) { return paramNames[i]; }
public override int ParamsCount() { return paramNames.Length; }
public override string ToString(int i)
{
switch (i)
{
case 0: return Activity;
default: return string.Empty;
}
}
public void UpdateParam(int i, string strValue)
{
switch (i)
{
case 0: Activity = strValue; return;
default: return;
}
}
public bool ValidateParam(int i, string strValue, out string message)
{
message = string.Empty;
switch (i)
{
case 0:
return true;
default:
message = "Invalid index";
return false;
}
}
public override void UpdateTestParams(Entities.ComponentTest dbEntity)
{
if (dbEntity == null) return;
try
{
iPerlCommunicationParams tmp = (iPerlCommunicationParams)(new XmlSerializer(typeof(iPerlCommunicationParams)))
.Deserialize(new StringReader(dbEntity.Parameters));
testParamsEntity = dbEntity;
componentName = dbEntity.CmpntName;
test = dbEntity.Test;
Activity = tmp.Activity;
}
catch
{
}
}
/// <summary>
/// Parameterless constructor initializes the parameters
/// </summary>
public iPerlCommunicationParams()
{
}
public iPerlCommunicationParams(Entities.ComponentTest testParamsEntity, string componentName, Entities.Test test)
{
this.testParamsEntity = testParamsEntity;
this.componentName = componentName;
this.test = test;
}
}
}

View File

@ -0,0 +1,136 @@
///
/// Copyright (c) 2015 Sensus Metering Systems
/// Author: Milan Hanajík
///
using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using TBF.BenchControl;
using TBF.Boxes;
using TBF.Resources;
using TBF.UiBridge;
namespace TBF.BenchControl.TestMethods.iPerlCommunication
{
public class iPerlCommunicationSeq : Sequences.SequenceBase
{
private static readonly ILog log = LogManager.GetLogger(typeof(iPerlCommunicationSeq));
System.Windows.Forms.Form modelessDlg;
///
delegate void ICommFormFormDlgt(iPerlCommunicationSeq myRef, string activity);
///
void OpenIPerlCommForm(iPerlCommunicationSeq myRef, string activity)
{
myRef.modelessDlg = new iPerlCommunicationForm(WaterMeters, activity);
modelessDlg.Show();
}
/// <summary>
/// Flying start mass collection method sequence
/// </summary>
/// <param name="test">Test entity</param>
/// <returns>
/// Event.Done . . . . . . . OK
/// Event.UiCmdStop . . . . Stopped by the user using the on-screen button STOP
/// Event.OpArgumentError . Target flow is out of range
/// Event.Error . . . . . . Unspecified error
/// </returns>
public IList<Event> Execute(Entities.Test test, iPerlCommunicationParams testParams)
{
IList<Event> e = new List<Event>(); /// Events from currently running operations
Event retVal = Event.Done;
checkUiOp = new Operations.CheckUIOp(true); /// Runs in more then one state
processDataLoggingOp = new TBF.BenchControl.Operations.ProcessDataLoggingOp(processDataLogger, this);
//====================================
// Transition or SetRoute - Start
//====================================
switch (Transition(transitionBefore, TransitionContext.BeforeTest))
{
case Event.Error: { retVal = Event.Error; goto stopTest; }
case Event.UiCmdStop: { retVal = Event.UiCmdStop; goto stopTest; }
}
if (testParams.Activity.Contains("Simulate"))
{
IList<Event> rList = new List<Event>(1);
Entities.TestResult tstRslt = new Entities.TestResult(test, 1, Entities.MetersKind.Single);
if (testParams.Activity.Contains("Q1"))
{
tstRslt.VolumeMaster = tstRslt.VolumeCTV = 5;
for (int i = 0; i < WaterMeters.Count; i++)
{
tstRslt.Meters[i].VolumeMeter = 5;
tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV;
}
AddOrOverwriteResult(tstRslt);
}
else if (testParams.Activity.Contains("Q2"))
{
tstRslt.VolumeMaster = tstRslt.VolumeCTV = 5;
for (int i = 0; i < WaterMeters.Count; i++)
{
tstRslt.Meters[i].VolumeMeter = 5;
tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV;
}
AddOrOverwriteResult(tstRslt);
}
else if (testParams.Activity.Contains("Q3"))
{
tstRslt.VolumeMaster = tstRslt.VolumeCTV = 5;
for (int i = 0; i < WaterMeters.Count; i++)
{
tstRslt.Meters[i].VolumeMeter = 5;
tstRslt.Meters[i].VolumeRef = tstRslt.VolumeCTV;
}
AddOrOverwriteResult(tstRslt);
}
rList.Add(Event.Done);
return rList;
}
else
{
///
/// Show the modeless dialog with error indication
///
Program.MainWnd.Invoke(new ICommFormFormDlgt(OpenIPerlCommForm), new object[] { this, testParams.Activity });
}
loop:
//------------------------------------------------
Bridge.OnActivity(this, Strings.Test_in_progress);
//------------------------------------------------
/// Make sure the CycleBeginForm is closed so that water meter data (s/n) can be copied into results
if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stopTest;
/// Test 'Quit'
if ((modelessDlg is GenericDevices.IHasCompleted) && !(modelessDlg as GenericDevices.IHasCompleted).Completed)
{
goto loop; /// Modeless dilaog not closed, keep looping
}
modelessDlg = null; /// Modeless dialog is closed now
stopTest:
/// Transition sequence at the end of test
/// Prevent overwriting 'retVal' in case it was set to non-default value earlier
switch (Transition(transitionAfter, TransitionContext.AfterTest))
{
case Event.Error: { if (retVal == Event.Done) retVal = Event.Error; break; }
case Event.UiCmdStop: { if (retVal == Event.Done) retVal = Event.UiCmdStop; break; }
}
/// Create a list with one item 'retVal' (default is Event.Done) and return it
IList<Event> retList = new List<Event>(1);
retList.Add(retVal);
return retList;
}
}
}

View File

@ -119,5 +119,22 @@ namespace TBF.BenchControl.WaterMeters.iPerl
AlarmMask.ToString("X4"),
ConfigCheckSum.ToString("X4"));
}
}
public string ToString(int sel)
{
return string.Format("{1} PCBNr={6} TestModeCfg={7}",
Version,
MeterState,
TargetTimeVeryLowBatt,
TargetTimeLowBatt,
TestModeTime,
EmptyPipeThreshold,
PCBNumber[0].ToString("X2") + PCBNumber[1].ToString("X2") + PCBNumber[2].ToString("X2") + PCBNumber[3].ToString("X2") + PCBNumber[4].ToString("X2"),
TestModeConfig.ToString("X2"),
RadioAddress,
TempCalibration,
AlarmMask.ToString("X4"),
ConfigCheckSum.ToString("X4"));
}
}
}

View File

@ -120,10 +120,13 @@ namespace TBF.BenchControl.WaterMeters.iPerl
public void StopDevice()
{
stopWorkerThread = true;
workerThread.Join(2000);
optoSerialPort.Close();
optoPortOpen = false;
if (DebugLevel == Entities.DebugMode.Normal)
{
stopWorkerThread = true;
workerThread.Join(2000);
optoSerialPort.Close();
optoPortOpen = false;
}
}
/// <summary>

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.5.74.1")]
[assembly: AssemblyFileVersion("1.5.74.1")]
[assembly: AssemblyVersion("1.5.75.1")]
[assembly: AssemblyFileVersion("1.5.75.1")]

View File

@ -329,12 +329,31 @@
<DependentUpon>TestMethodCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlAdjustment\TestMethodFactory.cs" />
<Compile Include="BenchControl\TestMethods\iPerlAdjustment\iPerlCommunicationForm.cs">
<Compile Include="BenchControl\TestMethods\iPerlAdjustment\iPerlAdjustmentForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlAdjustment\iPerlCommunicationForm.designer.cs">
<Compile Include="BenchControl\TestMethods\iPerlAdjustment\iPerlAdjustmentForm.designer.cs">
<DependentUpon>iPerlAdjustmentForm.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlCommunication\AllCompletedEventArgs.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\CommCompletedEventArgs.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\iPerlCommunicationParams.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\iPerlCommunicationSeq.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\iPerlCommunicationForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlCommunication\iPerlCommunicationForm.designer.cs">
<DependentUpon>iPerlCommunicationForm.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlCommunication\TestMethod.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\TestMethodCfg.cs" />
<Compile Include="BenchControl\TestMethods\iPerlCommunication\TestMethodCfgCtrl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlCommunication\TestMethodCfgCtrl.designer.cs">
<DependentUpon>TestMethodCfgCtrl.cs</DependentUpon>
</Compile>
<Compile Include="BenchControl\TestMethods\iPerlCommunication\TestMethodFactory.cs" />
<Compile Include="BenchControl\WaterMeters\iPerl\CalibrationStruct.cs" />
<Compile Include="BenchControl\WaterMeters\iPerl\ConfigStruct.cs" />
<Compile Include="BenchControl\WaterMeters\iPerl\Enums.cs" />
@ -1484,9 +1503,15 @@
<EmbeddedResource Include="BenchControl\TestMethods\iPerlAdjustment\TestMethodCfgCtrl.resx">
<DependentUpon>TestMethodCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\TestMethods\iPerlAdjustment\iPerlCommunicationForm.resx">
<EmbeddedResource Include="BenchControl\TestMethods\iPerlAdjustment\iPerlAdjustmentForm.resx">
<DependentUpon>iPerlAdjustmentForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\TestMethods\iPerlCommunication\iPerlCommunicationForm.resx">
<DependentUpon>iPerlCommunicationForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\TestMethods\iPerlCommunication\TestMethodCfgCtrl.resx">
<DependentUpon>TestMethodCfgCtrl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="BenchControl\TestMethods\LeakTest\TestMethodCfgCtrl.resx">
<DependentUpon>TestMethodCfgCtrl.cs</DependentUpon>
</EmbeddedResource>