tbf/TBF/Rig/TestMethods/GenesisCommunication/GenesisCommunicationForm.cs

1935 lines
84 KiB
C#

using TBF.Rig.TestMethods.iPerlCommunication;
///
/// 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.Drawing;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using log4net;
using Common;
using Config.Entities;
using TBF.Resources;
using TBF.Rig.Sequences;
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
using Results.Entities;
using static Sensus.iPerl.NfcHandler.MCI_Protocol;
using System.Threading.Tasks;
using TBF.Rig.RegisterReaders.GenesisRegReader.communication;
using TBF.Rig.RegisterReaders.GenesisRegReader.implementations;
using TBF.Rig.TestMethods.GenesisCommunication;
using TBF.Rig.TestMethods.iPerlCommunication.communication;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
using TBF.Rig.Uni.SharedDialogs.SmartMetersCommunication.common;
using CommunicationInterface = TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.CommunicationInterface;
using ConfigStruct = TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.ConfigStruct;
using MessageID = TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.MessageID;
using MeterType = TBF.Rig.TestMethods.iPerlCommunication.iPerlHead.MeterType;
namespace TBF.Rig.TestMethods.GenesisCommunication
{
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
FailedInit, /// 14H = 20
FailedConnect, /// 15H = 21
FailedReadSerialNr, /// 16H = 22
FailedSetPassword, /// 17H = 23
FailedLogin, /// 18H = 24
FailedSetTestMode, /// 19H = 25
FailedSetActiveMode, /// 1AH = 26
FailedWriteCalibrationFactor,/// 1BH = 27
FailedWriteRegister,/// 1CH = 28
FailedPrepare, /// 1DH = 29
}
public partial class GenesisCommunicationForm : Form, GenericDevices.IHasCompleted
{
private static readonly ILog log = LogManager.GetLogger(typeof(GenesisCommunicationForm));
protected static readonly ILog rfidDataLogger = LogManager.GetLogger("RfidData");
const int Hz2CorrFactorsAddr = 0x1875; /// Used by Reset2HzCorrection(...) and Write2HzCorrection(...)
const int Q2CorrFactorsAddr = 0x1878; /// Used by ResetQ2Correction(...) and WriteQ2Correction(...)
const int Q2CorrFactorsAddrLR = 0x1878;
const int Q2CorrFactorsAddrRL = 0x1879;
public const string SlotInitializeStr = "Initialise Slot";
public const string SlotUpdateStr = "Update Slot";
public const string SlotConnectStr = "Connect Slot";
public const string SlotPCBSlotStr = "PCB Slot";
public const string SlotSetPasswordStr = "Set Password";
public const string SlotLoginStr = "Login";
public const string SlotGroupedLoginStr = "Login (Combined workflow)";
public const string SlotSetTestModeStr = "Switch to Test Mode";
public const string SlotSetActiveModeStr ="Switch to Active Mode";
public const string SlotDisconnectStr = "Disconnect Slot";
public const string PrepareSlotQ3CalibrationStr = "Prepare Q3 Calibration Slot";
public const string WriteSlotQ3CalibrationStr = "Write Q3 Calibration Slot";
public const string CheckMeterPrepareStr = "Check Meter Prepare Slot";
public const string HoldSlotStr = "Hold Slot";
public const string PrepareInitializeStr = "Initialise Prepare";
public const string ReadConfigurationStr = "Read configuration"; /// Example: "Read configuration" or "Read configuration if enabled"
public const string SetTestModeStr = "Set Test mode"; /// Example: "Set Test mode" or "Set Test mode A0" (hexadecimal number is the required 'testModeConfig'
public const string SetActiveModeStr = "Set Active mode";
public const string ReadSerialNrStr = "Read SerialNr";
public const string SetIdleModeStr = "Set Idle mode";
public const string ReadCalibrationStr = "Read calibration";
public const string ReadCalibrationV4Str = "Read calibration_V4";
public const string WriteCalibrationFactorStr = "Write calibration factor";
public const string WriteCalibrationV4FactorsStr = "Write calibration_V4";
public const string NormalizeCalibrationFactorStr = "Normalize calibration factor";
public const string NormalizeCalibrationV4FactorsStr = "Normalize calibration_V4";
public const string GetDefaultQ2CorrectionsStr = "Get default Q2 corrections";
public const string ReadQ2CorrectionStr = "Read Q2 corrections";
public const string ResetQ2CorrectionStr = "Reset Q2 correction";
public const string WriteDefaultQ2CorrectionsStr = "Write default Q2 corrections";
public const string InitOrReadQ2CorrectionsStr = "Init or read Q2 corrections";
public const string WriteQ2CorrectionStr = "Write Q2 correction"; /// No arguments
public const string WriteQ2CorrectionAltStr = "Write Q2 correction Alt"; /// No arguments
public const string WriteQ2CorrectionGreeceStr = "Write Q2 correction Greece"; /// Arguments: test_name
public const string WriteQ2CorrectionRLStr = "Write Q2 correction R-L"; /// Arguments: test_name
public const string WriteQ2CorrectionLRStr = "Write Q2 correction L-R"; /// Arguments: test_name
public const string WriteQ2CorrectionIncl05Str = "Write_Q2_correction_incl.-0,5..0,5%"; /// No arguments
public const string WriteQ2CorrectionAltIncl05Str = "Write_Q2_correction_Alt_incl.-0,5..0,5%"; /// No arguments
public const string WriteQ2CorrectionPlusIncl05Str = "Write_Q2_correction_plus_incl.-0,5..0,5%"; /// No arguments
public const string WriteQ2CorrectionPlusAltIncl05Str = "Write_Q2_correction_plus_Alt_incl.-0,5..0,5%"; /// No arguments
public const string WriteQ2CorrectionGreeceIncl05Str = "Write_Q2_correction_Greece_incl.-0,5..0,5%"; /// Arguments: test_name
public const string WriteQ2CorrectionRLIncl05Str = "Write_Q2_correction_R-L_incl.-0,5..0,5%"; /// Arguments: test_name
public const string WriteQ2CorrectionLRIncl05Str = "Write_Q2_correction_L-R_incl.-0,5..0,5%"; /// Arguments: test_name
public const string UpdateBothQ2FactorsTestRLOnlyStr = "Update_both_Q2_factors_Test_RL_only"; /// No arguments
public const string UpdateBothQ2FactorsTestLROnlyStr = "Update_both_Q2_factors_Test_LR_only"; /// No arguments
public const string UpdateQ2CorrectionsStr = "Update Q2 corrections"; /// Arguments: R-L_test_name L-R_test_name
public const string ConditnlUpdateQ2CorrectionsStr = "Conditional update of Q2 corrections"; /// Arguments: R-L_test_name L-R_test_name
public const string ConditnlUpdateQ2CorrRLStr = "Conditional update of Q2 correction R-L"; /// Arguments: R-L_test_name
public const string ConditnlUpdateQ2CorrLRStr = "Conditional update of Q2 correction L-R"; /// Arguments: L-R_test_name
public const string Reset2HzCorrectionStr = "Reset 2Hz correction";
public const string Write2HzCorrectionStr = "Write 2Hz correction";
public const string DewaReworkRLStr = "DEWA rework R-L";
public const string DewaReworkLRStr = "DEWA rework L-R";
public const string StartTestingSealedMetersStr = "Start testing sealed meters";
public const string EndTestingSealedMetersStr = "End testing sealed meters";
public const string SimulateCmd = "simulate ";
public static Color DisabledColor = Color.DarkGray;
public static Color OptoAndDirOKColor = Color.Green;
public static Color OptoNokColor = Color.Orange;
public static Color DirNokColor = Color.Red;
#region Simulation / RFID / NFC Interface: ReadRequestPort, WriteRequestPort
/// <summary>
/// Wrapper function with safe interface and unsafe body
/// </summary>
/// <param name="iperlHead">Water meter (iPerlHead) object</param>
/// <returns>Value returned by readRequestPort(...)</returns>
/// <summary>
/// Wrapper function with safe interface and unsafe body
/// </summary>
/// <param name="iperlHead">Water meter (iPerlHead) object</param>
/// <returns>Value returned by writeRequestPort(...)</returns>
#endregion iPerl_Head_RFID_Interface: ReadRequestPort, WriteRequestPort
readonly bool checkBoxesEditMode;
DateTime startTime;
int startTimeSec;
// 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<GenesisSmartReader> genesisHeads;
static IList<int> waterMeterPositions0; /// keeps original 0-based indices in RegisterReaders list
static int commonWMType;
///
/// RFID multiplexer PCB / RFID serial port and worker thread related variables
///
static TestMethod testMethod;
public static TestMethodCfg cfg;
static IList<Config.Entities.Test> tests;
static IList<iPerlCommunicationParams> multiTestParams;
static volatile int currentActivityStep;
static volatile int currentGroup; /// form -> worker thread (0 = none)
static int lastGroup;
private GenesisWorkerGroupCompletion groupCompletion;
static IList<Thread> workerThreads;
static IList<int> muxBrdOrGroup14Nrs;
static volatile bool stopWorkerThreads; /// form -> worker thread
/// <summary> Parameterless constructor (without watermeters, threads) </summary>
public GenesisCommunicationForm()
{
InitializeComponent();
}
/// <summary>
/// Constructor for checkBox states (active/inactive iPerl head) editing.
/// </summary>
/// <param name="checkBoxes">Initial check box states</param>
public GenesisCommunicationForm(bool isCheckBoxesEditMode)
: this()
{
GenesisCommunicationForm.cfg = new TestMethodCfg(null); // default iPerl Head communication params
if (isCheckBoxesEditMode)
{
checkBoxesEditMode = true;
saveButton.Visible = true;
activityLabel.Text = Strings.Optical_heads;
ShuffleTextBoxes(ProcessData.WMsCount, ProcessData.LineSize);
#if IPERL
ContextMenu cm = new ContextMenu();
//////////////////////////////////////////////////////////////////////
cm.MenuItems.Add(NewMenuItem("Initialise Slot" , "Initialize"));
// cm.MenuItems.Add(NewMenuItem("Update Slot" , "Update"));
// cm.MenuItems.Add(NewMenuItem("Connect Slot" , "Connect"));
cm.MenuItems.Add(NewMenuItem("Login (Combined)" , "Login (Combined)"));
cm.MenuItems.Add(NewMenuItem("PCB Slot" , "PCBSlot"));
// cm.MenuItems.Add(NewMenuItem("Set Password" , "SetPassword"));
// cm.MenuItems.Add(NewMenuItem("Login" , "Login"));
cm.MenuItems.Add(NewMenuItem("Switch to Test Mode" , "SetTestMode"));
cm.MenuItems.Add(NewMenuItem("Switch to Active Mode" , "SetActiveMode"));
/////////////////////////////////////////////////////////////////////
this.ContextMenu = cm;
#endif
}
}
/// <summary>
/// Constructor for one iPerlCommunication 'test'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public GenesisCommunicationForm(TestMethod testMethod, Test test, iPerlCommunicationParams testParams)
: this(testMethod, new List<Test> { test }, new List<iPerlCommunicationParams> { testParams })
{
}
/// <summary>
/// Constructor for multiple iPerlCommunication 'tests'
/// </summary>
/// <param name="waterMetersCount">Number of text boxes for serial numbers</param>
public GenesisCommunicationForm(TestMethod testMethod, IList<Test> tests, IList<iPerlCommunicationParams> multiTestParams)
: this()
{
checkBoxesEditMode = false;
GenesisCommunicationForm.testMethod = testMethod;
GenesisCommunicationForm.cfg = testMethod.Cfg as TestMethodCfg;
GenesisCommunicationForm.tests = tests;
GenesisCommunicationForm.multiTestParams = 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() == GetDefaultQ2CorrectionsStr.ToLower())
{
/// Reset IsQ2PreCorrectionCalculated that is used for synchronization/to prevent double REST call
ProcessData.IsQ2PreCorrectionCalculated = false;
commonWMType = 0;
break;
}
}
}
PrepareForTestsActivities();
}
private bool CanUseUi()
{
return !IsDisposed && !Disposing && IsHandleCreated;
}
void PrepareForTestsActivities()
{
startTime = DateTime.Now;
startTimeSec = StateMachine.Time;
/// Attach to 'CommCompleted' handler
CommCompletedHandler += delegate(object sender, CommCompletedEventArgs args)
{
if (!CanUseUi()) return;
if (InvokeRequired)
{
try
{
BeginInvoke(new EventHandler<CommCompletedEventArgs>((s, a) =>
{
if (!CanUseUi()) return;
DoOnCommCompleted(s, a);
}), sender, args);
}
catch (ObjectDisposedException) { }
catch (InvalidOperationException) { }
}
else
{
DoOnCommCompleted(sender, args);
}
};
/// Attach to 'AllCompleted' handler
AllCompletedHandler += delegate(object sender, AllCompletedEventArgs args)
{
if (IsDisposed || Disposing || !IsHandleCreated)
return;
if (InvokeRequired)
{
try
{
BeginInvoke(new EventHandler<AllCompletedEventArgs>((s, a) =>
{
if (IsDisposed || Disposing)
return;
DoOnAllCompleted(s, a);
}), sender, args);
}
catch (ObjectDisposedException) { }
catch (InvalidOperationException) { }
}
else
{
DoOnAllCompleted(sender, args);
}
};
formCompleted = false;
StartForceCloseHandler();
genesisHeads = new List<GenesisSmartReader>();
waterMeterPositions0 = new List<int>();
///
for (int wmPos = 0; wmPos < ProcessData.RegisterReaders.Length; wmPos++)
{
GenesisSmartReader genesisSmartReader = ProcessData.RegisterReaders[wmPos] as GenesisSmartReader;
if (genesisSmartReader != null)
{
genesisHeads.Add(genesisSmartReader);
waterMeterPositions0.Add(wmPos);
}
}
WaterMetersCount = genesisHeads.Count;
ShuffleTextBoxes(WaterMetersCount, ProcessData.LineSize);
///
/// Prepare worker threads, 'rfidPortNrs', 'lastGroup', etc..
///
currentActivityStep = 0;
currentGroup = 0;
stopWorkerThreads = false;
/// group numbers are >=1, lastGroup == 0 means there is no group
lastGroup = 0;
foreach (var iPerl in GenesisCommunicationForm.genesisHeads)
{
if (iPerl.Group > lastGroup) lastGroup = iPerl.Group;
}
workerThreads = new List<Thread>();
for (int i = 0; i < cfg.NrThreads; i++)
{
Thread thread = new Thread(Worker);
thread.CurrentCulture = CultureInfo.CurrentCulture;
thread.CurrentUICulture = CultureInfo.CurrentUICulture;
workerThreads.Add(thread);
}
muxBrdOrGroup14Nrs = new List<int>();
foreach (var iPerl in GenesisCommunicationForm.genesisHeads)
{
if (!muxBrdOrGroup14Nrs.Contains(iPerl.MuxBoardNrOrGroup14)) muxBrdOrGroup14Nrs.Add(iPerl.MuxBoardNrOrGroup14);
}
groupCompletion = new GenesisWorkerGroupCompletion(workerThreads.Count);
groupCompletion.Begin(0, 1);
log.InfoFormat("Genesis workers configured: Threads={0}, Group1Count={1}, LastGroup2={2}", workerThreads.Count, muxBrdOrGroup14Nrs.Count, lastGroup);
log.WarnFormat("nrThreads = {0}", workerThreads.Count);
}
/// <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;
int gap = (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, genesisHeads.Count);
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 = OptoAndDirOKColor;
samplePictureBox2.BackColor = OptoNokColor;
samplePictureBox3.BackColor = DirNokColor;
}
private void GenesisCommunicationForm_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;
}
///
/// Set checkbox states accroding to iPerlHeads[i].Disabled states
///
for (int i = 0; i < textBoxesCount; i++)
{
labels[i].Visible = counters[i].Visible = messages[i].Visible = checkBoxes[i].Visible = true;
if (!checkBoxesEditMode && (genesisHeads[i] == null || genesisHeads[i].Disabled))
{
/// iPerl position i+1 is disabled
checkBoxes[i].Enabled = checkBoxes[i].Checked = ckbState[i] = false;
counters[i].BackColor = DisabledColor;
messages[i].Text = Strings.Head_was_disabled_by_the_user;
}
else
{
/// iPerl position i+1 is enabled
checkBoxes[i].Enabled = checkBoxes[i].Checked = ckbState[i] = true;
messages[i].Text = "---";
}
}
///
/// 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
for (int i = 0; i < genesisHeads.Count; i++)
{
counters[i].BackColor = OptoNokColor;
}
/// Start communication process by incrementing 'currentGroup'.
currentGroup++;
int wtId = 0;
foreach (var wt in workerThreads)
{
wt.Start(new Boxes.IntBox(wtId++)); /// Start worker threads !!!
}
}
}
private void NormalClose()
{
CommCompletedHandler = null;
AllCompletedHandler = null;
if (multiTestParams != null &&
multiTestParams.Count > 0 &&
!multiTestParams[0].SimultWithNext) /// RFID Communication at the end of the cycle does not influence the result
{
UpdateRfidCommResult(tests); /// TODO: Pass the test info in a correct way
}
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();
}
#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;
stopWorkerThreads = true;
forcedClose = true;
DialogResult = DialogResult.Cancel;
Close();
}
#endregion
private static int _messageBoxActive = 0;
// blocked while MessageBox is active
private static readonly ManualResetEventSlim _messageBoxDone =
new ManualResetEventSlim(true);
/// <summary>
/// Worker thread
/// </summary>
/// <param name="threadData">Thread ID (integer) wrapped into IntBox</param>
void Worker(object threadData)
{
int threadID = (threadData as Boxes.IntBox).Val;
int activityStep = 0; /// activity step > 0 in case multiTestParams are used
for (int i = 0; i < multiTestParams.Count; i++ )
{
while (activityStep != currentActivityStep && !stopWorkerThreads) Thread.Sleep(50);
if (stopWorkerThreads) break;
Test currentTest = tests[i];
iPerlCommunicationParams currentTestParams = multiTestParams[i];
string currentActivity = currentTestParams.Activity; /// Current activity
TBF.UiBridge.TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 10, 0, 140, 0, 0, 0 });
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[i], Progress.JustStarted));
if (threadID == 0)
{
/// Check whether previous activity was 'Set test mode A0' or 'A4'
if (i > 0 && multiTestParams[i - 1].Activity.ToLower().Contains(SetTestModeStr.ToLower()) && !multiTestParams[i - 1].Activity.Contains("80"))
{
/// Start processing of opto-datastreams from all iPERL-s
int count = 0;
for (int wmNr0 = 0; wmNr0 < genesisHeads.Count; wmNr0++)
{
WaterMeter wm = (ProcessData.BatchRslts.Batch.WaterMeters != null && ProcessData.BatchRslts.Batch.WaterMeters.Count > wmNr0)
? ProcessData.BatchRslts.Batch.WaterMeters[wmNr0] : null;
GenesisSmartReader ihead = genesisHeads[wmNr0];
if (ihead != null && wm != null && !wm.Disabled)
{
lock (ihead)
{
ihead.StartDataStreamProcessing();
count++;
}
}
}
log.WarnFormat("End of activity '{0}', StartDataStreamProcessing() of {1} heads was called.", multiTestParams[i - 1].Activity, count);
}
/// A new activity starts - information into RFID data log
rfidDataLogger.InfoFormat("");
rfidDataLogger.WarnFormat("Activity = {0}", currentActivity);
rfidDataLogger.InfoFormat("");
}
//HOLD ON - if activity is like HoldSlotStr, ignore loop and do activity like HoldSlotStr
bool isHoldActivity = currentActivity.ToLower().Equals(HoldSlotStr.ToLower());
if (isHoldActivity)
{
log.Debug($"Activity '{currentActivity}' is HoldSlotStr, skipping loop and performing HoldOn operation. Thread: {threadID}");
CommErr error;
string resultStr = string.Empty;
error = HoldOn(threadID, ref resultStr); // wait for the hold on to complete - one time for each thread
ProcessWaterMetersDialogConfirmation(threadID, resultStr,error);
}
for (int group = 1; group <= lastGroup; group++)
{
/// Synchronize with QuidoRS and other threads
while (((group != currentGroup) || (activityStep != currentActivityStep)) && !stopWorkerThreads)
{
Thread.Sleep(50);
}
if (stopWorkerThreads) break;
if (!isHoldActivity)
{
#if TURA_SPECIAL
int threadIx = threadID; /// Just one thread for TURA_SPECIAL
#else
foreach (int threadIx in GenesisWorkerGroupCompletion.BoardIndexes(threadID, workerThreads.Count, muxBrdOrGroup14Nrs.Count))
#endif
{
bool wmFound = false;
for (int wmNr0 = 0; wmNr0 < genesisHeads.Count; wmNr0++)
{
GenesisSmartReader ihead = genesisHeads[wmNr0];
if ((ihead.Group == group) && (threadIx < muxBrdOrGroup14Nrs.Count) && (ihead.MuxBoardNrOrGroup14 == muxBrdOrGroup14Nrs[threadIx]))
{
wmFound = true;
WaterMeter wm = null;
if (ProcessData.BatchRslts.Batch.WaterMeters != null)
{
foreach (var w in ProcessData.BatchRslts.Batch.WaterMeters)
{
if (w.WMPosition == wmNr0 + 1)
{
wm = w;
break;
}
}
}
CommErr error;
string resultStr = string.Empty;
///
/// RFID communication activity call
///
if ((ihead == null) || ihead.Disabled || !ckbState[wmNr0]) error = CommErr.HeadDisabledByUser;
#if IPERL
else if (currentActivity.ToLower().Equals(SlotInitializeStr.ToLower())) error = SlotInitialize(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotUpdateStr.ToLower())) error = SlotUpdate(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotConnectStr.ToLower())) error = SlotConnect(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotPCBSlotStr.ToLower())) error = SlotPCBSlot(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotSetPasswordStr.ToLower())) error = SlotSetPassword(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotLoginStr.ToLower())) error = SlotLogin(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotGroupedLoginStr.ToLower())) error = SlotGroupedLogin(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotSetTestModeStr.ToLower())) error = SlotSetTestMode(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotSetActiveModeStr.ToLower()))error = SlotSetActiveMode(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SlotDisconnectStr.ToLower())) error = SlotDisconnect(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(PrepareSlotQ3CalibrationStr.ToLower())) error = PrepareSlotQ3Calibration(threadID, ihead,wm, currentTest, tests , ref resultStr);
else if (currentActivity.ToLower().Equals(WriteSlotQ3CalibrationStr.ToLower())) error = WriteSlotQ3Calibration(threadID, ihead, wm, currentTest, tests, ref resultStr);
else if (currentActivity.ToLower().Equals(CheckMeterPrepareStr.ToLower())) error = CheckMeterPrepare(threadID, ihead, ref resultStr);
//TODO MAREK dorobit dalsie moznosti podla vzoru
else if (currentActivity.ToLower().Contains(ReadSerialNrStr.ToLower())) error = ReadSerialNr(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Contains(SetTestModeStr.ToLower())) error = SetTestMode(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SetActiveModeStr.ToLower())) error = SetActiveMode(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Equals(SetIdleModeStr.ToLower())) error = SetIdleMode(threadID, ihead, ref resultStr);
else if (currentActivity.ToLower().Contains(ReadConfigurationStr.ToLower())) error = ReadConfiguration(ihead, wm, ref resultStr);
///
/// RFID communication functions below require a reference to water meter entity (wm != null)
///
else if (wm == null) error = CommErr.CommFailed;
else if (currentActivity.ToLower().Contains(SimulateCmd.ToLower())) error = Simulate(ihead, wm, ref resultStr);
#endif
else
{
error = CommErr.None;
ConditionID id = ConditionID.Count;
#if IPERL
for (id = ConditionID.A; id < ConditionID.Count; id++)
{
if (currentActivity.ToLower() == string.Format(SequenceConditionOp.ConditionNameFmt, id).ToLower())
{
error = SetIperlCommMilestoneReached(testMethod, id, ref resultStr);
break;
}
}
#endif
if (id == ConditionID.Count)
{
resultStr = "Invalid activity"; /// No activity or milestone
}
}
///
/// Process the result of RFID communication activity
///
if (error == CommErr.HeadDisabledByUser || !ckbState[wmNr0])
{
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, Strings.Head_was_disabled_by_the_user, CommErr.HeadDisabledByUser));
}
else if (error == CommErr.None)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, resultStr, CommErr.None));
}
else if ((error == CommErr.OutOfRange) || (error == CommErr.Q2OutOfRange))
{
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, resultStr, CommErr.CommFailed));
}
else if ((error == CommErr.FailedInit) ||
(error == CommErr.FailedConnect)||
(error == CommErr.FailedReadSerialNr)||
(error == CommErr.FailedSetPassword)||
(error == CommErr.FailedLogin)||
(error == CommErr.FailedSetTestMode)||
(error == CommErr.FailedSetActiveMode)||
(error == CommErr.FailedWriteRegister)||
(error == CommErr.FailedWriteCalibrationFactor) ||
(error == CommErr.FailedPrepare)
)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, resultStr, error));
}
else if (ihead.CommFailed || (error == CommErr.CommFailed))
{
ihead.CommFailed = true;
if (wm != null && (wm.ResultCode & (int)Results.Entities.ResultCode.RfidErrorCodeMask) == 0)
{
wm.ResultCode |= (((int)error << 16) | ((int)tests[i].ItemNr << 20));
}
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, Strings.Radio_Communication_failed, error));
}
else
{
ihead.CommFailed = true;
if (wm != null && (wm.ResultCode & (int)Results.Entities.ResultCode.RfidErrorCodeMask) == 0)
{
wm.ResultCode |= (((int)error << 16) | ((int)tests[i].ItemNr << 20));
}
string failureCauseLocal = string.Format(Strings.failed_0_1_exclamation, currentActivity, error);
rfidDataLogger.ErrorFormat("Group={0}, Board={1}, {2}", currentGroup, ihead.MuxBoardNrOrGroup14, failureCauseLocal);
OnCommCompleted(null, new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, failureCauseLocal, error));
}
break;
}
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[i], Progress.FlowSetting));
}
if (!wmFound)
{
OnCommCompleted(null, new CommCompletedEventArgs(threadID, -1, null, null, string.Empty, CommErr.None)); /// Send negative wmNr
}
Thread.Sleep( 2000);
if (stopWorkerThreads) break;
}
}
if (stopWorkerThreads) break;
log.DebugFormat("Genesis worker group completed: Activity={0}, Group2={1}, Worker={2}", activityStep, group, threadID);
OnCommCompleted(null, new CommCompletedEventArgs(threadID, -1, null, null, string.Empty, CommErr.None)
{ WorkerGroupCompleted = true, ActivityStep = activityStep, Group = group });
} /// for (int group
TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[i], Progress.Completed));
activityStep++;
if (stopWorkerThreads) break;
}
}
private CommErr CheckMeterPrepare(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedWriteRegister;
var gciFullLoginResult = iHead.OptoHeadTest.CheckMeterPrepare();
if (!string.IsNullOrEmpty(resultStr) && resultStr.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.Debug("CheckMeterPrepare successful");
resultStr = string.Format($"Check Meter Prepare: OK");
// note Q3 calibration is done
error = CommErr.None;
}
else
{
resultStr = "Check Meter Prepare: Failed";
}
return error;
}
/// <summary>
/// Set the state messages in WaterMeters Dialog Confirmation
/// Use after HoldOn()
/// </summary>
/// <param name="threadID"></param>
/// <param name="resultStr"></param>
private static void ProcessWaterMetersDialogConfirmation(int threadID, string resultStr, CommErr commErr)
{
bool wmFound = false;
for (int wmNr0 = 0; wmNr0 < genesisHeads.Count; wmNr0++)
{
GenesisSmartReader ihead = genesisHeads[wmNr0];
wmFound = true;
WaterMeter wm = null;
if (ProcessData.BatchRslts.Batch.WaterMeters != null)
{
foreach (var w in ProcessData.BatchRslts.Batch.WaterMeters)
{
if (w.WMPosition == wmNr0 + 1)
{
wm = w;
break;
}
}
}
OnCommCompleted(null,
new CommCompletedEventArgs(threadID, wmNr0, ihead, wm, resultStr, commErr));
}
}
private CommErr HoldOn(int threadId, ref string resultStr)
{
log.InfoFormat("HoldOn() threadId={0}", threadId);
CommErr error = CommErr.CommFailed;
// only first thread enters here
if (Interlocked.CompareExchange(ref _messageBoxActive, 1, 0) == 0)
{
try
{
// block other threads
_messageBoxDone.Reset();
if (this.InvokeRequired)
{
this.Invoke(new Action(() => { MessageBox.Show( this, "Confirm when you are ready to continue.", "Communication HOLD ON", MessageBoxButtons.OK, MessageBoxIcon.Information ); }));
}
else
{
MessageBox.Show( this, "Confirm when you are ready to continue.", "Communication HOLD ON", MessageBoxButtons.OK, MessageBoxIcon.Information );
}
}
finally
{
// release all waiting threads after OK
Interlocked.Exchange(ref _messageBoxActive, 0);
_messageBoxDone.Set();
}
}
else
{
// other threads wait here until OK is pressed
_messageBoxDone.Wait();
}
error = CommErr.None;
return error;
}
private CommErr PrepareSlotQ3Calibration(int threadId, GenesisSmartReader iHead, WaterMeter wm,
Test currentTest, IList<Test> tests, ref string resultStr)
{
CommErr error = CommErr.FailedPrepare;
//TODO BUMI get Next test method
log.InfoFormat("PrepareSlotQ3Calibration() threadId={0}", threadId);
try
{
//there is only currecnt test method
//find all tests in Procedure and set the test method
log.Debug($"StateMachne Procedure:{StateMachine.Procedure?.Name}");
log.Debug($"StateMachne TestInstances:{StateMachine.TestInstances?.Length}");
IList<Test> procedureTests = StateMachine.Procedure?.Tests;
Test NextTest = null;
bool bNextChatch = false;
foreach (Test test in procedureTests)
{
if (test.Equals(currentTest))
{
bNextChatch = true;
continue;
}
if (bNextChatch)
{
NextTest = test;
break;
}
}
var gciFullLoginResult = iHead.OptoHeadTest.PrepareQ3Calibration(cfg, NextTest, wm);
log.Debug($"PrepareSlotQ3Calibration(threadId: {threadId}, iHead: {iHead?.Name}) result:{gciFullLoginResult}");
if (!string.IsNullOrEmpty(gciFullLoginResult) &&
gciFullLoginResult.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.DebugFormat("PrepareQ3Calibration successfull threadId={0} head={1}", threadId, iHead?.Name);
resultStr = string.Format($"Write Q3 Calibration: OK");
// note Q3 calibration is done
error = CommErr.None;
}
else
{
log.DebugFormat("PrepareQ3Calibration failed threadId={0} head={1}", threadId, iHead?.Name);
resultStr = "Write Q3 Calibration: Failed";
}
return error;
}catch (Exception ex)
{
log.ErrorFormat("PrepareSlotQ3Calibration() threadId={0}, iHead: {1}, Error: {2}", threadId,iHead, ex.Message);
return CommErr.FailedPrepare;
}
}
private CommErr WriteSlotQ3Calibration(int threadId, GenesisSmartReader iHead, WaterMeter wm,
Test currentTest, IList<Test> tests, ref string resultStr)
{
CommErr error = CommErr.FailedWriteCalibrationFactor;
log.DebugFormat("WriteSlotQ3Calibration() threadId={0}, iHead: {1}, wm: {2}, currentTest: {3}, tests: {4}", threadId, iHead?.Name, wm?.Id, currentTest?.Name, tests?.Count);
//TODO BUMI get Before test method
try
{
//there is only currecnt test method
//find all tests in Procedure and set the test method
log.Debug($"StateMachne Procedure:{StateMachine.Procedure?.Name}");
log.Debug($"StateMachne TestInstances:{StateMachine.TestInstances?.Length}");
IList<Test> procedureTests = StateMachine.Procedure?.Tests;
Test BeforeTest = null;
foreach (Test test in procedureTests)
{
if (test.Equals(currentTest))
{
log.DebugFormat("WriteSlotQ3Calibration() threadId={0}, currentTest: {1}, BeforeTest: {2}", threadId, currentTest?.Name, BeforeTest?.Name);
break;
}
BeforeTest = test;
}
if (BeforeTest == null)
{
log.DebugFormat($"No Before test method found, we use the current test method threadId={0}, currentTest: {1}", threadId, currentTest?.Name);
BeforeTest = currentTest;
}
var gciFullLoginResult = iHead.OptoHeadTest.WriteQ3Calibration(cfg, BeforeTest, wm);
if (!string.IsNullOrEmpty(gciFullLoginResult) &&
gciFullLoginResult.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.Debug("SlotLogin successful");
resultStr = string.Format($"Write Q3 Calibration: OK");
// note Q3 calibration is done
error = CommErr.None;
}
else
{
resultStr = "Write Q3 Calibration: Failed";
}
return error;
}
catch (Exception ex)
{
log.ErrorFormat("WriteSlotQ3Calibration() threadId={0}, Error: {1}", threadId, ex.Message);
return CommErr.FailedWriteCalibrationFactor;
}
}
private CommErr SlotGroupedLogin(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedLogin;
var gciFullLoginResult = iHead.OptoHeadTest.GroupedLoginSlot();
if (gciFullLoginResult.Success)
{
log.Debug($"SlotLogin Head:{iHead.Name} successful, PCB: {gciFullLoginResult?.PcbResult?.Result?.PcbId}");
resultStr = string.Format($"Login OK - Serial No: {gciFullLoginResult?.PcbResult?.Result?.PcbId}");
log.Debug($"Setting PCB: {gciFullLoginResult?.PcbResult?.Result?.PcbId} for Head: {iHead.Name}");
iHead.SerialNr = gciFullLoginResult?.PcbResult?.Result?.PcbId;
if (iHead.ConfigStruct != null)
{
iHead.ConfigStruct.PCBNumberString = gciFullLoginResult?.PcbResult?.Result?.PcbId;
}
error = CommErr.None;
}
else
{
resultStr = "Failed Combined Login";
}
return error;
}
private CommErr SlotDisconnect(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedSetActiveMode;
bool result = iHead.OptoHeadTest.TurnOffRadio();
if (result)
{
log.Debug("SlotDisconnect successful");
resultStr = string.Format($"Slot Disconnected: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Disconnect Slot";
}
return error;
}
private CommErr SlotSetActiveMode(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedSetActiveMode;
resultStr = iHead.OptoHeadTest.SetActiveModeSlot();
if (!string.IsNullOrEmpty(resultStr) && resultStr.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk) )
{
log.Debug("SlotSetActiveMode successful");
resultStr = string.Format($"Serial No: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Read Serial No";
}
return error;
}
private CommErr SlotSetTestMode(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedSetTestMode;
resultStr = iHead.OptoHeadTest.SetTestModeSlot();
if (!string.IsNullOrEmpty(resultStr) && resultStr.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.Debug("SlotSetTestMode successful");
resultStr = string.Format($"SlotSetTestMode: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Set Test Mode";
}
return error;
}
private CommErr SlotLogin(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedLogin;
resultStr = iHead.OptoHeadTest.LoginSlot();
if (!string.IsNullOrEmpty(resultStr) && resultStr.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.Debug("SlotLogin successful");
resultStr = string.Format($"SlotLogin: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed SlotLogin";
}
return error;
}
private CommErr SlotSetPassword(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedSetPassword;
resultStr = iHead.OptoHeadTest.SetPasswordSlot();
if (!string.IsNullOrEmpty(resultStr) && resultStr.Equals(TBF.Rig.RegisterReaders.GenesisRegReader.communication.OptoHeadTest.ResultOk))
{
log.Debug("SlotSetPassword successful");
resultStr = string.Format($"SlotSetPassword: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Set Password";
}
return error;
}
private CommErr SlotPCBSlot(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedReadSerialNr;
PcbReadResult pcbReadSlot = iHead.OptoHeadTest.PCB_ReadSlot();
if (pcbReadSlot.Success)
{
var pcbId = pcbReadSlot?.PcbId;
log.Debug($"SlotPCBSlot Head:{iHead.Name} successful, PCB:{pcbId}");
resultStr = string.Format($"SlotPCBSlot: {pcbId}");
if (!string.IsNullOrWhiteSpace(pcbId))
{
log.Debug($"Setting PCB: {pcbId} for Head: {iHead.Name}");
iHead.SerialNr = pcbId;
if (iHead.ConfigStruct != null) iHead.ConfigStruct.PCBNumberString = pcbId;
}
error = CommErr.None;
}
else
{
resultStr = "Failed SlotPCBSlot";
}
return error;
}
private CommErr SlotConnect(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
CommErr error = CommErr.FailedConnect;
resultStr = iHead.OptoHeadTest.ConnectSlot();
if (!string.IsNullOrEmpty(resultStr))
{
log.Debug("SlotConnect successful");
resultStr = string.Format($"SlotConnect: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Connect Slot";
}
return error;
}
private CommErr SlotUpdate(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
resultStr = iHead.OptoHeadTest.UpdateSlot();
return CommErr.None;
}
private CommErr SlotInitialize(int threadId, GenesisSmartReader iHead, ref string resultStr)
{
log.Debug("SlotInitialize - thrededId = " + threadId);
CommErr error = CommErr.FailedInit;
resultStr = iHead.OptoHeadTest.InitialiseSlot();
if (!string.IsNullOrEmpty(resultStr))
{
log.Debug("SlotInitialize successful");
resultStr = string.Format($"SlotInitialize: {resultStr}");
error = CommErr.None;
}
else
{
resultStr = "Failed Init Slot";
}
return error;
}
private CommErr ReadSerialNr(int threadId, GenesisSmartReader ihead, ref string resultStr)
{
log.Debug("ReadSerialNr threadId=" + threadId + ", ihead=" + ihead.ToString());
if (ihead.ConfigStruct == null)
{
log.Debug("ConfigStruct is null - created new in ReadSerialNr()");
ihead.ConfigStruct = new TBF.Rig.RegisterReaders.GenesisRegReader.implementations.ConfigStruct();
}
if (ihead.CommFailed || ihead.ConfigStruct == null) return CommErr.CommFailed;
//I will do communication to meter now
CommErr error = CommErr.Read;
var result = ihead.OptoHeadTest.ReadRequest_PCB();
if (!string.IsNullOrEmpty(result))
{
log.Debug("ReadSerialNr successful");
resultStr = string.Format($"Serial No: {result}");
error = CommErr.None;
}
else
{
resultStr = "Failed Read Serial No";
}
return error;
}
private CommErr SetIdleMode(int threadId, GenesisSmartReader ihead, ref string resultStr)
{
log.Debug("SetActiveMode threadId=" + threadId);
CommErr error = CommErr.CmdActive;
/// Switch to active mode
if (ihead.OptoHeadTest.SetIdleMode())
{
error = CommErr.None;
}
if (error == CommErr.None)
{
if (ihead.ConfigStruct == null)
resultStr = "OK (Config not available)";
else
resultStr = ihead.ConfigStruct.GetStatusModeString();
}
return error;
}
#region Communication functions
#if IPERL
/// <summary>
/// Read a complete configuration structure of the watermeter
/// </summary>
/// <param name="ihead">iPERL head object</param>
/// <param name="wm">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr ReadConfiguration(GenesisSmartReader ihead, WaterMeter wm, ref string resultStr)
{
// TODO BUMI in clasic case we need to read most of data - see ConfigStruct
///
/// The activity is "Read configuration" (this enables the watermeter, resets error flag)
/// or "Read configuration if enabled" (this keeps the error flag).
///
if (!multiTestParams[currentActivityStep].Activity.ToLower().Contains(" if enabled"))
{
ihead.CommFailed = false;
}
if (ihead.CommFailed) return CommErr.CommFailed;
//zeroing
ihead.ConfigStruct = null; /// Clear previous ConfigStruct, avoid reuse of (not anymore valid) PCB Number
CommErr error = CommErr.Read;
int readRetVal = 0;
/// Read configuration
if (ihead.OptoHeadTest.ReadConfiguration(DiagnosticLedState.State4))
{
error = CommErr.None;
//read, set and create ConfigStruct is set directly in method ReadConfiguration
//ihead.ConfigStruct = new ConfigStruct(); //.FromByteArray(config);
if (ihead.ConfigStruct != null)
{
resultStr = ihead.ConfigStruct.ToString(1);
}
else
{
resultStr = "Data not available";
}
}
else
{
resultStr = "Failed to read configuration";
}
//return error + Math.Max(0, Math.Min(readRetVal, 4));
return error;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="threadId">Thread ID passed to RFID communication functions</param>
/// <param name="ihead">iPERL head object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr SetTestMode(int threadId, GenesisSmartReader ihead, ref string resultStr)
{
log.Debug("SetTestMode threadId=" + threadId + ", ihead=" + ihead.ToString());
if (ihead.ConfigStruct == null)
{
log.Debug("ConfigStruct is null - created new in SetTestMode()");
ihead.ConfigStruct = new TBF.Rig.RegisterReaders.GenesisRegReader.implementations.ConfigStruct();
}
if (ihead.CommFailed || ihead.ConfigStruct == null) return CommErr.CommFailed;
//I will do communication to meter now
DiagnosticLedState testModeConfig = DiagnosticLedState.State4; /// Default value
///
if (ihead.OptoHeadTest.SetTestMode())
{
log.Debug($"Meter Head:{ihead.Name}, test mode activated now");
}
if (ihead.ConfigStruct.MeterState == ProtocolStatuses.Active/*Test*/ && ihead.ConfigStruct.TestModeConfig == testModeConfig)
{
/// Already in the correct test mode
resultStr = "Already " + ihead.ConfigStruct.ToString(1);
log.Debug($"Meter Head:{ihead.Name}, status: {resultStr}");
return CommErr.None;
}
/// Communication necessary
CommErr error = CommErr.None;
/// Now the meter should be in the Test mode ... verify
if (error == CommErr.None)
{
/// Verify the configuration
error = CommErr.Verify;
if ((ihead.ConfigStruct.MeterState == ProtocolStatuses.Active) &&
(ihead.ConfigStruct.TestModeConfig == testModeConfig))
{
error = CommErr.None;
resultStr = ihead.ConfigStruct.GetActiveModeString();
}
}
return error;
}
/// <summary>
/// Set the watermeter to the active mode.
/// Read a part of configuration afterwards to verify the mode was set correctly.
/// </summary>
/// <param name="ihead">iPERL head object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr SetActiveMode(int threadId, GenesisSmartReader ihead, ref string resultStr)
{
log.Debug("SetActiveMode threadId=" + threadId);
CommErr error = CommErr.CmdActive;
/// Switch to active mode
if (ihead.OptoHeadTest.SetActiveMode())
{
error = CommErr.None;
}
if (error == CommErr.None)
{
if (ihead.ConfigStruct == null)
resultStr = "OK (Config not available)";
else
resultStr = ihead.ConfigStruct.GetActiveModeString();
}
return error;
}
/// <summary>
/// Reset both Q2 correction factors in the memory to 0.
/// Read them back to verify factors were written correctly.
/// </summary>
/// <param name="ihead">Water meter object</param>
/// <param name="resultStr">String passed to caller</param>
/// <returns>true on success</returns>
static CommErr Simulate(GenesisSmartReader ihead, WaterMeter wm, ref string resultStr)
{
string[] arguments = multiTestParams[currentActivityStep].Activity.Split(new char[] { ' ' });
if (arguments.Length < 2 || arguments[1].ToLower() != "iperls") return CommErr.None;
if (ihead.CommFailed) return CommErr.CommFailed;
string[] pcbNrs = new string[] { "831232435539", "831232435562",
"831232435587", "831232432141",
"831232432497", "831232763641" };
if (wm.WMPosition > 0 && wm.WMPosition <= pcbNrs.Length)
{
ihead.SerialNr = wm.SerialNr = pcbNrs[wm.WMPosition - 1];
}
resultStr = string.Format("PCB Nr. = {0}", wm.SerialNr ?? "<null>");
return CommErr.None;
}
static CommErr SetIperlCommMilestoneReached(TestMethod testMethod, ConditionID id, ref string resultStr)
{
if (id < ConditionID.A || id >= ConditionID.Count)
{
resultStr = Strings.Error;
return CommErr.WrongArguments;
}
testMethod.IperlCommMilestone[(int)id] = true;
resultStr = string.Format(SequenceConditionOp.ConditionNameFmt, id);
return CommErr.None;
}
#endif
#endregion
/// <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)
{
try
{
///
/// Update the text message
///
if (data.WMNr0 >= 0) messages[data.WMNr0].Text = data.CommMessage;
///
/// Update head active/inactive switch
///
if (data.WMNr0 >= 0 && data.CommErr == CommErr.HeadDisabledByUser)
{
/// iPerl head was disabled by the user
ckbState[data.WMNr0] = false;
checkBoxes[data.WMNr0].Checked = false;
checkBoxes[data.WMNr0].Enabled = false;
if (data.Ihead != null) data.Ihead.Disabled = true;
if (data.Wm != null) data.Wm.Disabled = true;
}
else if (data.WMNr0 >= 0 && data.CommErr == CommErr.None)
{
/// One RFID communication successful => iPerl cannot be disabled by the user anymore
ckbState[data.WMNr0] = true;
checkBoxes[data.WMNr0].Checked = true;
checkBoxes[data.WMNr0].Enabled = false;
}
// else if (data.WMNr0 >= 0 && data.CommErr != CommErr.None)
// {
// //disable if error
// ckbState[data.WMNr0] = false;
// checkBoxes[data.WMNr0].Checked = false;
// checkBoxes[data.WMNr0].Enabled = false;
// if (data.Ihead != null) data.Ihead.Disabled = true;
// if (data.Wm != null) data.Wm.Disabled = true;
// //color
// if (counters.Length > data.WMNr0) counters[data.WMNr0].BackColor = OptoNokColor;
// }
///
/// Update opto-communication indication
///
for (int i = 0; i < genesisHeads.Count; i++)
{
if (genesisHeads[i] == null || genesisHeads[i].Disabled)
{
counters[i].BackColor = DisabledColor;
}
else
{
counters[i].BackColor = OptoAndDirOKColor;
/*switch (genesisHeads[i].CheckFlowDirection())
{
case OptoHeadState.OptoAndDirOK:
counters[i].BackColor = OptoAndDirOKColor;
break;
case OptoHeadState.DirNok:
counters[i].BackColor = DirNokColor;
break;
default:
case OptoHeadState.OptoNok:
counters[i].BackColor = OptoNokColor;
break;
}*/
}
}
// Per-meter results update the UI only. Advance after every worker
// has finished all of its Group 1 assignments for this Group 2.
if (!data.WorkerGroupCompleted || !groupCompletion.Complete(data.ActivityStep, data.Group, data.ThreadId)) return;
log.InfoFormat("Genesis group completed: Activity={0}, Group2={1}, Workers={2}", data.ActivityStep, data.Group, workerThreads.Count);
if (currentGroup < lastGroup)
{
/// Go to the next step / next group
currentGroup++;
groupCompletion.Begin(currentActivityStep, currentGroup);
}
else if (currentActivityStep + 1 < multiTestParams.Count)
{
currentGroup = 0;
currentActivityStep++;
activityLabel.Text = multiTestParams[currentActivityStep].Activity;
currentGroup++;
groupCompletion.Begin(currentActivityStep, currentGroup);
}
else
{
log.Debug("Waiting for all Genesis workers; results remain visible for 4 seconds afterwards.");
Thread[] finishingThreads = workerThreads.ToArray();
Task.Run(() =>
{
foreach (var thread in finishingThreads) thread.Join();
if (!CanUseUi()) return;
BeginInvoke(new Action(async () =>
{
if (!CanUseUi()) return;
// nechaj výsledky/chyby čitateľné 4 sekundy
await Task.Delay(4000);
if (!CanUseUi() || forcedClose) return;
NormalClose();
}));
});
}
}
catch (Exception e)
{
log.ErrorFormat("DoOnCommCompleted({0}) failed: {1}", data, e.Message);
log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace);
}
}
public static event EventHandler<AllCompletedEventArgs> AllCompletedHandler;
void DoOnAllCompleted(object sender, AllCompletedEventArgs data)
{
Text = data.CommMessage;
}
/// <summary>
/// Update test result representing RFID communication success/failure
/// </summary>
/// <param name="test"></param>
void UpdateRfidCommResult(IList<Config.Entities.Test> tests)
{
DateTime endTime = DateTime.Now;
int testTime = StateMachine.Time - startTimeSec;
if (!tests.Contains(StateMachine.TestInstances[0].Test))
{
tests.Insert(0, StateMachine.TestInstances[0].Test); /// Add RFID test as the 1st item
}
foreach (var test in tests)
{
Results.Entities.TestRslt tstRslt = ProcessData.BatchRslts.GetTestRslt(test.Name, test.Part);
if (tstRslt != null)
{
Results.Utils.GetCounterStates(tstRslt, Program.LocalSettings.Counters);
/// Auxiliary results ... not required
/// Main results
tstRslt.MethodClass = TbfComponents.FindComponent(test.Method).ClassName;
tstRslt.TestDone = true;
tstRslt.StartTime = tstRslt.Batch.StartTime;
tstRslt.EndTime = endTime;
tstRslt.FlowSetTime = 0;
tstRslt.MassOfEvapWater = 0;
tstRslt.TestTime += testTime; /// [s] total communication time of all tests
for (int i = 0; i < genesisHeads.Count; i++)
{
Results.Entities.MeterTestRslt meterRslt =
ProcessData.BatchRslts.GetMeterTestRslt(test.Name, waterMeterPositions0[i], CompoundMeterId.Single);
if (meterRslt != null && genesisHeads[i] != null)
{
meterRslt.WaterMeter.SerialNr = genesisHeads[i].SerialNr;
meterRslt.Passed = (!genesisHeads[i].CommFailed && !genesisHeads[i].Disabled);
meterRslt.TestDone = true;
}
}
}
}
UiBridge.Bridge.OnTestCompleted(this, new UiBridge.TestCompletedEventArgs(string.Empty, null));
}
#if IPERL
private MenuItem NewMenuItem(string text, string tag)
{
MenuItem menuItem = new MenuItem { Text = text, Tag = tag };
menuItem.Click += OnClick_Optical_Heads_Settings_Menu;
return menuItem;
}
private async void OnClick_Optical_Heads_Settings_Menu(object sender, EventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
activityLabel.Text = menuItem.Text;
List<Task> tasks = new List<Task>();
foreach (var iHead in ProcessData.SmartHeadsUni)
{
if (!checkBoxes[iHead.Position - 1].Checked)
{
if (iHead.Position - 1 < messages.Length) messages[iHead.Position - 1].Text = "";
continue;
}
messages[iHead.Position - 1].Text = $"COM{iHead.RfidComPortNr}";
Application.DoEvents(); // Refresh UI
tasks.Add(Task.Run(async () =>
{
if (iHead is GenesisSmartReader genesisHead)
{
string result = await ProcessTask(genesisHead, menuItem.Tag);
this.Invoke((Action)(() =>
{
messages[iHead.Position - 1].Text = result;
Application.DoEvents(); // Refresh UI
}));
}
}));
}
await Task.WhenAll(tasks);
}
private async Task<string> ProcessTask(GenesisSmartReader iHead, object tag)
{
string txt = "";
bool success = false;
switch (tag)
{
////////////////////////////////////////////////////////
case "Initialize":
txt = iHead.OptoHeadTest.InitialiseSlot();
break;
//now unused
case "Update":
txt = iHead.OptoHeadTest.UpdateSlot();
break;
case "Connect":
txt = iHead.OptoHeadTest.ConnectSlot();
break;
//~now unused
case "PCBSlot":
PcbReadResult pcbReadSlot = iHead.OptoHeadTest.PCB_ReadSlot();
txt = pcbReadSlot.Success ? pcbReadSlot.PcbId : "PCB read failed";
break;
//now unused
case "SetPassword":
txt = iHead.OptoHeadTest.SetPasswordSlot();
break;
case "Login":
txt = iHead.OptoHeadTest.LoginSlot();
break;
//~ now unused
case "Login (Combined)":
var result = iHead.OptoHeadTest.GroupedLoginSlot();
txt = result?.LoginResult?.Success ?? false ? ("Login successful; PCB: " + result?.PcbResult?.Result?.PcbId): "Login failed";
break;
case "SetTestMode":
txt = iHead.OptoHeadTest.SetTestModeSlot();
break;
case "SetActiveMode":
txt = iHead.OptoHeadTest.SetActiveModeSlot();
break;
}
return txt;
}
#endif /// IPERL
#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>
private 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 GenesisCommunicationForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!forcedClose && !formCompleted && !checkBoxesEditMode)
{
e.Cancel = true;
}
}
}
}