2025-10-18 07:59:07 +00:00
///
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
///
//#define VERIFY_ACTIVE_MODE
//#define VERIFY_Q2_CORR_RESET
using System ;
using System.Collections.Generic ;
2025-11-12 11:34:29 +00:00
using System.Linq ;
using System.Runtime.CompilerServices ;
2025-10-18 07:59:07 +00:00
using System.Windows.Forms ;
using Config.Entities ;
using log4net ;
2025-11-12 11:34:29 +00:00
using NHibernate.Util ;
2025-10-18 07:59:07 +00:00
using TBF.Resources ;
2025-11-06 13:11:13 +00:00
using TBF.Rig.Generic ;
2025-10-18 07:59:07 +00:00
using TBF.Rig.RegisterReaders.CommonRR.IPerl ;
using TBF.Rig.RegisterReaders.iPerlReaderUNI ;
2025-11-12 11:34:29 +00:00
using TBF.Rig.RegisterReaders.PoseidonReader ;
2025-10-18 07:59:07 +00:00
using TBF.Rig.Sequences ;
2025-11-12 11:34:29 +00:00
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead ;
2025-10-18 07:59:07 +00:00
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common ;
2025-11-06 13:11:13 +00:00
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations ;
2025-11-12 11:34:29 +00:00
using TBF.Tools ;
2025-10-18 07:59:07 +00:00
using CheckBoxImage = TBF . Boxes . CheckBoxImage ;
//using TestMethodCfg = TBF.Rig.RegisterReaders.iPerlReaderUNI.TestMethodCfg;
namespace TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication
{
public enum CommErr
{
None = 0 ,
CommFailed , /// 1
OpenPort , /// 2
Read , /// 3
Read1 , /// 4
Read2 , /// 5
Read3 , /// 6
Read4 , /// 7
Write , /// 8
ReadAfterWrite , /// 9
CmdActive , /// 0AH = 10
CmdTest , /// 0BH = 11
Verify , /// 0CH = 12
WrongIPerlType , /// 0DH = 13
OutOfRange , /// 0EH = 14
Q2OutOfRange , /// 0FH = 15
MissingTest , /// 10H = 16
RFPowerRecordMissing , /// 11H = 17
HeadDisabledByUser , /// 12H = 18
WrongArguments , /// 13H = 19
}
public partial class SmartCommunicationForm : Form , GenericDevices . IHasCompleted
{
private static readonly ILog log = LogManager . GetLogger ( typeof ( SmartCommunicationForm ) ) ;
protected static readonly ILog rfidDataLogger = LogManager . GetLogger ( "RfidData" ) ;
readonly bool checkBoxesEditMode ;
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
2025-11-06 13:11:13 +00:00
// Set to 'true' when the form closes
2025-10-18 07:59:07 +00:00
public bool Completed { get { return formCompleted ; } }
bool formCompleted ;
bool forcedClose ; /// Set in the forced close handler
/// <summary> Number of text boxes for serial numbers </summary>
public int WaterMetersCount ;
const int MaxTextBoxesCount = 48 ;
int textBoxesCount ;
Label [ ] labels ;
PictureBox [ ] counters ;
TextBox [ ] messages ;
CheckBoxImage [ ] checkBoxes ;
static int [ ] ckbIndex ;
static bool [ ] ckbState ;
2025-11-06 13:11:13 +00:00
static IList < ISmartReader > iperlHeads ;
2025-10-18 07:59:07 +00:00
static IList < int > waterMeterPositions0 ; /// keeps original 0-based indices in RegisterReaders list
static int commonWMType ;
2025-11-12 11:34:29 +00:00
//share form to correction solver
public IList < ISmartReader > Heads { get = > iperlHeads ; }
public ILog Log { get = > SmartCommunicationForm . log ; }
public ILog RfidDataLogger { get = > SmartCommunicationForm . rfidDataLogger ; }
public Label ActivityLabel { get = > this . activityLabel ; }
public Label [ ] Labels { get = > this . labels ; }
public PictureBox [ ] Counters { get = > this . counters ; }
public TextBox [ ] Messages { get = > this . messages ; }
public CheckBoxImage [ ] CheckBoxes { get = > this . checkBoxes ; }
public int [ ] CkbIndex { get = > SmartCommunicationForm . ckbIndex ; }
public bool [ ] CkbState { get = > SmartCommunicationForm . ckbState ; }
2025-10-18 07:59:07 +00:00
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
2025-11-12 11:34:29 +00:00
private static List < ICorrections > _corrections ;
private static ICorrections Correction
{
get
{
if ( string . IsNullOrEmpty ( SelectedTypeReader ) & & _corrections . Count > 0 )
{
return _corrections . First ( ) ;
}
foreach ( ICorrections correction in _corrections )
{
if ( SelectedTypeReader = = correction . TypeIdentificatorName ( ) )
{
return correction ;
}
}
if ( _corrections . Count > 0 )
{
return _corrections . First ( ) ;
}
2025-11-06 13:11:13 +00:00
2025-11-12 11:34:29 +00:00
return null ;
}
}
private List < string > TypeReaders
2025-11-06 13:11:13 +00:00
{
2025-11-12 11:34:29 +00:00
get { return IdentifyReaderTypes ( ) ; }
}
public static string SelectedTypeReader { get ; set ; }
2025-10-18 07:59:07 +00:00
2025-11-12 11:34:29 +00:00
private List < ICorrections > GetNewCorrectionList ( ISmartTestMethod componentBase ,
TestMethodCfg cfg , IList < Test > tests , IList < ITestParams > multiTestParams )
{
List < ICorrections > correctionsList = new List < ICorrections > ( ) ;
foreach ( var smartHead in ProcessData . SmartHeadsUni )
{
try {
if ( smartHead is IperlHead iperlHead )
{
if ( correctionsList . Any ( x = > x is IPerlCorrections ) )
continue ;
correctionsList . Add ( new IPerlCorrections ( this , componentBase , cfg , tests , multiTestParams ) ) ;
continue ;
}
if ( smartHead is SmartReader smartReader )
{
if ( correctionsList . Any ( x = > x is SmartReader ) )
continue ;
correctionsList . Add ( new PoseidonCorrections ( this ) ) ;
continue ;
}
throw new Exception ( "Unknown smart head type" ) ;
}
catch ( Exception e )
{
log . Error ( "IdentifyReaderTypes()" , e ) ;
}
}
return correctionsList ;
2025-11-06 13:11:13 +00:00
}
2025-11-12 11:34:29 +00:00
private static List < ICorrections > GetNewCorrectionList ( SmartCommunicationForm form )
{
List < ICorrections > correctionsList = new List < ICorrections > ( ) ;
foreach ( var smartHead in ProcessData . SmartHeadsUni )
{
try {
if ( smartHead is IperlHead iperlHead )
{
if ( correctionsList . Any ( x = > x is IPerlCorrections ) )
continue ;
correctionsList . Add ( new IPerlCorrections ( form ) ) ;
continue ;
}
if ( smartHead is SmartReader smartReader )
{
if ( correctionsList . Any ( x = > x is SmartReader ) )
continue ;
correctionsList . Add ( new PoseidonCorrections ( form ) ) ;
continue ;
}
throw new Exception ( "Unknown smart head type" ) ;
}
catch ( Exception e )
{
log . Error ( "IdentifyReaderTypes()" , e ) ;
}
}
return correctionsList ;
2025-11-06 13:11:13 +00:00
2025-11-12 11:34:29 +00:00
}
public static List < string > IdentifyReaderTypes ( )
{
List < string > typeReaders = new List < string > ( ) ;
foreach ( var smartHead in ProcessData . SmartHeadsUni )
{
try
{
if ( typeReaders . Contains ( smartHead . ClassName ) )
continue ;
if ( smartHead is IperlHead iperlHead )
{
typeReaders . Add ( iperlHead . ClassName ) ;
continue ;
}
if ( smartHead is SmartReader smartReader )
{
typeReaders . Add ( smartReader . ClassName ) ;
continue ;
}
throw new Exception ( "Unknown smart head type" ) ;
}
catch ( Exception e )
{
log . Error ( "IdentifyReaderTypes()" , e ) ;
}
}
return typeReaders ;
}
2025-10-18 07:59:07 +00:00
public static ITestMethodCfg ? TestMethodCfg
{
2025-11-06 13:11:13 +00:00
get
{
2025-11-12 11:34:29 +00:00
return Correction ? . Cfg ;
2025-11-06 13:11:13 +00:00
}
set
{
// Add null check for the value being set
if ( value = = null )
{
// Log or handle null case
return ;
}
2025-11-12 11:34:29 +00:00
if ( _corrections = = null | | _corrections . Count = = 0 )
2025-11-06 13:11:13 +00:00
{
2025-11-12 11:34:29 +00:00
_corrections = GetNewCorrectionList ( null ) ;
2025-11-06 13:11:13 +00:00
}
2025-11-12 11:34:29 +00:00
foreach ( var correction in _corrections )
{
correction . Cfg = value ;
}
2025-11-06 13:11:13 +00:00
}
2025-10-18 07:59:07 +00:00
}
static int currentActivityStep ;
static int currentGroup ; /// form -> worker thread (0 = none)
static int lastGroup ;
static int completedCommCount ; /// Number of completed communication steps
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
public SmartCommunicationForm ( )
{
InitializeComponent ( ) ;
}
/// <summary>
/// Constructor for checkBox states (active/inactive iPerl head) editing.
/// </summary>
/// <param name="checkBoxes">Initial check box states</param>
public SmartCommunicationForm ( bool isCheckBoxesEditMode )
: this ( )
{
2025-11-06 13:11:13 +00:00
//TODO get corrections based on defined meter
2025-11-12 11:34:29 +00:00
_corrections = GetNewCorrectionList ( this ) ; // default iPerl Head communication params
InitializeMeterTypeItems ( ) ;
2025-10-18 07:59:07 +00:00
if ( isCheckBoxesEditMode )
{
checkBoxesEditMode = true ;
saveButton . Visible = true ;
activityLabel . Text = Strings . Optical_heads ;
ShuffleTextBoxes ( ProcessData . WMsCount , ProcessData . LineSize ) ;
2025-11-06 13:11:13 +00:00
2025-11-12 11:34:29 +00:00
this . ContextMenu = Correction . GetContextMenu ( ) ;
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
}
2025-11-12 11:34:29 +00:00
InitializeWaterMeterData ( ) ;
if ( iperlHeads . Count < = 0 )
UpdateHeads ( ) ;
2025-10-18 07:59:07 +00:00
}
/// <summary>
/// Constructor for one iPerlCommunication 'test'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
2025-11-06 13:11:13 +00:00
public SmartCommunicationForm ( Generic . IComponent componentBase , Test test , ITestParams testParams )
: this ( componentBase , new List < Test > { test } , new List < ITestParams > { testParams } )
2025-10-18 07:59:07 +00:00
{
}
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
2025-11-06 13:11:13 +00:00
public SmartCommunicationForm ( Generic . IComponent componentBase , IList < Test > tests , IList < ITestParams > multiTestParams )
2025-10-18 07:59:07 +00:00
: this ( )
{
checkBoxesEditMode = false ;
2025-11-06 13:11:13 +00:00
//TODO get corrections based on defined meter
2025-11-12 11:34:29 +00:00
_corrections = GetNewCorrectionList ( componentBase as ISmartTestMethod ,
componentBase . Cfg as TestMethodCfg , tests , multiTestParams ) ;
InitializeMeterTypeItems ( ) ;
UpdateHeads ( ) ;
//_corrections = new PoseidonCorrections(this, log, rfidDataLogger, componentBase as ISmartTestMethod,componentBase.Cfg as TestMethodCfg,tests,multiTestParams);
2025-10-18 07:59:07 +00:00
if ( multiTestParams . Count > 0 )
{
ProcessData . RegisterReaders = StateMachine . GetMetersPath ( tests [ 0 ] ) . RegisterReaders ;
activityLabel . Text = multiTestParams [ 0 ] . Activity ;
foreach ( var p in multiTestParams )
{
if ( p . Activity . ToLower ( ) = = iPerlCommunicationConstants . GetDefaultQ2CorrectionsStr . ToLower ( ) )
{
/// Reset IsQ2PreCorrectionCalculated that is used for synchronization/to prevent double REST call
ProcessData . IsQ2PreCorrectionCalculated = false ;
commonWMType = 0 ;
break ;
}
}
}
2025-11-06 13:11:13 +00:00
/// Attach to 'CommCompleted' handler
SmartCommunicationForm . CommCompletedHandler + = delegate ( object sender , CommCompletedEventArgs args )
{
if ( InvokeRequired )
{
Invoke ( new EventHandler < CommCompletedEventArgs > ( DoOnCommCompleted ) , sender , args ) ;
}
else DoOnCommCompleted ( sender , args ) ;
} ;
2025-10-18 07:59:07 +00:00
2025-11-06 13:11:13 +00:00
/// Attach to 'AllCompleted' handler
SmartCommunicationForm . AllCompletedHandler + = delegate ( object sender , AllCompletedEventArgs args )
{
if ( InvokeRequired )
{
Invoke ( new EventHandler < AllCompletedEventArgs > ( DoOnAllCompleted ) , sender , args ) ;
}
else DoOnAllCompleted ( sender , args ) ;
} ;
formCompleted = false ;
StartForceCloseHandler ( ) ;
2025-10-18 07:59:07 +00:00
2025-11-12 11:34:29 +00:00
InitializeWaterMeterData ( ) ;
}
private void UpdateHeads ( )
{
iperlHeads ? . Clear ( ) ;
if ( iperlHeads = = null ) iperlHeads = new List < ISmartReader > ( ) ;
waterMeterPositions0 ? . Clear ( ) ;
if ( waterMeterPositions0 = = null ) waterMeterPositions0 = new List < int > ( ) ;
//iperlHeads = ProcessData.SmartHeadsUni;
string comparedTypeReader = SelectedTypeReader ;
if ( string . IsNullOrEmpty ( SelectedTypeReader ) )
{
comparedTypeReader = ProcessData . SmartHeadsUni ? . First ( ) ? . GetType ( ) . Name ;
}
ICorrections corre = null ;
foreach ( ICorrections correction in _corrections )
{
if ( correction . TypeIdentificatorName ( ) = = SelectedTypeReader )
{
corre = correction ;
break ;
}
}
if ( corre ! = null )
{
int wmPos = 0 ;
foreach ( var smartHead in ProcessData . SmartHeadsUni )
{
if ( corre . IsFamilyOfSmartReader ( smartHead ) )
{
iperlHeads . Add ( smartHead ) ;
waterMeterPositions0 . Add ( wmPos ) ;
wmPos + + ;
if ( wmPos > = ProcessData . WMsCount ) break ;
}
}
}
}
private void InitializeMeterTypeItems ( )
{
if ( _corrections . Count > = 0 )
{
meterTypeComboBox . Items . Clear ( ) ;
int iItem = 0 ;
foreach ( ICorrections correction in _corrections )
{
string name = correction ? . TypeIdentificatorName ( ) ;
if ( string . IsNullOrEmpty ( name ) )
{
name = iItem . ToString ( ) ;
}
meterTypeComboBox . Items . Add ( name ) ;
if ( iItem = = 0 )
SelectedTypeReader = name ;
iItem + + ;
}
meterTypeComboBox . Visible = true ;
meterTypeComboBox . Enabled = true ;
meterTypeComboBox . SelectedIndex = 0 ;
}
}
private void InitializeWaterMeterData ( )
{
InitializeSmartReaderLists ( ) ;
if ( iperlHeads . Count < = 0 )
UpdateHeads ( ) ;
WaterMetersCount = iperlHeads . Count ;
ShuffleTextBoxes ( WaterMetersCount , ProcessData . LineSize ) ;
Correction . PrepareForTestsActivities ( WaterMetersCount ) ;
}
/// <summary>
/// this part works fine if we are on <b>test loop</b>
/// - because ProcessData.RegisterReaders is initialized in test loop
/// </summary>
private static void InitializeSmartReaderLists ( )
{
2025-11-06 13:11:13 +00:00
iperlHeads = new List < ISmartReader > ( ) ;
2025-10-18 07:59:07 +00:00
waterMeterPositions0 = new List < int > ( ) ;
///
for ( int wmPos = 0 ; wmPos < ProcessData . RegisterReaders . Length ; wmPos + + )
{
2025-11-06 13:11:13 +00:00
ISmartReader iperlHead = ProcessData . RegisterReaders [ wmPos ] as ISmartReader ;
2025-10-18 07:59:07 +00:00
2025-11-12 11:34:29 +00:00
if ( iperlHead ! = null ) // what if iperlHead should be null
2025-11-06 13:11:13 +00:00
{
2025-10-18 07:59:07 +00:00
iperlHeads . Add ( iperlHead ) ;
waterMeterPositions0 . Add ( wmPos ) ;
2025-11-06 13:11:13 +00:00
}
2025-10-18 07:59:07 +00:00
}
2025-11-06 13:11:13 +00:00
}
2025-10-18 07:59:07 +00:00
2025-11-06 13:11:13 +00:00
/// <summary>
/// Called when communication with all watermeters is completed
/// </summary>
static void OnAllCompleted ( object sender , AllCompletedEventArgs data )
{
if ( AllCompletedHandler = = null ) return ;
try { AllCompletedHandler ( sender , data ) ; }
catch ( Exception e ) { log . Error ( "AllCompletedHandler(...) failed" , e ) ; }
}
private void DoOnCommCompleted ( object sender , CommCompletedEventArgs data )
{
2025-11-12 11:34:29 +00:00
Correction . DoOnCommCompleted ( sender , data , waterMeterPositions0 ) ;
2025-10-18 07:59:07 +00:00
}
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +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 )
{
labels = new Label [ MaxTextBoxesCount ]
{
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 ,
} ;
counters = new PictureBox [ MaxTextBoxesCount ]
{
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 ,
} ;
messages = new TextBox [ MaxTextBoxesCount ]
{
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 ,
} ;
checkBoxes = new CheckBoxImage [ MaxTextBoxesCount ]
{
checkBoxImage1 , checkBoxImage2 , checkBoxImage3 , checkBoxImage4 , checkBoxImage5 , checkBoxImage6 , checkBoxImage7 , checkBoxImage8 , checkBoxImage9 , checkBoxImage10 ,
checkBoxImage11 , checkBoxImage12 , checkBoxImage13 , checkBoxImage14 , checkBoxImage15 , checkBoxImage16 , checkBoxImage17 , checkBoxImage18 , checkBoxImage19 , checkBoxImage20 ,
checkBoxImage21 , checkBoxImage22 , checkBoxImage23 , checkBoxImage24 , checkBoxImage25 , checkBoxImage26 , checkBoxImage27 , checkBoxImage28 , checkBoxImage29 , checkBoxImage30 ,
checkBoxImage31 , checkBoxImage32 , checkBoxImage33 , checkBoxImage34 , checkBoxImage35 , checkBoxImage36 , checkBoxImage37 , checkBoxImage38 , checkBoxImage39 , checkBoxImage40 ,
checkBoxImage41 , checkBoxImage42 , checkBoxImage43 , checkBoxImage44 , checkBoxImage45 , checkBoxImage46 , checkBoxImage47 , checkBoxImage48 ,
} ;
ckbIndex = new int [ MaxTextBoxesCount ] ;
ckbState = new bool [ MaxTextBoxesCount ] ;
textBoxesCount = MaxTextBoxesCount ;
///
if ( wmsCount < textBoxesCount & & lineSize > 0 )
{
int nrLines = ( wmsCount + lineSize - 1 ) / lineSize ;
2025-11-12 11:34:29 +00:00
int gap = nrLines = = 0 ? 0 : ( textBoxesCount - wmsCount ) / nrLines ;
2025-10-18 07:59:07 +00:00
for ( int i = 0 ; i < ckbIndex . Length ; i + + )
{
ckbIndex [ i ] = - 1 ; /// Initialize with invalid indices
}
int dest = 0 ;
for ( int l = 0 ; l < nrLines ; l + + )
{
for ( int i = 0 ; i < lineSize ; i + + )
{
int origin = l * lineSize + l * gap + i ;
labels [ dest ] = labels [ origin ] ;
counters [ dest ] = counters [ origin ] ;
messages [ dest ] = messages [ origin ] ;
checkBoxes [ dest ] = checkBoxes [ origin ] ;
ckbIndex [ origin ] = dest ;
dest + + ;
}
}
textBoxesCount = wmsCount ;
}
2025-11-12 11:34:29 +00:00
int count = checkBoxesEditMode ? textBoxesCount : Math . Min ( textBoxesCount , Correction . GetHeadsCount ( ) ) ;
2025-10-18 07:59:07 +00:00
for ( int j = 0 ; j < count ; j + + )
{
labels [ j ] . Text = ( j + 1 ) . ToString ( ) ;
}
ResizeDlgToFitEnabledControls ( ) ;
}
void ResizeDlgToFitEnabledControls ( )
{
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 + 50 ;
Height = yMax + 60 ;
}
void Localize ( )
{
Text = checkBoxesEditMode ? Strings . Optical_heads : Strings . Water_Meter_States ;
saveButton . Text = Strings . Save ;
sampleLabel1 . Text = Strings . Direction_and_pulses_are_OK ;
sampleLabel2 . Text = Strings . There_are_no_opto_pulses ;
sampleLabel3 . Text = Strings . Direction_is_NOK ;
samplePictureBox1 . BackColor = iPerlCommunicationConstants . OptoAndDirOKColor ;
samplePictureBox2 . BackColor = iPerlCommunicationConstants . OptoNokColor ;
samplePictureBox3 . BackColor = iPerlCommunicationConstants . DirNokColor ;
}
2025-11-12 11:34:29 +00:00
private void SmartCommunicationForm_Load ( object sender , EventArgs e )
2025-10-18 07:59:07 +00:00
{
Localize ( ) ;
if ( checkBoxesEditMode )
{
/// Check box edit mode => Hide explanation of activity colours
sampleLabel1 . Visible = false ;
sampleLabel2 . Visible = false ;
sampleLabel3 . Visible = false ;
samplePictureBox1 . Visible = false ;
samplePictureBox2 . Visible = false ;
samplePictureBox3 . Visible = false ;
}
2025-11-12 11:34:29 +00:00
if ( _corrections . Count > 0 ) //enable combo for choose SmartMeter
{
meterTypeComboBox . Visible = true ;
}
Correction . Load ( labels , counters , messages , checkBoxes , ckbIndex , ckbState , iperlHeads , textBoxesCount , checkBoxesEditMode ) ;
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
///
/// Set location and checkbox states to values stored in local settings
///
TBF . LocalSettings ls = Program . LocalSettings ;
Left = ( ls . iPerlCommunicationsFormLeft ! = 0 ) ? ls . iPerlCommunicationsFormLeft : 150 ;
Top = ( ls . iPerlCommunicationsFormTop ! = 0 ) ? ls . iPerlCommunicationsFormTop : 150 ;
SetCheckBoxStates ( ls . OptoHeadsEnabled ) ;
if ( ! checkBoxesEditMode )
{
/// Regular activity (not a checkbox edit mode invoked from TBF menu)
/// Reset opto-data indication
2025-11-12 11:34:29 +00:00
for ( int i = 0 ; i < Correction . GetHeadsCount ( ) ; i + + )
2025-10-18 07:59:07 +00:00
{
counters [ i ] . BackColor = iPerlCommunicationConstants . OptoNokColor ;
}
/// Start communication process by incrementing 'currentGroup'.
currentGroup + + ;
int wtId = 0 ;
2025-11-12 11:34:29 +00:00
foreach ( var wt in Correction . GetAllThreads ( ) )
2025-10-18 07:59:07 +00:00
{
wt . Start ( new Boxes . IntBox ( wtId + + ) ) ; /// Start worker threads !!!
}
}
}
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
#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 ;
2025-11-12 11:34:29 +00:00
Correction ? . StopWorkerThreads ( true ) ;
2025-10-18 07:59:07 +00:00
forcedClose = true ;
DialogResult = DialogResult . Cancel ;
Close ( ) ;
}
#endregion
/// <summary>
/// Worker thread
/// </summary>
/// <param name="threadData">Thread ID (integer) wrapped into IntBox</param>
void Worker ( object threadData )
{
2025-11-12 11:34:29 +00:00
Correction ? . Worker ( threadData ) ;
2025-11-06 13:11:13 +00:00
}
2025-10-18 07:59:07 +00:00
2025-11-06 13:11:13 +00:00
void StartDataStreamProcessingForActiveMeters ( int iMultiTestParamsItem )
{
2025-11-12 11:34:29 +00:00
Correction ? . StartDataStreamProcessingForActiveMeters ( iMultiTestParamsItem ) ;
2025-10-18 07:59:07 +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 ;
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
public static event EventHandler < AllCompletedEventArgs > AllCompletedHandler ;
void DoOnAllCompleted ( object sender , AllCompletedEventArgs data )
{
Text = data . CommMessage ;
}
2025-11-06 13:11:13 +00:00
2025-10-18 07:59:07 +00:00
#region Check boxes edit mode support
private void checkBoxImage1_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 0 ] ] = checkBoxImage1 . Checked ; }
private void checkBoxImage2_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 1 ] ] = checkBoxImage2 . Checked ; }
private void checkBoxImage3_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 2 ] ] = checkBoxImage3 . Checked ; }
private void checkBoxImage4_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 3 ] ] = checkBoxImage4 . Checked ; }
private void checkBoxImage5_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 4 ] ] = checkBoxImage5 . Checked ; }
private void checkBoxImage6_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 5 ] ] = checkBoxImage6 . Checked ; }
private void checkBoxImage7_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 6 ] ] = checkBoxImage7 . Checked ; }
private void checkBoxImage8_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 7 ] ] = checkBoxImage8 . Checked ; }
private void checkBoxImage9_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 8 ] ] = checkBoxImage9 . Checked ; }
private void checkBoxImage10_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 9 ] ] = checkBoxImage10 . Checked ; }
private void checkBoxImage11_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 10 ] ] = checkBoxImage11 . Checked ; }
private void checkBoxImage12_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 11 ] ] = checkBoxImage12 . Checked ; }
private void checkBoxImage13_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 12 ] ] = checkBoxImage13 . Checked ; }
private void checkBoxImage14_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 13 ] ] = checkBoxImage14 . Checked ; }
private void checkBoxImage15_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 14 ] ] = checkBoxImage15 . Checked ; }
private void checkBoxImage16_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 15 ] ] = checkBoxImage16 . Checked ; }
private void checkBoxImage17_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 16 ] ] = checkBoxImage17 . Checked ; }
private void checkBoxImage18_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 17 ] ] = checkBoxImage18 . Checked ; }
private void checkBoxImage19_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 18 ] ] = checkBoxImage19 . Checked ; }
private void checkBoxImage20_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 19 ] ] = checkBoxImage20 . Checked ; }
private void checkBoxImage21_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 20 ] ] = checkBoxImage21 . Checked ; }
private void checkBoxImage22_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 21 ] ] = checkBoxImage22 . Checked ; }
private void checkBoxImage23_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 22 ] ] = checkBoxImage23 . Checked ; }
private void checkBoxImage24_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 23 ] ] = checkBoxImage24 . Checked ; }
private void checkBoxImage25_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 24 ] ] = checkBoxImage25 . Checked ; }
private void checkBoxImage26_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 25 ] ] = checkBoxImage26 . Checked ; }
private void checkBoxImage27_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 26 ] ] = checkBoxImage27 . Checked ; }
private void checkBoxImage28_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 27 ] ] = checkBoxImage28 . Checked ; }
private void checkBoxImage29_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 28 ] ] = checkBoxImage29 . Checked ; }
private void checkBoxImage30_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 29 ] ] = checkBoxImage30 . Checked ; }
private void checkBoxImage31_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 30 ] ] = checkBoxImage31 . Checked ; }
private void checkBoxImage32_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 31 ] ] = checkBoxImage32 . Checked ; }
private void checkBoxImage33_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 32 ] ] = checkBoxImage33 . Checked ; }
private void checkBoxImage34_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 33 ] ] = checkBoxImage34 . Checked ; }
private void checkBoxImage35_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 34 ] ] = checkBoxImage35 . Checked ; }
private void checkBoxImage36_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 35 ] ] = checkBoxImage36 . Checked ; }
private void checkBoxImage37_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 36 ] ] = checkBoxImage37 . Checked ; }
private void checkBoxImage38_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 37 ] ] = checkBoxImage38 . Checked ; }
private void checkBoxImage39_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 38 ] ] = checkBoxImage39 . Checked ; }
private void checkBoxImage40_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 39 ] ] = checkBoxImage40 . Checked ; }
private void checkBoxImage41_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 40 ] ] = checkBoxImage41 . Checked ; }
private void checkBoxImage42_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 41 ] ] = checkBoxImage42 . Checked ; }
private void checkBoxImage43_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 42 ] ] = checkBoxImage43 . Checked ; }
private void checkBoxImage44_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 43 ] ] = checkBoxImage44 . Checked ; }
private void checkBoxImage45_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 44 ] ] = checkBoxImage45 . Checked ; }
private void checkBoxImage46_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 45 ] ] = checkBoxImage46 . Checked ; }
private void checkBoxImage47_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 46 ] ] = checkBoxImage47 . Checked ; }
private void checkBoxImage48_Click ( object sender , EventArgs e ) { ckbState [ ckbIndex [ 47 ] ] = checkBoxImage48 . Checked ; }
/// <summary>
/// Get states of checkboxes as one bitfield (long)
/// </summary>
/// <returns>Long bitfield</returns>
2025-11-06 13:11:13 +00:00
public long GetCheckBoxStates ( )
2025-10-18 07:59:07 +00:00
{
long result = 0 ;
for ( int i = 0 ; i < 48 ; i + + )
{
int wmNr0 = ckbIndex [ i ] ;
if ( wmNr0 > = 0 & & ckbState [ wmNr0 ] )
{
result + = ( 1L < < wmNr0 ) ;
}
}
return result ;
}
/// <summary>
/// Set checkboxes to states stored in a bitfield (long)
/// </summary>
private void SetCheckBoxStates ( long state )
{
CheckBoxImage [ ] chkBoxes = new CheckBoxImage [ 48 ]
{
checkBoxImage1 , checkBoxImage2 , checkBoxImage3 , checkBoxImage4 , checkBoxImage5 ,
checkBoxImage6 , checkBoxImage7 , checkBoxImage8 , checkBoxImage9 , checkBoxImage10 ,
checkBoxImage11 , checkBoxImage12 , checkBoxImage13 , checkBoxImage14 , checkBoxImage15 ,
checkBoxImage16 , checkBoxImage17 , checkBoxImage18 , checkBoxImage19 , checkBoxImage20 ,
checkBoxImage21 , checkBoxImage22 , checkBoxImage23 , checkBoxImage24 , checkBoxImage25 ,
checkBoxImage26 , checkBoxImage27 , checkBoxImage28 , checkBoxImage29 , checkBoxImage30 ,
checkBoxImage31 , checkBoxImage32 , checkBoxImage33 , checkBoxImage34 , checkBoxImage35 ,
checkBoxImage36 , checkBoxImage37 , checkBoxImage38 , checkBoxImage39 , checkBoxImage40 ,
checkBoxImage41 , checkBoxImage42 , checkBoxImage43 , checkBoxImage44 , checkBoxImage45 ,
checkBoxImage46 , checkBoxImage47 , checkBoxImage48 ,
} ;
for ( int i = 0 ; i < 48 ; i + + )
{
int wmNr0 = ckbIndex [ i ] ;
if ( wmNr0 > = 0 )
{
chkBoxes [ i ] . Checked = ckbState [ wmNr0 ] = ( ( state & ( 1L < < wmNr0 ) ) ! = 0 ) ;
}
}
}
private void saveButton_Click ( object sender , EventArgs e )
{
Program . LocalSettings . OptoHeadsEnabled = GetCheckBoxStates ( ) ;
Program . LocalSettings . Save ( ) ;
DialogResult = DialogResult . OK ;
Close ( ) ;
}
#endregion
private void SmartCommunicationForm_FormClosing ( object sender , FormClosingEventArgs e )
{
if ( ! forcedClose & & ! formCompleted & & ! checkBoxesEditMode )
{
e . Cancel = true ;
}
}
2025-11-06 13:11:13 +00:00
public void NormalClose ( )
{
CommCompletedHandler = null ;
AllCompletedHandler = null ;
2025-11-12 11:34:29 +00:00
Correction ? . NormalClose ( waterMeterPositions0 ) ;
2025-11-06 13:11:13 +00:00
long checkboxStates = GetCheckBoxStates ( ) ;
if ( Program . LocalSettings . iPerlCommunicationsFormLeft ! = Location . X | |
Program . LocalSettings . iPerlCommunicationsFormTop ! = Location . Y | |
Program . LocalSettings . OptoHeadsEnabled ! = checkboxStates )
{
/// Update local settings
Program . LocalSettings . iPerlCommunicationsFormLeft = Location . X ;
Program . LocalSettings . iPerlCommunicationsFormTop = Location . Y ;
Program . LocalSettings . OptoHeadsEnabled = checkboxStates ;
Program . LocalSettings . Save ( ) ;
}
formCompleted = true ;
DialogResult = DialogResult . OK ;
Close ( ) ;
}
2025-11-12 11:34:29 +00:00
private void meterTypeComboBox_SelectedIndexChanged ( object sender , EventArgs e )
{
ComboBox senderCombo = sender as ComboBox ;
if ( senderCombo = = null ) return ;
SelectedTypeReader = senderCombo . SelectedItem ? . ToString ( ) ;
UpdateHeads ( ) ;
}
2025-10-18 07:59:07 +00:00
}
}