2015-08-11 06:50:32 +00:00
///
2016-10-27 12:27:37 +00:00
/// Copyright (c) 2015-2016 Sensus Metering Systems
2015-08-11 06:50:32 +00:00
///
2016-10-27 12:27:37 +00:00
//#define VERIFY_ACTIVE_MODE
//#define VERIFY_Q2_CORR_RESET
2015-08-11 06:50:32 +00:00
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 ;
2016-04-19 08:10:51 +00:00
using System.Text ;
2015-08-11 06:50:32 +00:00
using System.Threading ;
using System.Windows.Forms ;
using log4net ;
2015-12-04 16:17:20 +00:00
using Config.Entities ;
2015-08-11 06:50:32 +00:00
using TBF.Resources ;
2016-01-03 01:05:35 +00:00
using TBF.BenchControl.Sequences ;
2015-08-11 06:50:32 +00:00
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 ,
2016-11-10 13:07:11 +00:00
ReadAfterWrite ,
2015-08-17 14:02:30 +00:00
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
{
2016-04-18 11:38:13 +00:00
if ( wm . DebugLevel ! = DebugMode . Normal ) return 0 ; /// No function in debug mode
2015-08-27 05:03:42 +00:00
2016-04-18 11:38:13 +00:00
if ( wm . RfidComPortNr > 0 )
2015-08-19 11:04:47 +00:00
{
2016-04-18 11:38:13 +00:00
return openPort1 ( wm . RfidComPortNr ) ;
}
else
{
switch ( wm . MuxBoardNr )
{
default :
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
{
2016-04-18 11:38:13 +00:00
if ( wm . DebugLevel ! = DebugMode . Normal ) return 0 ; /// No function in debug mode
2015-08-27 05:03:42 +00:00
2016-04-18 11:38:13 +00:00
if ( wm . RfidComPortNr > 0 )
{
return closePort1 ( ) ;
}
else
2015-08-19 11:04:47 +00:00
{
2016-04-18 11:38:13 +00:00
switch ( wm . MuxBoardNr )
{
default :
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
{
2016-10-27 12:27:37 +00:00
buffer = new byte [ lenght ] ;
if ( wm . DebugLevel ! = DebugMode . Normal ) return wm . Name . Equals ( "iPerl13" ) ? 2 : 0 ; /// Simulates an error on position 13
2015-08-11 06:50:32 +00:00
2016-10-27 12:27:37 +00:00
byte [ ] buf = new byte [ 200 ] ;
///
fixed ( byte * pBuf = buf )
2015-08-11 06:50:32 +00:00
{
2016-10-27 12:27:37 +00:00
int retv ;
if ( wm . RfidComPortNr > 0 )
{
retv = readRequestPort1 ( messageID , offset , lenght , pBuf , timeout ) ;
}
else
{
switch ( wm . MuxBoardNr )
2016-04-18 11:38:13 +00:00
{
2016-10-27 12:27:37 +00:00
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 ;
2016-04-18 11:38:13 +00:00
}
2016-10-27 12:27:37 +00:00
}
2015-08-19 11:04:47 +00:00
2015-08-11 06:50:32 +00:00
for ( int i = 0 ; i < lenght ; i + + ) buffer [ i ] = buf [ i ] ;
2015-09-16 14:30:30 +00:00
2016-10-27 12:27:37 +00:00
///
/// Logging
///
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 ( ) ) ;
2016-10-27 12:27:37 +00:00
else if ( ( messageID = = MessageID . Calibration ) & & ( offset = = 2 ) & & ( lenght = = 2 ) )
rfidDataLogger . InfoFormat ( "{0}: ReadRequestPort({1},2,2,...) returned {2} {3}" , name , messageID , retv , ( retv ! = 0 ) ? "!" : string . Format ( "Cal={0}" , buf [ 0 ] + 256 * buf [ 1 ] ) ) ;
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-08-11 06:50:32 +00:00
2016-10-27 12:27:37 +00:00
return retv ;
}
2015-08-11 06:50:32 +00:00
}
/// <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
{
2016-10-27 12:27:37 +00:00
if ( wm . DebugLevel ! = DebugMode . Normal ) return 0 ;
2015-08-11 06:50:32 +00:00
fixed ( byte * pBuf = buffer )
{
2016-10-27 12:27:37 +00:00
int retv ;
if ( wm . RfidComPortNr > 0 )
{
retv = writeRequestPort1 ( messageID , offset , lenght , pBuf , timeout ) ;
}
else
{
switch ( wm . MuxBoardNr )
2016-04-18 11:38:13 +00:00
{
2016-10-27 12:27:37 +00:00
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 ;
2016-04-18 11:38:13 +00:00
}
2016-10-27 12:27:37 +00:00
}
2015-08-19 11:04:47 +00:00
2016-10-27 12:27:37 +00:00
Thread . Sleep ( 250 ) ;
///
/// Logging
///
string name = string . Format ( "{0}({1})" , wm . Name , wm . SerialNr ) ;
if ( lenght = = 1 )
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-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 ) ? "!" : "" ) ;
2016-10-27 12:27:37 +00:00
return retv ;
2015-08-15 21:01:26 +00:00
}
2015-08-11 06:50:32 +00:00
}
#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" ;
2016-11-02 12:16:07 +00:00
const string NormalizeCalibrationFactorStr = "Normalize calibration factor" ;
2015-08-14 12:33:36 +00:00
const string ResetQ2CorrectionStr = "Reset Q2 correction" ;
const string WriteQ2CorrectionStr = "Write Q2 correction" ;
2016-02-16 13:44:10 +00:00
const string Reset2HzCorrectionStr = "Reset 2Hz correction" ;
const string Write2HzCorrectionStr = "Write 2Hz correction" ;
2015-08-14 12:33:36 +00:00
2015-08-11 06:50:32 +00:00
2016-01-08 18:18:45 +00:00
DateTime startTime ;
int startTimeSec ;
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>
2016-01-19 16:38:09 +00:00
public int WaterMetersCount ;
2015-08-11 06:50:32 +00:00
int textBoxesCount ;
Label [ ] labels ;
2016-06-27 13:24:10 +00:00
PictureBox [ ] 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 ;
2017-02-14 14:41:50 +00:00
static IList < int > waterMeterPositions ; /// keeps original indices in RegisterReaders list
2015-09-04 11:49:04 +00:00
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 ;
2016-01-19 16:38:09 +00:00
static IList < Config . Entities . Test > tests ;
2015-09-04 11:49:04 +00:00
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 ,
} ;
2016-06-27 13:24:10 +00:00
counters = new PictureBox [ 48 ]
2015-09-21 14:29:12 +00:00
{
2016-06-27 13:24:10 +00:00
pictureBox1 , pictureBox2 , pictureBox3 , pictureBox4 , pictureBox5 ,
pictureBox6 , pictureBox7 , pictureBox8 , pictureBox9 , pictureBox10 ,
pictureBox11 , pictureBox12 , pictureBox13 , pictureBox14 , pictureBox15 ,
pictureBox16 , pictureBox17 , pictureBox18 , pictureBox19 , pictureBox20 ,
pictureBox21 , pictureBox22 , pictureBox23 , pictureBox24 , pictureBox25 ,
pictureBox26 , pictureBox27 , pictureBox28 , pictureBox29 , pictureBox30 ,
pictureBox31 , pictureBox32 , pictureBox33 , pictureBox34 , pictureBox35 ,
pictureBox36 , pictureBox37 , pictureBox38 , pictureBox39 , pictureBox40 ,
pictureBox41 , pictureBox42 , pictureBox43 , pictureBox44 , pictureBox45 ,
pictureBox46 , pictureBox47 , pictureBox48 ,
2015-09-21 14:29:12 +00:00
} ;
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 ;
2016-01-08 18:18:45 +00:00
startTime = DateTime . Now ;
startTimeSec = StateMachine . Time ;
2015-08-11 06:50:32 +00:00
/// 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>
2016-01-19 16:38:09 +00:00
/// Constructor for one iPerlCommunication 'test'
2015-08-11 06:50:32 +00:00
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
2016-01-19 16:38:09 +00:00
public iPerlCommunicationForm ( TestMethodCfg cfg , Test test , iPerlCommunicationParams testParams )
: this ( )
{
iPerlCommunicationForm . cfg = cfg ;
iPerlCommunicationForm . tests = new List < Test > ( ) ;
iPerlCommunicationForm . tests . Add ( test ) ;
iPerlCommunicationForm . multiTestParams = new List < iPerlCommunicationParams > ( ) ;
iPerlCommunicationForm . multiTestParams . Add ( testParams ) ;
2016-02-13 15:40:26 +00:00
ProcessData . RegisterReaders = StateMachine . GetMetersPath ( test ) . RegisterReaders ;
2016-01-19 16:38:09 +00:00
activityLabel . Text = testParams . Activity ;
ConstructorCommon ( ) ;
}
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public iPerlCommunicationForm ( TestMethodCfg cfg , IList < Test > tests , IList < iPerlCommunicationParams > multiTestParams )
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 ;
2016-01-19 16:38:09 +00:00
iPerlCommunicationForm . tests = tests ;
iPerlCommunicationForm . multiTestParams = multiTestParams ;
2015-09-06 21:36:14 +00:00
2016-01-19 16:38:09 +00:00
if ( multiTestParams . Count > 0 )
{
2016-02-13 15:40:26 +00:00
ProcessData . RegisterReaders = StateMachine . GetMetersPath ( tests [ 0 ] ) . RegisterReaders ;
2016-01-19 16:38:09 +00:00
activityLabel . Text = multiTestParams [ 0 ] . Activity ;
}
ConstructorCommon ( ) ;
}
void ConstructorCommon ( )
{
waterMeters = new List < WaterMeters . iPerl . WaterMeter > ( ) ;
2017-02-14 14:41:50 +00:00
waterMeterPositions = new List < int > ( ) ;
///
for ( int wmPos = 0 ; wmPos < ProcessData . RegisterReaders . Length ; wmPos + + )
2015-09-04 11:49:04 +00:00
{
2017-02-14 14:41:50 +00:00
WaterMeters . iPerl . WaterMeter iPerl = ProcessData . RegisterReaders [ wmPos ] as WaterMeters . iPerl . WaterMeter ;
if ( iPerl ! = null )
2016-04-19 08:10:51 +00:00
{
2017-02-14 14:41:50 +00:00
waterMeters . Add ( iPerl ) ;
waterMeterPositions . Add ( wmPos ) ;
2016-04-19 08:10:51 +00:00
}
2015-09-04 11:49:04 +00:00
}
2016-01-19 16:38:09 +00:00
WaterMetersCount = waterMeters . Count ;
2016-04-19 08:10:51 +00:00
ShuffleTextBoxes ( WaterMetersCount , Config . Data . LineSize ) ;
2015-09-04 11:49:04 +00:00
///
/// 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 ;
}
2016-04-19 08:10:51 +00:00
StringBuilder sb = new StringBuilder ( ) ;
2016-04-20 13:03:18 +00:00
sb . Append ( "rfidPortNrs = [" ) ;
2016-04-19 08:10:51 +00:00
foreach ( var v in rfidPortNrs ) sb . Append ( string . Format ( " {0}" , v ) ) ;
2016-04-20 13:03:18 +00:00
sb . Append ( string . Format ( " ], nrThreads = {0}" , workerThreads . Count ) ) ;
2016-04-19 08:10:51 +00:00
log . WarnFormat ( sb . ToString ( ) ) ;
2015-09-04 11:49:04 +00:00
}
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 ;
}
2016-04-23 12:32:15 +00:00
///
/// Resize the dialog to fit the enabled controls
///
int xMax = 0 ;
int yMax = 0 ;
for ( int i = 0 ; i < textBoxesCount ; i + + )
{
if ( messages [ i ] . Left + messages [ i ] . Width > xMax ) xMax = messages [ i ] . Left + messages [ i ] . Width ;
if ( messages [ i ] . Top + messages [ i ] . Height > yMax ) yMax = messages [ i ] . Top + messages [ i ] . Height ;
}
Width = xMax + 30 ;
Height = yMax + 50 ;
2015-08-11 06:50:32 +00:00
}
2016-04-23 12:32:15 +00:00
void Localize ( )
2015-08-11 06:50:32 +00:00
{
Text = Strings . Water_Meter_States ;
2017-02-21 08:56:50 +00:00
for ( int i = 0 ; i < Math . Min ( textBoxesCount , waterMeters . Count ) ; i + + )
2015-08-11 06:50:32 +00:00
{
2017-02-21 08:56:50 +00:00
labels [ i ] . Text = waterMeters [ i ] . Name ;
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 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 ;
2016-06-27 13:24:10 +00:00
counters [ i ] . BackColor = Color . Red ;
2015-09-21 14:29:12 +00:00
}
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 ;
2017-02-14 14:41:50 +00:00
if ( multiTestParams ! = null & &
multiTestParams . Count > 0 & &
! multiTestParams [ 0 ] . SimultWithNext ) /// RFID Communication at the end of the cycle does not influence the result
2016-02-08 16:03:07 +00:00
{
UpdateRfidCommResult ( tests ) ; /// TODO: Pass the test info in a correct way
}
2016-01-03 01:05:35 +00:00
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
2016-01-08 18:18:45 +00:00
for ( int i = 0 ; i < multiTestParams . Count ; i + + )
2015-09-04 11:49:04 +00:00
{
2016-01-08 18:18:45 +00:00
iPerlCommunicationParams testParams = multiTestParams [ i ] ;
TBF . UiBridge . TestProgressEventArgs . SetEstimatedTimes ( new int [ ] { 0 , 0 , 10 , 140 , 0 , 0 , 0 } ) ;
2016-01-19 16:38:09 +00:00
TBF . UiBridge . Bridge . OnTestProgress ( null , new TBF . UiBridge . TestProgressEventArgs ( tests [ i ] , Config . Entities . Progress . JustStarted ) ) ;
2016-01-08 18:18:45 +00:00
2015-09-04 11:49:04 +00:00
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
{
2016-03-01 17:57:36 +00:00
if ( rfidPortIx > = rfidPortNrs . Count ) break ; // quit, all RFID ports of all water meters done
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 ) ;
2016-11-02 12:16:07 +00:00
else if ( activity . ToLower ( ) . Equals ( NormalizeCalibrationFactorStr . ToLower ( ) ) ) error = NormalizeCalibrationFactor ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( ResetQ2CorrectionStr . ToLower ( ) ) ) error = ResetQ2Correction ( wm , ref resultStr ) ;
2015-09-04 11:49:04 +00:00
else if ( activity . ToLower ( ) . Equals ( WriteQ2CorrectionStr . ToLower ( ) ) ) error = WriteQ2Correction ( wm , ref resultStr ) ;
2016-02-16 13:44:10 +00:00
else if ( activity . ToLower ( ) . Equals ( Reset2HzCorrectionStr . ToLower ( ) ) ) error = Reset2HzCorrection ( wm , ref resultStr ) ;
else if ( activity . ToLower ( ) . Equals ( Write2HzCorrectionStr . ToLower ( ) ) ) error = Write2HzCorrection ( wm , ref resultStr ) ;
2015-09-04 11:49:04 +00:00
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 + + ;
2016-01-19 16:38:09 +00:00
TBF . UiBridge . Bridge . OnTestProgress ( null , new TBF . UiBridge . TestProgressEventArgs ( tests [ i ] , Config . Entities . Progress . FlowSetting ) ) ;
2015-09-04 11:49:04 +00:00
}
2016-01-08 18:18:45 +00:00
if ( ! wmFound )
{
OnCommCompleted ( null , new CommCompletedEventArgs ( threadId , - 1 , string . Empty ) ) ; /// Send negative wmNr
}
2015-09-04 11:49:04 +00:00
if ( stopWorkerThreads ) break ;
}
if ( stopWorkerThreads ) break ;
} /// for (int group
2016-01-19 16:38:09 +00:00
TBF . UiBridge . Bridge . OnTestProgress ( null , new TBF . UiBridge . TestProgressEventArgs ( tests [ i ] , Config . Entities . Progress . Completed ) ) ;
2015-09-04 11:49:04 +00:00
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
}
2016-02-16 14:57:30 +00:00
Thread . Sleep ( 250 ) ;
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
}
}
2016-02-16 14:57:30 +00:00
Thread . Sleep ( 250 ) ;
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
}
2016-02-16 14:57:30 +00:00
Thread . Sleep ( 250 ) ;
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
{
2016-02-16 14:57:30 +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
2016-10-27 12:27:37 +00:00
#if VERIFY_ACTIVE_MODE
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
{
2016-03-01 15:22:49 +00:00
if ( wm . ConfigStruct = = null )
2015-08-14 09:38:53 +00:00
{
2016-03-01 15:22:49 +00:00
if ( 0 = = ReadRequestPort ( wm , MessageID . Configuration , 0 , 4 , out cfg_0_3 , cfg . CommTimeout ) )
2015-08-17 14:02:30 +00:00
{
2016-03-01 15:22:49 +00:00
wm . ConfigStruct . Update ( 0 , cfg_0_3 ) ;
if ( wm . ConfigStruct . MeterState = = MeterState . Active )
{
error = CommErr . None ;
resultStr = wm . ConfigStruct . ToString ( 1 ) ;
break ;
}
2015-08-17 14:02:30 +00:00
}
2015-08-14 09:38:53 +00:00
}
}
}
2016-02-16 14:57:30 +00:00
#else
if ( error = = CommErr . None )
{
2016-03-01 15:22:49 +00:00
if ( wm . ConfigStruct = = null )
resultStr = "OK (Config not available)" ;
else
resultStr = wm . ConfigStruct . ToString ( 1 ) ;
2016-02-16 14:57:30 +00:00
}
#endif
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
2016-11-10 13:07:11 +00:00
///
2015-10-16 09:24:03 +00:00
/// Parse calibration factor (1 argument) or calibration factor limits (2 arguments)
2016-11-10 13:07:11 +00:00
///
2015-10-16 09:24:03 +00:00
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
}
2016-11-10 13:07:11 +00:00
///
/// Start communication with iPerl
///
CommErr error ;
2015-08-19 19:12:10 +00:00
byte [ ] data = new byte [ 2 ] { ( byte ) ( newCalibFactor & 0x00FF ) , ( byte ) ( ( newCalibFactor > > 8 ) & 0x00FF ) } ;
2016-11-10 13:07:11 +00:00
int writeAndVerifyRetries = 0 ;
do
2015-08-15 15:51:54 +00:00
{
2016-11-10 13:07:11 +00:00
///
/// Write the new calibration factor (up to cfg.MaxCommRetries tims)
///
error = CommErr . Write ;
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
{
2016-11-10 13:07:11 +00:00
///
/// Read and verify the calibration factor
///
error = CommErr . ReadAfterWrite ;
byte [ ] calib_2_3 = null ;
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
{
2016-11-10 13:07:11 +00:00
error = CommErr . Verify ;
if ( calib_2_3 ! = null & & calib_2_3 . Length = = 2 & & data [ 0 ] = = calib_2_3 [ 0 ] & & data [ 1 ] = = calib_2_3 [ 1 ] )
{
error = CommErr . None ;
wm . CalibrationStruct . Update ( data , 2 ) ;
resultStr = wm . CalibrationStruct . ToString ( ) ;
break ;
}
2015-08-15 15:51:54 +00:00
}
2015-08-14 09:38:53 +00:00
}
2016-11-10 13:07:11 +00:00
wm . CalibrationStruct . Update ( data , 2 ) ;
2015-08-15 15:51:54 +00:00
}
2016-11-10 13:07:11 +00:00
while ( + + writeAndVerifyRetries < = cfg . MaxCommRetries ) ;
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
2016-11-02 12:16:07 +00:00
/// <summary>
/// Normalize calibration factor in case ti is close to value 8000.
/// </summary>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr NormalizeCalibrationFactor ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
{
if ( wm . CommFailed ) return CommErr . CommFailed ;
if ( wm . CalibrationFactor < = 5000 )
{
resultStr = "Calibratin factor is OK" ;
return CommErr . None ; /// No need to update the calibration factor
}
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
CommErr error = CommErr . Write ;
/// Determine the new calibration factor
UInt16 newCalibFactor = 0 ;
switch ( wm . CalibrationStruct . MeterType )
{
case MeterType . DN15 : newCalibFactor = 2650 ; break ;
case MeterType . DN20 : newCalibFactor = 3746 ; break ;
case MeterType . DN25 : newCalibFactor = 3300 ; break ;
case MeterType . DN32 : newCalibFactor = 2500 ; break ;
case MeterType . DN40 : newCalibFactor = 3000 ; break ;
case MeterType . DN26 :
case MeterType . CoaxManifold :
default :
newCalibFactor = 3040 ;
break ;
}
byte [ ] data = new byte [ 2 ] { ( byte ) ( newCalibFactor & 0x00FF ) , ( byte ) ( ( newCalibFactor > > 8 ) & 0x00FF ) } ;
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
if ( 0 = = WriteRequestPort ( wm , MessageID . Calibration , 2 , 2 , data , cfg . CommTimeout ) )
{
error = CommErr . None ;
wm . CalibrationStruct . Update ( data , 2 ) ;
break ;
}
}
if ( error = = CommErr . None )
{
error = CommErr . Verify ;
/// Read calibration
byte [ ] calib_2_3 = null ;
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
if ( 0 = = ReadRequestPort ( wm , MessageID . Calibration , 2 , 2 , out calib_2_3 , cfg . CommTimeout ) )
{
error = CommErr . None ;
wm . CalibrationStruct . Update ( calib_2_3 , 2 ) ;
resultStr = wm . CalibrationStruct . ToString ( ) ;
break ;
}
}
}
ClosePort ( wm ) ; /// Close RFID port
return error ;
}
2016-02-14 18:02:07 +00:00
const int Hz2CorrFactorsAddr = 0x1875 ; /// Used by Reset2HzCorrection(...) and Write2HzCorrection(...)
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
{
2016-02-16 13:44:10 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , wrData . Length , wrData , cfg . CommTimeout ) )
{
error = CommErr . None ;
break ;
}
2015-08-15 15:51:54 +00:00
}
2016-02-16 13:44:10 +00:00
///
/// Verification disabled on 16.02.2016
2016-10-27 12:27:37 +00:00
///
#if VERIFY_Q2_CORR_RESET
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" ;
2016-02-16 13:44:10 +00:00
wm . Q2CorrectionFactor = 0 ;
break ;
}
}
}
#else
if ( error = = CommErr . None )
{
resultStr = "Q2 corrections reset to 0" ;
wm . Q2CorrectionFactor = 0 ;
}
#endif
ClosePort ( wm ) ; /// Close RFID port
return error ;
}
/// <summary>
/// Reset 2Hz correction factor in the memory to 0.
/// </summary>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr Reset2HzCorrection ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
{
if ( wm . CommFailed ) return CommErr . CommFailed ;
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
CommErr error = CommErr . Write ;
/// Write zero Q2 correction
byte [ ] wrData = new byte [ 1 ] { 0 } ;
///
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Hz2CorrFactorsAddr , wrData . Length , wrData , cfg . CommTimeout ) )
{
error = CommErr . None ;
break ;
}
}
///
/// Verification disabled on 16.02.2016
///
#if false
/// Verify the correction factors
if ( error = = CommErr . None )
{
error = CommErr . Verify ;
/// Read calibration
byte [ ] rdData = null ;
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
if ( ( 0 = = ReadRequestPort ( wm , MessageID . MetrologyMemory , Hz2CorrFactorsAddr , 1 , out rdData , cfg . CommTimeout ) ) & &
( rdData ! = null ) & & ( rdData . Length = = 2 ) & & ( rdData [ 0 ] = = 0 ) & & ( rdData [ 1 ] = = 0 ) )
{
error = CommErr . None ;
resultStr = "2Hz correction reset to 0" ;
wm . Q2CorrectionFactor = 0 ;
2015-08-15 15:51:54 +00:00
break ;
}
}
}
2016-02-16 13:44:10 +00:00
#else
if ( error = = CommErr . None )
{
resultStr = "2Hz correction reset to 0" ;
wm . Hz2CorrectionFactor = 0 ;
}
#endif
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
2016-02-16 13:44:10 +00:00
wm . Q2ErrorWOCorrection = wm . LastTestResult . Error ;
wm . Q2CorrectionDone = false ;
double q2CorrectionFactor ;
bool wmOK = wm . CalculateQ2CorrectionFactor ( wm . LastTestResult , out q2CorrectionFactor ) ;
2015-10-23 14:10:28 +00:00
if ( q2CorrectionFactor = = 0 )
{
2016-02-16 13:44:10 +00:00
resultStr = string . Format ( "Q2 correction = 0 (writing bypassed)" ) ;
2015-10-23 14:10:28 +00:00
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
{
2016-02-16 13:44:10 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Q2CorrFactorsAddr , wrData . Length , wrData , cfg . CommTimeout ) )
{
error = CommErr . None ;
break ;
}
2015-08-15 15:51:54 +00:00
}
2016-02-16 13:44:10 +00:00
///
/// Verification disabled on 16.02.2016
///
#if false
if ( error = = CommErr . None )
2015-08-15 15:51:54 +00:00
{
2016-02-16 13:44:10 +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
{
2016-02-16 13:44:10 +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 ) ;
2016-02-16 13:44:10 +00:00
rfidDataLogger . Warn ( wm . Name + ": " + resultStr ) ;
wm . Q2CorrectionDone = true ;
wm . Q2CorrectionFactor = q2CorrectionFactor ;
2015-08-15 15:51:54 +00:00
break ;
}
}
}
2016-02-16 13:44:10 +00:00
#else
if ( error = = CommErr . None )
{
resultStr = string . Format ( "Q2 correction: R-flow={0}, L-flow={1}" , ( SByte ) q2CorrRFlow , ( SByte ) q2CorrLFlow ) ;
rfidDataLogger . Warn ( wm . Name + ": " + resultStr ) ;
wm . Q2CorrectionDone = true ;
wm . Q2CorrectionFactor = q2CorrectionFactor ;
}
#endif
2015-08-15 15:51:54 +00:00
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
2016-02-15 14:16:44 +00:00
/// <summary>
/// Write the calculated 2Hz correction factor to the memory.
/// </summary>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr Write2HzCorrection ( WaterMeters . iPerl . WaterMeter wm , ref string resultStr )
{
if ( wm . CommFailed ) return CommErr . CommFailed ;
2016-02-16 13:44:10 +00:00
/// Calculate the correction
wm . Hz2CorrectionDone = false ;
int hz2CorrectionFactor ;
bool wmOK = wm . Calculate2HzCorrectionFactor ( wm . LastTestResult2 , wm . LastTestResult , out wm . Diff2Hz8Hz , out hz2CorrectionFactor ) ;
2016-02-15 14:16:44 +00:00
if ( hz2CorrectionFactor = = 0 )
{
2016-02-16 13:44:10 +00:00
resultStr = string . Format ( "2Hz correction = 0 (writing bypassed)" ) ;
2016-02-15 14:16:44 +00:00
return CommErr . None ;
}
if ( OpenPort ( wm ) ! = 0 ) return CommErr . OpenPort ; /// Open RFID port
CommErr error = CommErr . Write ;
2016-02-16 13:44:10 +00:00
Byte hz2CorrectionByte = ( byte ) ( hz2CorrectionFactor & 0x000000FF ) ;
2016-02-15 14:16:44 +00:00
byte [ ] wrData = new byte [ 1 ] { hz2CorrectionByte } ;
///
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
2016-02-16 13:44:10 +00:00
if ( 0 = = WriteRequestPort ( wm , MessageID . MetrologyMemory , Hz2CorrFactorsAddr , wrData . Length , wrData , cfg . CommTimeout ) )
{
error = CommErr . None ;
break ;
}
2016-02-15 14:16:44 +00:00
}
2016-02-16 13:44:10 +00:00
///
/// Verification disabled on 16.02.2016
///
#if false
2016-02-15 14:16:44 +00:00
if ( error = = CommErr . None )
{
error = CommErr . Verify ;
/// Read calibration
byte [ ] rdData = null ;
for ( int j = 0 ; j < cfg . MaxCommRetries ; j + + )
{
if ( ( 0 = = ReadRequestPort ( wm , MessageID . MetrologyMemory , Hz2CorrFactorsAddr , 1 , out rdData , cfg . CommTimeout ) ) & &
( rdData ! = null ) & & ( rdData . Length = = 2 ) & & ( rdData [ 0 ] = = hz2CorrectionByte ) )
{
error = CommErr . None ;
resultStr = string . Format ( "2Hz factor = {0}" , ( SByte ) hz2CorrectionByte ) ;
rfidDataLogger . Warn ( wm . Name + ": " + resultStr ) ;
2016-02-16 13:44:10 +00:00
wm . Hz2CorrectionFactor = hz2CorrectionFactor ;
2016-02-15 14:16:44 +00:00
break ;
}
}
}
2016-02-16 13:44:10 +00:00
#else
if ( error = = CommErr . None )
{
resultStr = string . Format ( "2Hz correction = {0}" , ( SByte ) hz2CorrectionByte ) ;
rfidDataLogger . Warn ( wm . Name + ": " + resultStr ) ;
wm . Hz2CorrectionDone = true ;
wm . Hz2CorrectionFactor = hz2CorrectionFactor ;
}
#endif
2016-02-15 14:16:44 +00:00
ClosePort ( wm ) ; /// Close RFID port
return error ;
}
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 + + )
{
2016-06-27 13:24:10 +00:00
counters [ i ] . BackColor = ( waterMeters [ i ] . FlushedDataDelta = = 0 ) ? Color . Red : Color . Green ;
2015-09-21 14:29:12 +00:00
}
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>
2016-01-03 01:05:35 +00:00
/// Update test result representing RFID communication success/failure
2015-09-11 17:36:37 +00:00
/// </summary>
/// <param name="test"></param>
2016-01-19 16:38:09 +00:00
void UpdateRfidCommResult ( IList < Config . Entities . Test > tests )
2015-09-11 17:36:37 +00:00
{
2016-01-08 18:18:45 +00:00
DateTime endTime = DateTime . Now ;
int testTime = StateMachine . Time - startTimeSec ;
2015-09-11 17:36:37 +00:00
2016-01-19 16:38:09 +00:00
if ( ! tests . Contains ( StateMachine . Tests [ 0 ] ) )
2016-01-03 01:05:35 +00:00
{
2016-01-19 16:38:09 +00:00
tests . Insert ( 0 , StateMachine . Tests [ 0 ] ) ; /// Add RFID test as the 1st item
2016-01-08 18:18:45 +00:00
}
2016-01-03 01:05:35 +00:00
2016-01-19 16:38:09 +00:00
foreach ( var test in tests )
2016-01-08 18:18:45 +00:00
{
2016-01-19 16:38:09 +00:00
Results . Entities . TestRslt tstRslt = ProcessData . BatchRslts . GetTestRslt ( test . Name , test . Part ) ;
2016-01-08 18:18:45 +00:00
if ( tstRslt ! = null )
{
/// Auxiliary results ... not required
/// Main results
tstRslt . StartTime = tstRslt . Batch . StartTime ;
tstRslt . EndTime = endTime ;
tstRslt . FlowSetTime = 0 ;
tstRslt . TestTime + = testTime ; /// [s] total communication time of all tests
2017-02-14 14:41:50 +00:00
for ( int i = 0 ; i < waterMeters . Count ; i + + )
2016-01-08 18:18:45 +00:00
{
Results . Entities . MeterTestRslt meterRslt =
2017-02-14 14:41:50 +00:00
ProcessData . BatchRslts . GetMeterTestRslt ( test . Name , waterMeterPositions [ i ] , Config . Entities . CompoundMeterId . Single ) ;
2016-01-08 18:18:45 +00:00
WaterMeters . iPerl . WaterMeter iPerl = waterMeters [ i ] as WaterMeters . iPerl . WaterMeter ;
if ( meterRslt ! = null & & iPerl ! = null )
{
meterRslt . WaterMeter . SerialNr = iPerl . SerialNr ;
meterRslt . Passed = ( ! iPerl . CommFailed & & ! iPerl . Disabled ) ;
meterRslt . TestDone = true ;
}
}
}
2016-01-03 01:05:35 +00:00
}
2015-09-11 17:36:37 +00:00
}
2015-08-11 06:50:32 +00:00
}
}