tbf/TBF/Rig/Uni/SharedDialogs/SmartMetersCommunication/SmartCommunicationForm.cs

933 lines
36 KiB
C#

///
/// Copyright (c) 2015-2023 Sensus Slovensko a.s.
///
//#define VERIFY_ACTIVE_MODE
//#define VERIFY_Q2_CORR_RESET
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Forms;
using Config.Entities;
using log4net;
using NHibernate.Util;
using TBF.Resources;
using TBF.Rig.Generic;
using TBF.Rig.RegisterReaders.CommonRR.IPerl;
using TBF.Rig.RegisterReaders.iPerlReaderUNI;
using TBF.Rig.RegisterReaders.PoseidonReader;
using TBF.Rig.Sequences;
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.implementations;
using TBF.Tools;
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;
// Set to 'true' when the form closes
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;
static IList<ISmartReader> iperlHeads;
static IList<int> waterMeterPositions0; /// keeps original 0-based indices in RegisterReaders list
static int commonWMType;
//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; }
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
private static List<ICorrections> _corrections;
// Setting the initial combobox item raises SelectedIndexChanged before the
// constructor has finished preparing the form and its local settings.
private bool initializingMeterTypeItems;
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();
}
return null;
}
}
private List<string> TypeReaders
{
get { return IdentifyReaderTypes(); }
}
public static string SelectedTypeReader { get; set; }
private List<ICorrections> GetNewCorrectionList(ISmartTestMethod componentBase ,
ITestMethodCfg 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,log, rfidDataLogger, componentBase, cfg, tests, multiTestParams));
continue;
}
throw new Exception("Unknown smart head type");
}
catch (Exception e)
{
log.Error("IdentifyReaderTypes()", e);
}
}
return correctionsList;
}
private static List<ICorrections> GetNewCorrectionList(SmartCommunicationForm form)
{
// Manual communication is extended by registering a correction adapter here.
// An adapter is included only when at least one configured reader belongs to it.
// This keeps unsupported protocols out of the type selector and context menu.
List<ICorrections> candidates = new List<ICorrections>
{
new IPerlCorrections(form),
new IPerlASICCorrections(form),
new GenesisCorrections(form),
new AllyCorrections(form),
new PoseidonCorrections(form)
};
if (ProcessData.SmartHeadsUni == null)
return new List<ICorrections>();
return candidates
.Where(correction => ProcessData.SmartHeadsUni.Any(correction.IsFamilyOfSmartReader))
.ToList();
}
public static List<string> IdentifyReaderTypes()
{
List<string> typeReaders = new List<string>();
if (_corrections == null || ProcessData.SmartHeadsUni == null)
return typeReaders;
foreach (ICorrections correction in _corrections)
{
if (ProcessData.SmartHeadsUni.Any(correction.IsFamilyOfSmartReader))
typeReaders.Add(correction.TypeIdentificatorName());
}
return typeReaders;
}
public static ITestMethodCfg? TestMethodCfg
{
get
{
return Correction?.Cfg;
}
set
{
// Add null check for the value being set
if (value == null)
{
// Log or handle null case
return;
}
if (_corrections == null || _corrections.Count == 0)
{
_corrections = GetNewCorrectionList(null);
}
foreach (var correction in _corrections)
{
correction.Cfg = value;
}
}
}
static int currentActivityStep;
static int currentGroup; /// form -> worker thread (0 = none)
static int lastGroup;
static int completedCommCount; /// Number of completed communication steps
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
public SmartCommunicationForm()
{
InitializeComponent();
this.Icon = Properties.Resources.TBF_icon;
}
/// <summary>
/// Constructor for checkBox states (active/inactive iPerl head) editing.
/// </summary>
/// <param name="checkBoxes">Initial check box states</param>
public SmartCommunicationForm(bool isCheckBoxesEditMode)
: this()
{
//TODO get corrections based on defined meter
_corrections = GetNewCorrectionList(this); // default iPerl Head communication params
InitializeMeterTypeItems();
if (isCheckBoxesEditMode)
{
checkBoxesEditMode = true;
saveButton.Visible = true;
activityLabel.Text = Strings.Optical_heads;
ShuffleTextBoxes(ProcessData.WMsCount, ProcessData.LineSize);
//this.ContextMenu = Correction.GetContextMenu();
}
InitializeWaterMeterData();
if (iperlHeads.Count <= 0)
UpdateHeads();
}
/// <summary>
/// Constructor for one iPerlCommunication 'test'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public SmartCommunicationForm(Generic.IComponent componentBase, Test test, ITestParams testParams)
: this(componentBase, new List<Test> { test }, new List<ITestParams> { testParams })
{
}
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public SmartCommunicationForm(Generic.IComponent componentBase, IList<Test> tests, IList<ITestParams> multiTestParams)
: this()
{
checkBoxesEditMode = false;
ITestMethodCfg cfg = (componentBase as ITestMethodCfg);
ISmartTestMethod smartTestMethod = componentBase as ISmartTestMethod;
//TODO get corrections based on defined meter
_corrections = GetNewCorrectionList(smartTestMethod, smartTestMethod.TestMethodCfg, tests, multiTestParams);
InitializeMeterTypeItems();
UpdateHeads();
//_corrections = new PoseidonCorrections(this, log, rfidDataLogger, componentBase as ISmartTestMethod,componentBase.Cfg as TestMethodCfg,tests,multiTestParams);
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;
}
}
}
/// Attach to 'CommCompleted' handler
SmartCommunicationForm.CommCompletedHandler += delegate(object sender, CommCompletedEventArgs args)
{
if (InvokeRequired)
{
Invoke(new EventHandler<CommCompletedEventArgs>(DoOnCommCompleted), sender, args);
}
else DoOnCommCompleted(sender, args);
};
/// 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();
InitializeWaterMeterData();
}
private void UpdateHeads()
{
if (!(waterMeterPositions0 == null || waterMeterPositions0.Count <= 0)
&& labels != null && counters != null && messages != null && checkBoxes != null)
{
foreach (int position in waterMeterPositions0)
{
try
{
labels[position].Visible = false;
counters[position].Visible = false;
messages[position].Visible = false;
checkBoxes[position].Visible = false;
ckbIndex[position] = 0;
ckbState[position] = false;
}
catch (Exception e)
{
log.Error("UpdateHeads()", e);
}
}
}
iperlHeads?.Clear();
if (iperlHeads == null) iperlHeads = new List<ISmartReader>();
waterMeterPositions0?.Clear();
if (waterMeterPositions0 == null) waterMeterPositions0 = new List<int>();
//iperlHeads = ProcessData.SmartHeadsUni;
ICorrections corre = null;
if (string.IsNullOrEmpty(SelectedTypeReader))
{
ISmartReader firstReader = ProcessData.SmartHeadsUni?.FirstOrDefault();
corre = _corrections.FirstOrDefault(correction => correction.IsFamilyOfSmartReader(firstReader));
}
else
{
corre = _corrections.FirstOrDefault(
correction => correction.TypeIdentificatorName() == SelectedTypeReader);
}
if (corre != null)
{
for (int wmPos = 0; wmPos < ProcessData.SmartHeadsUni.Count; wmPos++)
{
ISmartReader smartHead = ProcessData.SmartHeadsUni[wmPos];
if (corre.IsFamilyOfSmartReader(smartHead))
{
iperlHeads.Add(smartHead);
waterMeterPositions0.Add(wmPos);
}
}
//we have items from the list, so we can enable the rows
if (iperlHeads.Count > 0)
{
WaterMetersCount = iperlHeads.Count;
ShuffleTextBoxes(WaterMetersCount, ProcessData.LineSize);
this.ContextMenu = corre.GetContextMenu();
corre.PrepareForTestsActivities(WaterMetersCount);
}
else
{
this.ContextMenu = null;
}
}
}
private void InitializeMeterTypeItems()
{
if (_corrections != null && _corrections.Count > 0)
{
initializingMeterTypeItems = true;
try
{
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;
}
finally
{
initializingMeterTypeItems = false;
}
}
}
private void InitializeWaterMeterData()
{
if (checkBoxesEditMode)
{
// In manual mode the selected family must determine the displayed heads.
// Do not preload all smart readers and overwrite the combobox selection.
UpdateHeads();
}
else
{
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>
/// <param name="selectedTypeReader"></param>
private static void InitializeSmartReaderLists()
{
iperlHeads = new List<ISmartReader>();
waterMeterPositions0 = new List<int>();
///
for (int wmPos = 0; wmPos < ProcessData.RegisterReaders.Length; wmPos++)
{
ISmartReader iperlHead = ProcessData.RegisterReaders[wmPos] as ISmartReader;
if (iperlHead != null) // what if iperlHead should be null
{
iperlHeads.Add(iperlHead);
waterMeterPositions0.Add(wmPos);
}
}
}
/// <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)
{
Correction.DoOnCommCompleted(sender, data, waterMeterPositions0);
}
/// <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)
{
InitializeTextBoxArrays();
///
if (wmsCount < textBoxesCount && lineSize > 0)
{
int nrLines = (wmsCount + lineSize - 1) / lineSize;
int gap = nrLines==0? 0 : (textBoxesCount - wmsCount) / nrLines;
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;
}
int count = checkBoxesEditMode ? textBoxesCount : Math.Min(textBoxesCount, Correction.GetHeadsCount());
for (int j = 0; j < count; j++)
{
labels[j].Text = (j + 1).ToString();
}
ResizeDlgToFitEnabledControls();
}
private void InitializeTextBoxArrays()
{
//if is initialized before we ignore initialization
if (labels != null
&& counters != null
&& messages != null
&& checkBoxes != null
&& ckbIndex != null
&& ckbState != null) return;
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;
}
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;
}
private void SmartCommunicationForm_Load(object sender, EventArgs e)
{
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;
}
if (_corrections == null || _corrections.Count == 0 || Correction == null)
{
ContextMenu = null;
log.Warn("SmartCommunicationForm opened without a registered manual communication adapter.");
return;
}
if (_corrections.Count > 0)//enable combo for choose SmartMeter
{
meterTypeComboBox.Visible = true;
}
Correction.Load(labels,counters,messages,checkBoxes,ckbIndex,ckbState, iperlHeads,textBoxesCount,checkBoxesEditMode );
///
/// Set location and checkbox states to values stored in local settings
///
TBF.LocalSettings ls = Program.LocalSettings;
if (ls == null)
{
log.Warn("SmartCommunicationForm loaded before LocalSettings were initialized; using default window and checkbox state.");
Left = 150;
Top = 150;
SetCheckBoxStates(0);
}
else
{
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
for (int i = 0; i < Correction.GetHeadsCount(); i++)
{
counters[i].BackColor = iPerlCommunicationConstants.OptoNokColor;
}
/// Start communication process by incrementing 'currentGroup'.
//currentGroup++;
int wtId = 0;
foreach (var wt in Correction.GetAllThreads())
{
wt.Start(new Boxes.IntBox(wtId++)); /// Start worker threads !!!
}
}
}
#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;
Correction?.StopWorkerThreads(true);
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)
{
Correction?.Worker(threadData);
}
void StartDataStreamProcessingForActiveMeters(int iMultiTestParamsItem)
{
Correction?.StartDataStreamProcessingForActiveMeters(iMultiTestParamsItem);
}
/// <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;
public static event EventHandler<AllCompletedEventArgs> AllCompletedHandler;
void DoOnAllCompleted(object sender, AllCompletedEventArgs data)
{
Text = data.CommMessage;
}
#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>
public long GetCheckBoxStates()
{
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;
}
}
public void NormalClose()
{
CommCompletedHandler = null;
AllCompletedHandler = null;
Correction?.NormalClose(waterMeterPositions0);
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();
}
private void meterTypeComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (initializingMeterTypeItems) return;
ComboBox senderCombo = sender as ComboBox;
if (senderCombo == null) return;
SelectedTypeReader = senderCombo.SelectedItem?.ToString();
UpdateHeads();
SmartCommunicationForm_Load(this, EventArgs.Empty);
}
}
}