2015-08-11 06:50:32 +00:00
///
/// Copyright (c) 2015 Sensus Metering Systems
///
using System ;
using System.Collections.Generic ;
using System.Drawing ;
2015-08-14 17:20:47 +00:00
using System.Globalization ;
2015-08-11 06:50:32 +00:00
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
{
2015-08-17 14:02:30 +00:00
public enum CommErr
{
None = 0 ,
2015-09-11 12:15:32 +00:00
CommFailed ,
2015-08-17 14:02:30 +00:00
OpenPort ,
Read ,
Write ,
CmdActive ,
CmdTest ,
Verify ,
}
2015-08-11 06:50:32 +00:00
public partial class iPerlCommunicationForm : Form , GenericDevices . IHasCompleted
{
2015-08-19 11:04:47 +00:00
private static readonly ILog log = LogManager . GetLogger ( typeof ( iPerlCommunicationForm ) ) ;
2015-08-15 21:01:26 +00:00
protected static readonly ILog rfidDataLogger = LogManager . GetLogger ( "RfidData" ) ;
2015-08-11 06:50:32 +00:00
#region DLL_Interface
2015-08-19 11:04:47 +00:00
[DllImport("libRfid1.dll", EntryPoint = "getDllVersion")] static extern unsafe int getDllVersion1 ( ) ;
[DllImport("libRfid1.dll", EntryPoint = "openPort")] static extern unsafe int openPort1 ( int comPort ) ;
[DllImport("libRfid1.dll", EntryPoint = "closePort")] static extern unsafe int closePort1 ( ) ;
[DllImport("libRfid1.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort1 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
[DllImport("libRfid1.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort1 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
2015-08-11 06:50:32 +00:00
2015-08-19 11:04:47 +00:00
[DllImport("libRfid2.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion2 ( ) ;
[DllImport("libRfid2.dll", EntryPoint = "openPort")] static extern unsafe int openPort2 ( int comPort ) ;
[DllImport("libRfid2.dll", EntryPoint = "closePort")] static extern unsafe int closePort2 ( ) ;
[DllImport("libRfid2.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort2 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
[DllImport("libRfid2.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort2 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
2015-08-11 06:50:32 +00:00
2015-08-19 11:04:47 +00:00
[DllImport("libRfid3.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion3 ( ) ;
[DllImport("libRfid3.dll", EntryPoint = "openPort")] static extern unsafe int openPort3 ( int comPort ) ;
[DllImport("libRfid3.dll", EntryPoint = "closePort")] static extern unsafe int closePort3 ( ) ;
[DllImport("libRfid3.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort3 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
[DllImport("libRfid3.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort3 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
2015-08-11 06:50:32 +00:00
2015-08-19 11:04:47 +00:00
[DllImport("libRfid4.dll", EntryPoint = "getDllVersion")] public static extern unsafe int getDllVersion4 ( ) ;
[DllImport("libRfid4.dll", EntryPoint = "openPort")] static extern unsafe int openPort4 ( int comPort ) ;
[DllImport("libRfid4.dll", EntryPoint = "closePort")] static extern unsafe int closePort4 ( ) ;
[DllImport("libRfid4.dll", EntryPoint = "readRequestPort")] static extern unsafe int readRequestPort4 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
[DllImport("libRfid4.dll", EntryPoint = "writeRequestPort")] static extern unsafe int writeRequestPort4 ( MessageID messageId , int offset , int lenght , byte * ptr , int timeout_ms ) ;
2015-08-11 06:50:32 +00:00
2015-08-19 11:04:47 +00:00
/// <summary>
/// Wrapper function with safe interface and unsafe body
/// </summary>
/// <param name="boardNr">0..3</param>
/// <param name="comPort">Com port number</param>
/// <returns>Value returned by openPort(...)</returns>
2015-08-27 05:03:42 +00:00
public static unsafe int OpenPort ( WaterMeters . iPerl . WaterMeter wm )
2015-08-19 11:04:47 +00:00
{
2015-08-27 05:03:42 +00:00
if ( wm . DebugLevel ! = Entities . DebugMode . Normal ) return 0 ;
/// Normal function
switch ( wm . MuxBoardNr )
2015-08-19 11:04:47 +00:00
{
default :
2015-08-22 18:37:43 +00:00
case 1 : return openPort1 ( cfg . RfidPortNrBoard1 ) ;
case 2 : return openPort2 ( cfg . RfidPortNrBoard2 ) ;
case 3 : return openPort3 ( cfg . RfidPortNrBoard3 ) ;
case 4 : return openPort4 ( cfg . RfidPortNrBoard4 ) ;
2015-08-19 11:04:47 +00:00
}
}
2015-08-15 21:01:26 +00:00
/// <summary>
/// Wrapper function with safe interface and unsafe body
/// </summary>
2015-08-19 11:04:47 +00:00
/// <param name="boardNr">0..3</param>
/// <param name="comPort">Com port number</param>
2015-08-15 21:01:26 +00:00
/// <returns>Value returned by openPort(...)</returns>
2015-08-27 05:03:42 +00:00
public static unsafe int ClosePort ( WaterMeters . iPerl . WaterMeter wm )
2015-08-15 21:01:26 +00:00
{
2015-08-27 05:03:42 +00:00
if ( wm . DebugLevel ! = Entities . DebugMode . Normal ) return 0 ;
/// Normal function
switch ( wm . MuxBoardNr )
2015-08-19 11:04:47 +00:00
{
default :
2015-08-22 18:37:43 +00:00
case 1 : return closePort1 ( ) ;
case 2 : return closePort2 ( ) ;
case 3 : return closePort3 ( ) ;
case 4 : return closePort4 ( ) ;
2015-08-19 11:04:47 +00:00
}
2015-08-15 21:01:26 +00:00
}
2015-08-19 11:04:47 +00:00
/// <summary>
2015-08-15 21:01:26 +00:00
/// Wrapper function with safe interface and unsafe body
2015-08-11 06:50:32 +00:00
/// </summary>
/// <returns>Value returned by readRequestPort(...)</returns>
2015-08-27 05:03:42 +00:00
public static unsafe int ReadRequestPort ( WaterMeters . iPerl . WaterMeter wm , MessageID messageID , int offset , int lenght , out byte [ ] buffer , int timeout )
2015-08-11 06:50:32 +00:00
{
2015-08-27 05:03:42 +00:00
byte [ ] buf = new byte [ 200 ] ;
2015-08-11 06:50:32 +00:00
int retv ;
fixed ( byte * pBuf = buf )
{
2015-08-27 05:03:42 +00:00
if ( wm . DebugLevel = = Entities . DebugMode . Normal )
{
/// Normal function
switch ( wm . MuxBoardNr )
{
default :
case 1 : retv = readRequestPort1 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 2 : retv = readRequestPort2 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 3 : retv = readRequestPort3 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 4 : retv = readRequestPort4 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
}
}
else
{
/// Simulation
if ( messageID = = MessageID . Configuration )
{
}
else if ( messageID = = MessageID . Calibration )
{
}
else if ( messageID = = MessageID . MetrologyMemory )
{
}
2015-09-06 21:36:14 +00:00
if ( wm . Name . Equals ( "iPerl13" ) )
retv = 2 ;
else
retv = 0 ;
2015-08-27 05:03:42 +00:00
}
2015-08-19 11:04:47 +00:00
2015-08-11 06:50:32 +00:00
buffer = new byte [ lenght ] ;
for ( int i = 0 ; i < lenght ; i + + ) buffer [ i ] = buf [ i ] ;
2015-09-16 14:30:30 +00:00
2015-09-21 14:29:12 +00:00
string name = string . Format ( "{0}({1})" , wm . Name , wm . SerialNr ) ;
///
2015-09-16 14:30:30 +00:00
if ( ( messageID = = MessageID . Configuration ) & & ( offset = = 0 ) & & ( lenght = = WaterMeters . iPerl . ConfigStruct . Length ) )
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: ReadRequestPort({1},...) returned {2} {3}" , name , messageID , retv , ( retv ! = 0 ) ? "!" : WaterMeters . iPerl . ConfigStruct . FromByteArray ( buffer ) . ToString ( ) ) ;
2015-09-16 14:30:30 +00:00
}
else if ( ( messageID = = MessageID . Calibration ) & & ( offset = = 0 ) & & ( lenght = = WaterMeters . iPerl . CalibrationStruct . Length ) )
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: ReadRequestPort({1},...) returned {2} {3}" , name , messageID , retv , ( retv ! = 0 ) ? "!" : WaterMeters . iPerl . CalibrationStruct . FromByteArray ( buffer ) . ToString ( ) ) ;
2015-09-16 14:30:30 +00:00
}
else
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: ReadRequestPort({1}, {2}, {3}, ...) returned {4} {5}" , name , messageID , offset , lenght , retv , ( retv ! = 0 ) ? "!" : "" ) ;
2015-09-16 14:30:30 +00:00
}
2015-08-11 06:50:32 +00:00
}
return retv ;
}
/// <summary>
/// Wrapper function with safe interface adn unsafe body
/// </summary>
/// <returns>Value returned by writeRequestPort(...)</returns>
2015-08-27 05:03:42 +00:00
public static unsafe int WriteRequestPort ( WaterMeters . iPerl . WaterMeter wm , MessageID messageID , int offset , int lenght , byte [ ] buffer , int timeout )
2015-08-11 06:50:32 +00:00
{
int retv ;
fixed ( byte * pBuf = buffer )
{
2015-08-27 05:03:42 +00:00
if ( wm . DebugLevel = = Entities . DebugMode . Normal )
{
/// Normal function
switch ( wm . MuxBoardNr )
{
default :
case 1 : retv = writeRequestPort1 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 2 : retv = writeRequestPort2 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 3 : retv = writeRequestPort3 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
case 4 : retv = writeRequestPort4 ( messageID , offset , lenght , pBuf , timeout ) ; break ;
}
}
else
{
/// Simulation
if ( messageID = = MessageID . Configuration )
{
}
else if ( messageID = = MessageID . Calibration )
{
}
else if ( messageID = = MessageID . MetrologyMemory )
{
}
retv = 0 ;
}
2015-08-19 11:04:47 +00:00
2015-09-21 14:29:12 +00:00
string name = string . Format ( "{0}({1})" , wm . Name , wm . SerialNr ) ;
///
if ( lenght = = 1 )
2015-08-15 21:01:26 +00:00
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: WriteRequestPort({2}, {3}, {4}, {5}) returned {1} {6}" , name , retv , messageID , offset , lenght , pBuf [ 0 ] . ToString ( "X2" ) , ( retv ! = 0 ) ? "!" : "" ) ;
2015-08-15 21:01:26 +00:00
}
else if ( lenght = = 2 )
{
2015-09-16 14:30:30 +00:00
if ( messageID = = MessageID . Calibration & & offset = = 2 )
{
UInt16 calibFactor = ( UInt16 ) ( pBuf [ 0 ] + 256 * pBuf [ 1 ] ) ;
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: WriteRequestPort(calibFactor={1}) returned {2} {3}" , name , calibFactor , retv , ( retv ! = 0 ) ? "!" : "" ) ;
2015-09-16 14:30:30 +00:00
}
else
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: WriteRequestPort({2}, {3}, {4}, {5} {6}) returned {1} {7}" , name , retv , messageID , offset , lenght , pBuf [ 0 ] . ToString ( "X2" ) , pBuf [ 1 ] . ToString ( "X2" ) , ( retv ! = 0 ) ? "!" : "" ) ;
2015-09-16 14:30:30 +00:00
}
2015-08-15 21:01:26 +00:00
}
else
{
2015-09-21 14:29:12 +00:00
rfidDataLogger . InfoFormat ( "{0}: WriteRequestPort({2}, {3}, {4}, {5} {6} ...) returned {1} {7}" , name , retv , messageID , offset , lenght , pBuf [ 0 ] . ToString ( "X2" ) , pBuf [ 1 ] . ToString ( "X2" ) , ( retv ! = 0 ) ? "!" : "" ) ;
2015-08-15 21:01:26 +00:00
}
}
2015-08-11 06:50:32 +00:00
return retv ;
}
#endregion DLL_Interface
2015-08-14 17:20:47 +00:00
const string ReadConfigurationStr = "Read configuration" ; /// Example: "Read configuration" or "Read configuration if enabled"
const string SetTestModeStr = "Set Test mode" ; /// Example: "Set Test mode" or "Set Test mode A0" (hexadecimal number is the required 'testModeConfig'
2015-08-14 12:33:36 +00:00
const string SetActiveModeStr = "Set Active mode" ;
const string ReadCalibrationStr = "Read calibration" ;
const string WriteCalibrationFactorStr = "Write calibration factor" ;
const string ResetQ2CorrectionStr = "Reset Q2 correction" ;
const string WriteQ2CorrectionStr = "Write Q2 correction" ;
2015-08-11 06:50:32 +00:00
// 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 ;
int textBoxesCount ;
Label [ ] labels ;
2015-09-21 14:29:12 +00:00
TextBox [ ] counters ;
2015-08-11 06:50:32 +00:00
TextBox [ ] messages ;
2015-09-04 11:49:04 +00:00
static IList < WaterMeters . iPerl . WaterMeter > waterMeters ;
Modbus . QuidoRS . QuidoRS quido ;
2015-08-11 06:50:32 +00:00
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
2015-09-04 11:49:04 +00:00
static TestMethodCfg cfg ;
static IList < iPerlCommunicationParams > multiTestParams ;
static int currentActivityStep ;
static int currentGroup ; /// form -> worker thread (0 = none)
2015-08-11 06:50:32 +00:00
static int lastGroup ;
2015-08-12 14:05:06 +00:00
static int completedCommCount ; /// Number of completed communication steps
2015-08-11 06:50:32 +00:00
static IList < Thread > workerThreads ;
static IList < int > rfidPortNrs ;
2015-09-04 11:49:04 +00:00
static bool stopWorkerThreads ; /// form -> worker thread
2015-08-11 06:50:32 +00:00
2015-09-04 11:49:04 +00:00
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
2015-08-11 06:50:32 +00:00
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 ,
} ;
2015-09-21 14:29:12 +00:00
counters = new TextBox [ 48 ]
{
textBox1 , textBox2 , textBox3 , textBox4 , textBox5 ,
textBox6 , textBox7 , textBox8 , textBox9 , textBox10 ,
textBox11 , textBox12 , textBox13 , textBox14 , textBox15 ,
textBox16 , textBox17 , textBox18 , textBox19 , textBox20 ,
textBox21 , textBox22 , textBox23 , textBox24 , textBox25 ,
textBox26 , textBox27 , textBox28 , textBox29 , textBox30 ,
textBox31 , textBox32 , textBox33 , textBox34 , textBox35 ,
textBox36 , textBox37 , textBox38 , textBox39 , textBox40 ,
textBox41 , textBox42 , textBox43 , textBox44 , textBox45 ,
textBox46 , textBox47 , textBox48 ,
} ;
2015-08-11 06:50:32 +00:00
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 ,
} ;
formCompleted = false ;
/// 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 ) ;
} ;
2015-09-05 22:09:52 +00:00
StartForceCloseHandler ( ) ;
2015-08-11 06:50:32 +00:00
}
2015-09-04 11:49:04 +00:00
2015-08-11 06:50:32 +00:00
/// <summary>
2015-09-04 11:49:04 +00:00
/// Constructor with a list of watermeters.
/// Creates a list of iPerl-s, re-shuffles UI conrols and allocates 'disabled' array.
2015-08-11 06:50:32 +00:00
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
2015-09-06 21:36:14 +00:00
public iPerlCommunicationForm ( IList < GenericDevices . IWaterMeter > waterMeters , TestMethodCfg cfg )
2015-08-11 06:50:32 +00:00
: this ( )
2015-09-04 11:49:04 +00:00
{
2015-09-06 21:36:14 +00:00
iPerlCommunicationForm . cfg = cfg ;
2015-09-04 11:49:04 +00:00
this . WaterMetersCount = waterMeters . Count ;
iPerlCommunicationForm . waterMeters = new List < WaterMeters . iPerl . WaterMeter > ( ) ;
///
foreach ( var wm in waterMeters )
{
WaterMeters . iPerl . WaterMeter iPerl = wm as WaterMeters . iPerl . WaterMeter ;
iPerlCommunicationForm . waterMeters . Add ( iPerl ) ;
}
ShuffleTextBoxes ( this . WaterMetersCount , Program . LineSize ) ;
///
/// Prepare worker threads, 'rfidPortNrs', 'lastGroup', etc..
///
workerThreads = new List < Thread > ( ) ;
rfidPortNrs = new List < int > ( ) ;
currentActivityStep = 0 ;
currentGroup = 0 ;
lastGroup = 0 ; /// group numbers are >=1, lastGroup == 0 means no group
completedCommCount = 0 ;
stopWorkerThreads = false ;
foreach ( var iPerl in iPerlCommunicationForm . waterMeters )
{
if ( ! rfidPortNrs . Contains ( iPerl . MuxBoardNr ) )
{
rfidPortNrs . Add ( iPerl . MuxBoardNr ) ;
2015-09-06 21:36:14 +00:00
if ( workerThreads . Count < cfg . NrThreads )
2015-09-04 11:49:04 +00:00
{
Thread thread = new Thread ( iPerlCommunicationForm . Worker ) ;
workerThreads . Add ( thread ) ;
}
}
2015-09-11 12:15:32 +00:00
2015-09-04 11:49:04 +00:00
if ( iPerl . Group > lastGroup ) lastGroup = iPerl . Group ;
}
}
/// <summary>
/// Constructor for one iPerlCommunication 'test'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm ( IList < GenericDevices . IWaterMeter > waterMeters ,
TestMethodCfg cfg , iPerlCommunicationParams testParams )
2015-09-06 21:36:14 +00:00
: this ( waterMeters , cfg )
2015-08-11 06:50:32 +00:00
{
2015-09-04 11:49:04 +00:00
iPerlCommunicationForm . multiTestParams = new List < iPerlCommunicationParams > ( ) ;
iPerlCommunicationForm . multiTestParams . Add ( testParams ) ;
2015-08-11 06:50:32 +00:00
2015-09-04 11:49:04 +00:00
activityLabel . Text = testParams . Activity ;
2015-08-13 06:35:34 +00:00
}
2015-08-11 06:50:32 +00:00
2015-09-04 11:49:04 +00:00
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm ( IList < GenericDevices . IWaterMeter > waterMeters , TestMethodCfg cfg ,
IList < iPerlCommunicationParams > multiTestParams )
2015-09-06 21:36:14 +00:00
: this ( waterMeters , cfg )
2015-09-04 11:49:04 +00:00
{
iPerlCommunicationForm . multiTestParams = multiTestParams ;
if ( multiTestParams . Count > 0 ) activityLabel . Text = multiTestParams [ 0 ] . Activity ;
}
2015-08-11 06:50:32 +00:00
/// <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 ] ;
2015-09-21 14:29:12 +00:00
counters [ dest ] = counters [ l * lineSize + l * gap + i ] ;
2015-08-11 06:50:32 +00:00
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 ) ;
}
}
2015-09-04 11:49:04 +00:00
2015-08-11 06:50:32 +00:00
private void iPerlCommunicationForm_Load ( object sender , EventArgs e )
{
Localize ( ) ;
//Height = 50 + 90 * WaterMetersCount;
for ( int i = 0 ; i < textBoxesCount ; i + + )
{
2015-09-11 12:15:32 +00:00
//if (disabled != null && i < disabled.Length && disabled[i])
//{
// labels[i].Visible = messages[i].Visible = false;
//}
//else
2015-08-11 06:50:32 +00:00
{
2015-09-21 14:29:12 +00:00
labels [ i ] . Visible = counters [ i ] . Visible = messages [ i ] . Visible = true ;
2015-08-11 06:50:32 +00:00
messages [ i ] . Text = "---" ;
}
}
2015-09-05 22:09:52 +00:00
TBF . LocalSettings ls = Program . LocalSettings ;
Left = ( ls . iPerlCommunicationsFormLeft ! = 0 ) ? ls . iPerlCommunicationsFormLeft : 150 ;
Top = ( ls . iPerlCommunicationsFormTop ! = 0 ) ? ls . iPerlCommunicationsFormTop : 150 ;
2015-08-19 11:04:47 +00:00
2015-09-21 14:29:12 +00:00
/// Reset opto-data indication
for ( int i = 0 ; i < waterMeters . Count ; i + + )
{
waterMeters [ i ] . FlushedDataCount = 0 ;
counters [ i ] . Text = "0" ;
}
2015-09-05 22:09:52 +00:00
///
/// Start worker threads, etc.
///
if ( workerThreads ! = null )
{
int wtId = 0 ;
foreach ( var wt in workerThreads ) wt . Start ( new Boxes . IntBox ( wtId + + ) ) ;
///
/// 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 + + ;
}
2015-08-11 06:50:32 +00:00
}
2015-09-04 11:49:04 +00:00
2015-08-11 06:50:32 +00:00
private void NormalClose ( )
{
CommCompletedHandler = null ;
AllCompletedHandler = null ;
2015-09-11 17:36:37 +00:00
Entities . TestResult result = CommResult ( StateMachine . Tests [ 0 ] ) ; /// TODO: Pass the test info in a correct way
BenchControl . Sequences . SequenceBase . AddOrOverwriteResult ( result ) ; /// TODO: Pass the result in a correct way
TBF . UiBridge . Bridge . OnTestCompleted ( this , new TBF . UiBridge . TestCompletedEventArgs ( result ) ) ;
2015-08-11 06:50:32 +00:00
formCompleted = true ;
2015-08-19 11:04:47 +00:00
Program . LocalSettings . iPerlCommunicationsFormLeft = Location . X ;
Program . LocalSettings . iPerlCommunicationsFormTop = Location . Y ;
Program . LocalSettings . Save ( ) ;
2015-08-11 06:50:32 +00:00
DialogResult = DialogResult . OK ;
Close ( ) ;
}
#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 ;
2015-09-04 11:49:04 +00:00
stopWorkerThreads = true ;
2015-08-11 06:50:32 +00:00
DialogResult = DialogResult . Cancel ;
Close ( ) ;
}
#endregion
2015-08-15 15:51:54 +00:00
/// <summary>
/// Worker thread
/// </summary>
/// <param name="threadData">Thread ID (integer) wrapped into IntBox</param>
2015-08-12 14:05:06 +00:00
static void Worker ( object threadData )
2015-08-11 06:50:32 +00:00
{
2015-08-12 14:05:06 +00:00
int threadId = ( threadData as Boxes . IntBox ) . Val ;
2015-08-11 06:50:32 +00:00
2015-09-04 11:49:04 +00:00
int activityStep = 0 ; /// activity step > 0 in case multiTestParams are used
2015-08-15 21:01:26 +00:00
2015-09-04 11:49:04 +00:00
foreach ( var testParams in multiTestParams )
{
string activity = testParams . Activity ; /// Current activity
2015-08-11 06:50:32 +00:00
2015-09-04 11:49:04 +00:00
if ( threadId = = 0 )
{
rfidDataLogger . InfoFormat ( "" ) ; /// Makes the log more readable when there is a lot of data
rfidDataLogger . WarnFormat ( "Activity = {0}" , activity ) ;
rfidDataLogger . InfoFormat ( "" ) ; /// Makes the log more readable when there is a lot of data
}
2015-08-12 14:05:06 +00:00
2015-09-04 11:49:04 +00:00
for ( int group = 1 ; group < = lastGroup ; group + + )
{
/// Synchronize with QuidoRS and other threads
2015-09-05 22:09:52 +00:00
while ( ( ( group ! = currentGroup ) | | ( activityStep ! = currentActivityStep ) ) & & ! stopWorkerThreads )
2015-09-04 11:49:04 +00:00
{
Thread . Sleep ( 50 ) ;
}
if ( stopWorkerThreads ) break ;
2015-09-06 21:36:14 +00:00
for ( int rfidPortIx = threadId ; rfidPortIx < threadId + 4 ; rfidPortIx + = cfg . NrThreads )
2015-09-04 11:49:04 +00:00
{
int rfidPortNr = rfidPortNrs [ rfidPortIx ] ;
int wmNr = 0 ;
bool wmFound = false ;
foreach ( var wm in waterMeters )
{
if ( ( wm . MuxBoardNr = = rfidPortNr ) & & ( wm . Group = = group ) )
{
wmFound = true ;
CommErr error ;
string resultStr = string . Empty ;
if ( activity . ToLower ( ) . Contains ( ReadConfigurationStr . ToLower ( ) ) ) error = ReadConfiguration ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Contains ( SetTestModeStr . ToLower ( ) ) ) error = SetTestMode ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( SetActiveModeStr . ToLower ( ) ) ) error = SetActiveMode ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( ReadCalibrationStr . ToLower ( ) ) ) error = ReadCalibration ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Contains ( WriteCalibrationFactorStr . ToLower ( ) ) ) error = WriteCalibrationFactor ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( ResetQ2CorrectionStr . ToLower ( ) ) ) error = ResetQ2Correction ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( WriteQ2CorrectionStr . ToLower ( ) ) ) error = WriteQ2Correction ( wm , ref resultStr ) ;
else
{
error = CommErr . None ;
resultStr = "Invalid activity" ;
}
2015-09-05 22:09:52 +00:00
if ( error = = CommErr . None )
{
OnCommCompleted ( null , new CommCompletedEventArgs ( threadId , wmNr , resultStr ) ) ;
}
2015-09-11 12:15:32 +00:00
else if ( wm . CommFailed | | error = = CommErr . CommFailed )
2015-09-05 22:09:52 +00:00
{
OnCommCompleted ( null , new CommCompletedEventArgs ( threadId , wmNr , "Watermeter is disabled" ) ) ;
}
2015-09-04 11:49:04 +00:00
else
{
OnCommCompleted ( null , new CommCompletedEventArgs ( threadId , wmNr , string . Format ( "{0} failed ({1}) !!!" , activity , error ) ) ) ;
rfidDataLogger . ErrorFormat ( "Group={0}, Board={1}, {2} failed ({3}) !!!" , currentGroup , wm . MuxBoardNr , activity , error ) ;
2015-09-11 12:15:32 +00:00
wm . CommFailed = true ;
2015-09-04 11:49:04 +00:00
}
break ;
}
wmNr + + ;
}
if ( ! wmFound ) OnCommCompleted ( null , new CommCompletedEventArgs ( threadId , - 1 , string . Empty ) ) ; /// Send negative wmNr
if ( stopWorkerThreads ) break ;
}
if ( stopWorkerThreads ) break ;
} /// for (int group
activityStep + + ;
if ( stopWorkerThreads ) break ;
}
2015-08-11 06:50:32 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-14 09:38:53 +00:00
/// <summary>
/// Read a complete configuration structure of the watermeter
/// </summary>
/// <param name="wm">Water meter object</param>
2015-08-15 15:51:54 +00:00
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr ReadConfiguration ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-11 06:50:32 +00:00
{
2015-08-14 17:20:47 +00:00
///
/// The activity is "Read configuration" (this enables the watermeter, resets error flag)
/// or "Read configuration if enabled" (this keeps th error flag).
///
2015-09-04 11:49:04 +00:00
if ( ! multiTestParams [ currentActivityStep ] . Activity . ToLower ( ) . Contains ( " if enabled" ) )
2015-08-15 15:51:54 +00:00
{
2015-09-11 12:15:32 +00:00
wm . CommFailed = false ;
2015-08-15 15:51:54 +00:00
}
2015-08-11 06:50:32 +00:00
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-14 09:38:53 +00:00
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-11 06:50:32 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . Read ;
2015-08-11 06:50:32 +00:00
2015-08-15 15:51:54 +00:00
/// Read configuration
byte [ ] config = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-11 06:50:32 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Configuration , 0 , ConfigStruct . Length , out config , cfg . CommTimeout ) )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-15 15:51:54 +00:00
wm . ConfigStruct = ConfigStruct . FromByteArray ( config ) ;
resultStr = wm . ConfigStruct . ToString ( 1 ) ;
break ;
}
2015-08-11 06:50:32 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-11 06:50:32 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-14 09:38:53 +00:00
/// <summary>
2015-08-14 12:33:36 +00:00
/// Set the watermeter to the test mode.
/// If testModeConfig is specified as a hexadeximal number appended to "set test mode ", it is verified
/// whether the testModeConfig is correctly set, if necessary it is changed to the specified value.
/// Read a part of configuration afterwards to verify the mode was set correctly.
2015-08-14 09:38:53 +00:00
/// </summary>
/// <param name="wm">Water meter object</param>
2015-08-15 15:51:54 +00:00
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr SetTestMode ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-11 06:50:32 +00:00
{
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-15 15:51:54 +00:00
Byte testModeConfig = 0xA0 ; /// Default value
///
2015-09-04 11:49:04 +00:00
if ( multiTestParams [ currentActivityStep ] . Activity . Length > SetTestModeStr . Length )
2015-08-11 06:50:32 +00:00
{
2015-09-04 11:49:04 +00:00
string testModeConfigStr = multiTestParams [ currentActivityStep ] . Activity . Substring ( SetTestModeStr . Length + 1 ) ;
2015-08-15 15:51:54 +00:00
UInt16 byteVal ;
if ( UInt16 . TryParse ( testModeConfigStr , NumberStyles . HexNumber , CultureInfo . CurrentCulture , out byteVal ) & & byteVal < = 255 )
2015-08-11 06:50:32 +00:00
{
2015-08-15 15:51:54 +00:00
testModeConfig = ( Byte ) byteVal ; /// Update with specified value
2015-08-14 12:33:36 +00:00
}
2015-08-15 15:51:54 +00:00
}
2015-08-14 12:33:36 +00:00
2015-08-15 15:51:54 +00:00
if ( wm . ConfigStruct . MeterState = = MeterState . Test & & wm . ConfigStruct . TestModeConfig = = testModeConfig )
{
/// Already in the correct test mode
2015-08-19 11:04:47 +00:00
resultStr = "Already " + wm . ConfigStruct . ToString ( 1 ) ;
2015-08-17 14:02:30 +00:00
return CommErr . None ;
2015-08-15 15:51:54 +00:00
}
2015-08-14 12:33:36 +00:00
2015-08-15 15:51:54 +00:00
/// Communication necessary
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-14 09:38:53 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . None ;
2015-08-14 17:20:47 +00:00
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None & & ( wm . ConfigStruct . TestModeConfig ! = testModeConfig ) & & ( wm . ConfigStruct . MeterState ! = MeterState . Active ) )
2015-08-15 15:51:54 +00:00
{
/// Switch to Active mode in order to change TestModeConfig
2015-08-17 14:02:30 +00:00
error = CommErr . CmdActive ;
2015-08-15 15:51:54 +00:00
byte [ ] cmd = new byte [ 1 ] { ( byte ) 6 } ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . Command , 0 , 1 , cmd , cfg . CommTimeout ) ) { error = CommErr . None ; break ; }
2015-08-15 15:51:54 +00:00
}
}
2015-08-14 17:20:47 +00:00
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None & & ( wm . ConfigStruct . TestModeConfig ! = testModeConfig ) )
2015-08-15 15:51:54 +00:00
{
/// Change the TestModeConfig if necessary
2015-08-17 14:02:30 +00:00
error = CommErr . Write ;
2015-08-15 15:51:54 +00:00
byte [ ] tstMdCfg = new byte [ 1 ] { testModeConfig } ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . Configuration , 21 , 1 , tstMdCfg , cfg . CommTimeout ) )
2015-08-14 17:20:47 +00:00
{
2015-08-15 15:51:54 +00:00
wm . ConfigStruct . Update ( 21 , tstMdCfg ) ;
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-15 15:51:54 +00:00
break ;
2015-08-14 17:20:47 +00:00
}
}
2015-08-11 06:50:32 +00:00
}
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-11 06:50:32 +00:00
{
2015-08-15 15:51:54 +00:00
/// Switch to test mode
2015-08-17 14:02:30 +00:00
error = CommErr . CmdTest ;
2015-08-15 15:51:54 +00:00
byte [ ] cmd = new byte [ 1 ] { ( byte ) 7 } ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . Command , 0 , 1 , cmd , cfg . CommTimeout ) ) { error = CommErr . None ; break ; }
2015-08-15 15:51:54 +00:00
}
2015-08-14 09:38:53 +00:00
}
2015-08-15 15:51:54 +00:00
/// Now the meter should be in the Test mode ... verify
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-14 09:38:53 +00:00
{
2015-08-15 15:51:54 +00:00
/// Verify the configuration
2015-08-17 14:02:30 +00:00
error = CommErr . Verify ;
2015-08-15 15:51:54 +00:00
byte [ ] cfg_0_3 = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Configuration , 0 , 4 , out cfg_0_3 , cfg . CommTimeout ) )
2015-08-15 15:51:54 +00:00
{
wm . ConfigStruct . Update ( 0 , cfg_0_3 ) ;
2015-08-17 14:02:30 +00:00
if ( wm . ConfigStruct . MeterState = = MeterState . Test )
{
error = CommErr . None ;
resultStr = wm . ConfigStruct . ToString ( 1 ) ;
break ;
}
2015-08-15 15:51:54 +00:00
}
}
2015-08-14 09:38:53 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-14 09:38:53 +00:00
}
2015-08-11 06:50:32 +00:00
2015-08-15 15:51:54 +00:00
2015-08-14 09:38:53 +00:00
/// <summary>
2015-08-14 12:33:36 +00:00
/// Set the watermeter to the active mode.
2015-08-14 09:38:53 +00:00
/// Read a part of configuration afterwards to verify the mode was set correctly.
/// </summary>
/// <param name="wm">Water meter object</param>
2015-08-15 15:51:54 +00:00
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr SetActiveMode ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-14 09:38:53 +00:00
{
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . CmdActive ;
2015-08-14 09:38:53 +00:00
2015-08-15 15:51:54 +00:00
/// Switch to active mode
byte [ ] cmd = new byte [ 1 ] { ( byte ) 6 } ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-14 09:38:53 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . Command , 0 , 1 , cmd , cfg . CommTimeout ) ) { error = CommErr . None ; break ; }
2015-08-15 15:51:54 +00:00
}
2015-08-14 09:38:53 +00:00
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . Verify ;
2015-08-11 06:50:32 +00:00
2015-08-15 15:51:54 +00:00
/// Read configuration
byte [ ] cfg_0_3 = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-14 09:38:53 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Configuration , 0 , 4 , out cfg_0_3 , cfg . CommTimeout ) )
2015-08-14 09:38:53 +00:00
{
2015-08-15 15:51:54 +00:00
wm . ConfigStruct . Update ( 0 , cfg_0_3 ) ;
2015-08-17 14:02:30 +00:00
if ( wm . ConfigStruct . MeterState = = MeterState . Active )
{
error = CommErr . None ;
resultStr = wm . ConfigStruct . ToString ( 1 ) ;
break ;
}
2015-08-14 09:38:53 +00:00
}
}
}
2015-08-11 06:50:32 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-11 06:50:32 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-14 12:33:36 +00:00
/// <summary>
/// Read a complete calibration structure from the watermeter
/// </summary>
/// <param name="wm">Water meter object</param>
2015-08-15 15:51:54 +00:00
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr ReadCalibration ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-14 12:33:36 +00:00
{
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-14 12:33:36 +00:00
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-14 12:33:36 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . Read ;
2015-08-14 12:33:36 +00:00
2015-08-15 15:51:54 +00:00
/// Read calibration
byte [ ] calib = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-14 12:33:36 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Calibration , 0 , CalibrationStruct . Length , out calib , cfg . CommTimeout ) )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-15 15:51:54 +00:00
wm . CalibrationStruct = CalibrationStruct . FromByteArray ( calib ) ;
resultStr = wm . CalibrationStruct . ToString ( ) ;
break ;
}
2015-08-14 12:33:36 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-14 12:33:36 +00:00
}
2015-08-15 15:51:54 +00:00
2015-08-14 12:33:36 +00:00
/// <summary>
/// Write the calculated calibration factor to the water meter.
/// Read a part of CalibrationStruct afterwards to verify factor was written correctly.
/// </summary>
/// <param name="wm">Water meter object</param>
2015-08-15 15:51:54 +00:00
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr WriteCalibrationFactor ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-11 06:50:32 +00:00
{
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-15 15:51:54 +00:00
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . Write ;
2015-08-11 06:50:32 +00:00
2015-10-16 09:24:03 +00:00
/// Parse calibration factor (1 argument) or calibration factor limits (2 arguments)
UInt16 newCalibFactor = 0 ;
2015-09-04 11:49:04 +00:00
if ( multiTestParams [ currentActivityStep ] . Activity . Length > WriteCalibrationFactorStr . Length )
2015-10-16 09:24:03 +00:00
{
UInt16 factorLimitLo ;
UInt16 factorLimitHi ;
UInt16 val ;
2015-09-04 11:49:04 +00:00
string calibFactrorStr = multiTestParams [ currentActivityStep ] . Activity . Substring ( WriteCalibrationFactorStr . Length + 1 ) ;
2015-10-16 09:24:03 +00:00
string [ ] arguments = calibFactrorStr . Split ( new char [ ] { ' ' } ) ;
if ( arguments . Length > = 2 & &
UInt16 . TryParse ( arguments [ 0 ] , out factorLimitLo ) & & factorLimitLo > 0 & &
UInt16 . TryParse ( arguments [ 1 ] , out factorLimitHi ) & & factorLimitHi > 0 )
{
newCalibFactor = wm . CalculateNewCalibFactor ( wm . CalibrationFactor , factorLimitLo , factorLimitHi ) ;
}
else if ( arguments . Length = = 1 & & UInt16 . TryParse ( arguments [ 0 ] , out val ) & & val > 0 )
{
newCalibFactor = val ; /// Update with specified value
}
else
{
newCalibFactor = 2710 ; /// Default calibration factor for DN15
}
}
else
{
newCalibFactor = wm . CalculateNewCalibFactor ( wm . CalibrationFactor , 2400 , 2700 ) ; /// Default factor limits for DN15
}
2015-08-21 12:30:47 +00:00
2015-08-19 19:12:10 +00:00
byte [ ] data = new byte [ 2 ] { ( byte ) ( newCalibFactor & 0x00FF ) , ( byte ) ( ( newCalibFactor > > 8 ) & 0x00FF ) } ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . Calibration , 2 , 2 , data , cfg . CommTimeout ) )
2015-08-24 13:16:14 +00:00
{
error = CommErr . None ;
wm . CalibrationStruct . Update ( data , 2 ) ;
break ;
}
2015-08-15 15:51:54 +00:00
}
2015-08-11 06:50:32 +00:00
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . Verify ;
2015-08-14 12:33:36 +00:00
2015-08-15 15:51:54 +00:00
/// Read calibration
byte [ ] calib_2_3 = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Calibration , 2 , 2 , out calib_2_3 , cfg . CommTimeout ) )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-15 15:51:54 +00:00
wm . CalibrationStruct . Update ( calib_2_3 , 2 ) ;
resultStr = wm . CalibrationStruct . ToString ( ) ;
break ;
}
2015-08-14 09:38:53 +00:00
}
2015-08-15 15:51:54 +00:00
}
2015-08-11 06:50:32 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-14 09:38:53 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-15 15:51:54 +00:00
}
2015-08-11 06:50:32 +00:00
2015-08-15 15:51:54 +00:00
const int Q2CorrFactorsAddr = 0x1878 ; /// Used by ResetQ2Correction(...) and WriteQ2Correction(...)
2015-08-11 06:50:32 +00:00
2015-08-15 15:51:54 +00:00
/// <summary>
/// Reset both Q2 correction factors in the memory to 0.
/// Read them back to verify factors were written correctly.
/// </summary>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr ResetQ2Correction ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-14 12:33:36 +00:00
{
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-15 15:51:54 +00:00
2015-08-27 05:03:42 +00:00
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
CommErr error = CommErr . Write ;
2015-08-15 15:51:54 +00:00
/// Write zero Q2 correction
2015-08-22 11:58:55 +00:00
byte [ ] wrData = new byte [ 2 ] { 0 , 0 } ;
///
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , 2 , wrData , cfg . CommTimeout ) ) { error = CommErr . None ; break ; }
2015-08-15 15:51:54 +00:00
}
2015-08-22 11:58:55 +00:00
/// Verify the correction factors
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . Verify ;
2015-08-15 15:51:54 +00:00
/// Read calibration
byte [ ] rdData = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( ( 0 = = ReadRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , 2 , out rdData , cfg . CommTimeout ) ) & &
2015-08-15 15:51:54 +00:00
( rdData ! = null ) & & ( rdData . Length = = 2 ) & & ( rdData [ 0 ] = = 0 ) & & ( rdData [ 1 ] = = 0 ) )
{
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-15 15:51:54 +00:00
resultStr = "Q2 correction factors reset to 0" ;
2015-08-26 16:59:38 +00:00
wm . CurrentQ2Correction = 0 ;
2015-08-15 15:51:54 +00:00
break ;
}
}
}
2015-08-14 12:33:36 +00:00
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-15 15:51:54 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-15 15:51:54 +00:00
}
/// <summary>
/// Write the calculated Q2 correction factors to the memory.
/// Read them back to verify factors were written correctly.
/// </summary>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
2015-08-17 14:02:30 +00:00
static CommErr WriteQ2Correction ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
2015-08-14 12:33:36 +00:00
{
2015-09-11 12:15:32 +00:00
if ( wm . CommFailed ) return CommErr . CommFailed ;
2015-08-15 15:51:54 +00:00
/// Write Q2 corrections
2015-08-22 11:58:55 +00:00
double q2CorrectionFactor = wm . Q2CorrectionFactor ( ) ;
2015-10-23 14:10:28 +00:00
if ( q2CorrectionFactor = = 0 )
{
resultStr = string . Format ( "Q2 factors = 0 (writing bypassed)" ) ;
return CommErr . None ;
}
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
CommErr error = CommErr . Write ;
2015-08-27 05:03:42 +00:00
Byte q2CorrRFlow = ( byte ) ( ( int ) Math . Round ( q2CorrectionFactor / 2 ) & 0x000000FF ) ;
Byte q2CorrLFlow = ( byte ) ( ( int ) Math . Round ( q2CorrectionFactor ) & 0x000000FF ) ;
2015-08-22 11:58:55 +00:00
byte [ ] wrData = new byte [ 2 ] { q2CorrRFlow , q2CorrLFlow } ;
///
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , 2 , wrData , cfg . CommTimeout ) ) { error = CommErr . None ; break ; }
2015-08-15 15:51:54 +00:00
}
2015-08-17 14:02:30 +00:00
if ( error = = CommErr . None )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . Verify ;
2015-08-15 15:51:54 +00:00
/// Read calibration
byte [ ] rdData = null ;
2015-09-06 21:36:14 +00:00
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
2015-08-15 15:51:54 +00:00
{
2015-09-06 21:36:14 +00:00
if ( ( 0 = = ReadRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , 2 , out rdData , cfg . CommTimeout ) ) & &
2015-08-22 14:25:35 +00:00
( rdData ! = null ) & & ( rdData . Length = = 2 ) & & ( rdData [ 0 ] = = q2CorrRFlow ) & & ( rdData [ 1 ] = = q2CorrLFlow ) )
2015-08-15 15:51:54 +00:00
{
2015-08-17 14:02:30 +00:00
error = CommErr . None ;
2015-08-27 05:03:42 +00:00
resultStr = string . Format ( "Q2 factors: R-flow={0}, L-flow={1}" , ( SByte ) q2CorrRFlow , ( SByte ) q2CorrLFlow ) ;
rfidDataLogger . Warn ( wm . Name + ": " + resultStr ) ;
2015-08-26 16:59:38 +00:00
wm . CurrentQ2Correction = q2CorrectionFactor ;
2015-08-15 15:51:54 +00:00
break ;
}
}
}
2015-08-27 05:03:42 +00:00
ClosePort ( wm ) ; /// Close RFID port
2015-08-22 16:11:53 +00:00
2015-08-17 14:02:30 +00:00
return error ;
2015-08-15 15:51:54 +00:00
}
2015-08-14 12:33:36 +00:00
2015-08-11 06:50:32 +00:00
/// <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 )
{
2015-09-05 22:09:52 +00:00
if ( data . WMNr > = 0 ) messages [ data . WMNr ] . Text = data . CommMessage ;
2015-08-12 14:05:06 +00:00
2015-09-21 14:29:12 +00:00
for ( int i = 0 ; i < waterMeters . Count ; i + + )
{
counters [ i ] . Text = ( waterMeters [ i ] . FlushedDataCount % 1000 ) . ToString ( ) ;
}
2015-08-12 14:05:06 +00:00
lock ( this )
{
2015-08-13 06:35:34 +00:00
if ( + + completedCommCount < rfidPortNrs . Count ) return ;
2015-08-12 14:05:06 +00:00
completedCommCount = 0 ;
}
2015-08-11 06:50:32 +00:00
if ( currentGroup < lastGroup )
{
2015-08-12 14:05:06 +00:00
/// Go to the next step / next group
2015-09-04 11:49:04 +00:00
if ( quido ! = null )
2015-08-11 06:50:32 +00:00
{
2015-09-05 22:09:52 +00:00
quido . SetOutputs ( ( ushort ) ( 16 - currentGroup - 1 ) ) ;
2015-08-12 14:05:06 +00:00
Thread . Sleep ( 100 ) ;
2015-08-11 06:50:32 +00:00
}
2015-09-05 22:09:52 +00:00
currentGroup + + ;
}
2015-09-04 11:49:04 +00:00
else if ( currentActivityStep + 1 < multiTestParams . Count )
{
2015-09-05 22:09:52 +00:00
currentGroup = 0 ;
2015-09-04 11:49:04 +00:00
currentActivityStep + + ;
activityLabel . Text = multiTestParams [ currentActivityStep ] . Activity ;
if ( quido ! = null )
{
2015-09-05 22:09:52 +00:00
quido . SetOutputs ( ( ushort ) ( 16 - currentGroup - 1 ) ) ;
2015-09-04 11:49:04 +00:00
Thread . Sleep ( 100 ) ;
}
2015-09-05 22:09:52 +00:00
currentGroup + + ;
2015-09-04 11:49:04 +00:00
}
else
2015-08-11 06:50:32 +00:00
{
2015-08-12 14:05:06 +00:00
/// Wait until all threads are finished
2015-08-11 06:50:32 +00:00
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 ;
}
2015-09-11 17:36:37 +00:00
/// <summary>
/// Create virtual test result with representing communication success/failure
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
Entities . TestResult CommResult ( Entities . Test test )
{
Entities . TestResult tstRslt = new Entities . TestResult ( test , 1 , Entities . MetersKind . Single ) ;
tstRslt . DoNotEvaluate = false ;
tstRslt . DoNotPublish = false ;
tstRslt . TimeStart = DateTime . Now ;
tstRslt . TimeEnd = DateTime . Now ;
tstRslt . AmbientTempAve = 20.0f ;
tstRslt . AmbientPressAve = 1000.0f ;
tstRslt . AmbientHumiAve = 50.0f ;
tstRslt . PressInStart = 1000.0f ;
tstRslt . PressOutStart = 1000.0f ;
tstRslt . TempInStart = 20.0f ;
tstRslt . TempOutStart = 20.0f ;
tstRslt . TempDivStart = 20.0f ;
tstRslt . PressInEnd = 1000.0f ;
tstRslt . PressOutEnd = 1000.0f ;
tstRslt . TempInEnd = 20.0f ;
tstRslt . TempOutEnd = 20.0f ;
tstRslt . TempDivEnd = 20.0f ;
tstRslt . PressInAvrg = 1000.0f ;
tstRslt . PressOutAvrg = 1000.0f ;
tstRslt . TempInAvrg = 20.0f ;
tstRslt . TempOutAvrg = 20.0f ;
tstRslt . TempDivAvrg = 20.0f ;
tstRslt . BatchNr = Program . LocalSettings . BatchNr ;
tstRslt . MassStartRaw = 0 ;
tstRslt . MassStart = 0 ;
tstRslt . MassEndRaw = 0 ;
tstRslt . MassEnd = 0 ;
tstRslt . MassDiff = 0 ;
tstRslt . DensityIn = Program . LocalSettings . RealDensity ;
tstRslt . DensityOut = Program . LocalSettings . RealDensity ;
tstRslt . DensityDiv = Program . LocalSettings . RealDensity ;
tstRslt . Time = 0 ;
tstRslt . FlowMass = 0 ;
tstRslt . FlowVolume = 0 ;
tstRslt . VolumeCTV = 0 ;
tstRslt . VolumeMaster = 0 ;
tstRslt . PulsesMaster = 0 ;
tstRslt . ConstMaster = 0 ;
tstRslt . ErrorMaster = 0 ;
for ( int i = 0 ; i < Program . WMsCount ; i + + )
{
/// Reference to iPerl water meter or null:
WaterMeters . iPerl . WaterMeter iPerl = ( i < iPerlCommunicationForm . waterMeters . Count ) ? iPerlCommunicationForm . waterMeters [ i ] : null ;
tstRslt . Meters [ i ] . SerialNr = iPerl . SerialNr ;
tstRslt . Meters [ i ] . PulsesPerLiter = 0 ;
tstRslt . Meters [ i ] . VolumeRef = 0 ;
tstRslt . Meters [ i ] . Time = 0 ;
tstRslt . Meters [ i ] . TimeStart = 0 ;
tstRslt . Meters [ i ] . TimeEnd = 0 ;
tstRslt . Meters [ i ] . PulsesMaster = 0 ;
tstRslt . Meters [ i ] . VolumeStart = 0 ;
tstRslt . Meters [ i ] . VolumeEnd = 0 ;
tstRslt . Meters [ i ] . VolumeMeter = 0 ;
tstRslt . Meters [ i ] . VolumeErrorPct = 0 ;
tstRslt . Meters [ i ] . Passed = ( ! iPerl . CommFailed & & ! iPerl . Disabled ) ;
tstRslt . Meters [ i ] . PulsesMeter = 0 ;
tstRslt . Meters [ i ] . Disabled = iPerl . Disabled ;
}
return tstRslt ;
}
2015-08-11 06:50:32 +00:00
}
}