/// /// Copyright (c) 2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.IO; using System.Linq; using System.Windows.Forms; using log4net; using NHibernate; using Common; using Config.Entities; using SharedDatabase.Entities; using TBF.Resources; using TBF.Rig.Sequences; namespace TBF.Rig.TestMethods.S640Communication { public enum CommErr { None = 0, CommFailed, /// 1 HeadDisabledByUser, /// 2 } /// /// (Program.LocalSettings.OptoHeadsEnabled & (1L << ix))) == 0 . . opto head is disabled in configuration /// optoheads[ix] == null . . . . . . . . . . . . . . . . . . . . . opto head is not part of the selected sensors path /// optoHeads[ix].Disabled == true . . . . . . . . . . . . . . . . opto head was disabled by the user /// public partial class S640CommForm : Form, GenericDevices.IHasCompleted { private static readonly ILog log = LogManager.GetLogger(typeof(S640CommForm)); protected static readonly ILog sirtDataLogger = LogManager.GetLogger("SirtData"); public const int UIBoxesCount = 20; public static Color DisabledColor = Color.DarkGray; public static Color OptoOKColor = Color.Green; public static Color OptoNokColor = Color.Red; public const string StartFileName = "Start.pro"; public const string EndFileName = "Ende.pro"; public const string ErrorFileName = "Error.dat"; enum Step { /// Start ReadSNsFromTracing, WatchOptoHeads, SaveStartPro, EnterSNsAndAwaitResponseToStartPro, AwaitResponseToStartPro, /// End EnterSNs, ConfirmSNsAndRadioAddresses, SaveEndePro, AwaitResponseToEndePro, ConfirmError, Idle, } 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 /// Number of text boxes for serial numbers public int WaterMetersCount; int textBoxesCount; /// bool[] enabledInConfiguration; Label[] labels; CheckBoxImage[] checkBoxes; PictureBox[] pictures; TextBox[] eRegisterNumbers; TextBox[] radioAddresses; TextBox[] serialNumbers; TextBox[] assignedSNs; TextBox[] assignedRadioAddresses; int[] ckbIndex; /// Initialized by ShuffleTextBoxes() ... to be used in the future in case of test benches with two lines RegisterReaders.S640Stream.S640Stream[] optoHeads; /// /// Parameters and current state of activities /// DebugMode debugLevel; int optoDataTimeout; string fileExchangePath; int fileExchangeTimeout; SerialNumbers serialNumbersMode; SerialNumbers assignedNumbersMode; bool skipBadMeters; ProcParams pPars; IList waterMeters; /// IList activities; IList tests; /// int currentActivityIx; /// Step step; DateTime savedTimestamp; bool isAnySNMissing; bool areValuesDisplayed; bool areNewSNsAndRadioAddressesAssigned; /// /// Production tracing support /// IList refRecords; IList records; System.Windows.Forms.Timer timer; /// /// Used in Step.WatchOptoHeads, initially all zeros /// int[] commOkLoopsCount; /// /// Parameterless constructor (without watermeters, threads) /// public S640CommForm() { InitializeComponent(); labels = new Label[UIBoxesCount] { wmLabel1, wmLabel2, wmLabel3, wmLabel4, wmLabel5, wmLabel6, wmLabel7, wmLabel8, wmLabel9, wmLabel10, wmLabel11, wmLabel12, wmLabel13, wmLabel14, wmLabel15, wmLabel16, wmLabel17, wmLabel18, wmLabel19, wmLabel20 }; checkBoxes = new CheckBoxImage[UIBoxesCount] { checkBoxImage1, checkBoxImage2, checkBoxImage3, checkBoxImage4, checkBoxImage5, checkBoxImage6, checkBoxImage7, checkBoxImage8, checkBoxImage9, checkBoxImage10, checkBoxImage11, checkBoxImage12, checkBoxImage13, checkBoxImage14, checkBoxImage15, checkBoxImage16, checkBoxImage17, checkBoxImage18, checkBoxImage19, checkBoxImage20, }; pictures = new PictureBox[UIBoxesCount] { pictureBox1, pictureBox2, pictureBox3, pictureBox4, pictureBox5, pictureBox6, pictureBox7, pictureBox8, pictureBox9, pictureBox10, pictureBox11, pictureBox12, pictureBox13, pictureBox14, pictureBox15, pictureBox16, pictureBox17, pictureBox18, pictureBox19, pictureBox20, }; eRegisterNumbers = new TextBox[UIBoxesCount] { fromOptoTextBox1, fromOptoTextBox2, fromOptoTextBox3, fromOptoTextBox4, fromOptoTextBox5, fromOptoTextBox6, fromOptoTextBox7, fromOptoTextBox8, fromOptoTextBox9, fromOptoTextBox10, fromOptoTextBox11, fromOptoTextBox12, fromOptoTextBox13, fromOptoTextBox14, fromOptoTextBox15, fromOptoTextBox16, fromOptoTextBox17, fromOptoTextBox18, fromOptoTextBox19, fromOptoTextBox20, }; radioAddresses = new TextBox[UIBoxesCount] { radioAddressTB1, radioAddressTB2, radioAddressTB3, radioAddressTB4, radioAddressTB5, radioAddressTB6, radioAddressTB7, radioAddressTB8, radioAddressTB9, radioAddressTB10, radioAddressTB11, radioAddressTB12, radioAddressTB13, radioAddressTB14, radioAddressTB15, radioAddressTB16, radioAddressTB17, radioAddressTB18, radioAddressTB19, radioAddressTB20, }; serialNumbers = new TextBox[UIBoxesCount] { serialNrTB1, serialNrTB2, serialNrTB3, serialNrTB4, serialNrTB5, serialNrTB6, serialNrTB7, serialNrTB8, serialNrTB9, serialNrTB10, serialNrTB11, serialNrTB12, serialNrTB13, serialNrTB14, serialNrTB15, serialNrTB16, serialNrTB17, serialNrTB18, serialNrTB19, serialNrTB20, }; assignedSNs = new TextBox[UIBoxesCount] { assignedSnTB1, assignedSnTB2, assignedSnTB3, assignedSnTB4, assignedSnTB5, assignedSnTB6, assignedSnTB7, assignedSnTB8, assignedSnTB9, assignedSnTB10, assignedSnTB11, assignedSnTB12, assignedSnTB13, assignedSnTB14, assignedSnTB15, assignedSnTB16, assignedSnTB17, assignedSnTB18, assignedSnTB19, assignedSnTB20, }; assignedRadioAddresses = new TextBox[UIBoxesCount] { assignedRadAddrTB1, assignedRadAddrTB2, assignedRadAddrTB3, assignedRadAddrTB4, assignedRadAddrTB5, assignedRadAddrTB6, assignedRadAddrTB7, assignedRadAddrTB8, assignedRadAddrTB9, assignedRadAddrTB10, assignedRadAddrTB11, assignedRadAddrTB12, assignedRadAddrTB13, assignedRadAddrTB14, assignedRadAddrTB15, assignedRadAddrTB16, assignedRadAddrTB17, assignedRadAddrTB18, assignedRadAddrTB19, assignedRadAddrTB20, }; ckbIndex = new int[UIBoxesCount]; /// Initialized by ShuffleTextBoxes() ... to be used in the future in case of test benches with two lines refRecords = new List(); records = new List(); } /// /// Constructor for one S640Communication test /// /// Number of text boxes for serial numbers public S640CommForm(S640Activity activity, I640Cfg cfg, Generic.IProcedureParams procParams, Test test, IList waterMeters) : this(new List { activity }, cfg, procParams, new List { test }, waterMeters) { } /// /// Constructor for multiple S640Communication tests /// /// Number of text boxes for serial numbers public S640CommForm(IList activities, I640Cfg cfg, Generic.IProcedureParams procParams, IList tests, IList waterMeters) : this() { this.activities = activities; debugLevel = cfg.DebugLevel; optoDataTimeout = cfg.OptoDataTimeout; fileExchangePath = string.IsNullOrEmpty(cfg.FileExchangePath) ? string.Empty : cfg.FileExchangePath; fileExchangeTimeout = cfg.FileExchangeTimeout; serialNumbersMode = cfg.SerialNumbers; assignedNumbersMode = cfg.AssignedNumbers; skipBadMeters = cfg.SkipBadMeters; this.tests = tests; this.pPars = procParams as ProcParams; this.waterMeters = waterMeters; if (activities.Count != tests.Count) { throw new Exception("Something strange: activities.Count != tests.Count"); } if (ProcessData.RegisterReaders.Length != ProcessData.BatchRslts.Batch.WaterMeters.Count) { throw new Exception("Something strange: RegisterReaders.Length != WaterMeters.Count"); } if (activities.Count > 0) { ProcessData.RegisterReaders = StateMachine.GetMetersPath(tests[0]).RegisterReaders; } optoHeads = new RegisterReaders.S640Stream.S640Stream[ProcessData.RegisterReaders.Length]; /// for (int wmPos = 0; wmPos < ProcessData.RegisterReaders.Length; wmPos++) { optoHeads[wmPos] = ProcessData.RegisterReaders[wmPos] as RegisterReaders.S640Stream.S640Stream; } WaterMetersCount = ProcessData.RegisterReaders.Length; ShuffleTextBoxes(WaterMetersCount, ProcessData.LineSize); enabledInConfiguration = new bool[textBoxesCount]; for (int i = 0; i < textBoxesCount; i++) { enabledInConfiguration[i] = (optoHeads[i] != null) && ((Program.LocalSettings.OptoHeadsEnabled & (1L << i)) != 0L); } isAnySNMissing = false; areValuesDisplayed = false; areNewSNsAndRadioAddressesAssigned = false; formCompleted = false; StartForceCloseHandler(); } /// /// Make sure the layout of labels/text boxes on the screen /// corresponds to the layout of watermeters of the test bench. /// /// Number of watermeters /// Number of watermeters in one line void ShuffleTextBoxes(int wmsCount, int lineSize) { textBoxesCount = UIBoxesCount; /// if (wmsCount < textBoxesCount && lineSize > 0) { int nrLines = (wmsCount + lineSize - 1) / lineSize; int gap = (textBoxesCount - wmsCount) / nrLines; int dest = 0; for (int l = 0; l < nrLines; l++) { for (int i = 0; i < lineSize; i++) { labels[dest] = labels[l * lineSize + l * gap + i]; checkBoxes[dest] = checkBoxes[l * lineSize + l * gap + i]; pictures[dest] = pictures[l * lineSize + l * gap + i]; eRegisterNumbers[dest] = eRegisterNumbers[l * lineSize + l * gap + i]; radioAddresses[dest] = radioAddresses[l * lineSize + l * gap + i]; serialNumbers[dest] = serialNumbers[l * lineSize + l * gap + i]; assignedSNs[dest] = assignedSNs[l * lineSize + l * gap + i]; assignedRadioAddresses[dest] = assignedRadioAddresses[l * lineSize + l * gap + i]; ckbIndex[l * lineSize + l * gap + i] = dest; dest++; } } textBoxesCount = wmsCount; } for (int i = 0; i < textBoxesCount; i++) { labels[i].Visible = checkBoxes[i].Visible = pictures[i].Visible = eRegisterNumbers[i].Visible = radioAddresses[i].Visible = true; if (optoHeads[i] != null) labels[i].Text = (i + 1).ToString(); } /// /// Resize this form to fit enabled controls /// //int xMax = 0; //int yMax = 0; //for (int i = 0; i < textBoxesCount; i++) //{ // if (messages[i].Left + messages[i].Width > xMax) xMax = messages[i].Left + messages[i].Width; // if (messages[i].Top + messages[i].Height > yMax) yMax = messages[i].Top + messages[i].Height; //} /////Width = xMax + 30; //Height = yMax + 50; } private void S640CommForm_Load(object sender, EventArgs e) { Localize(); /// /// Set location and checkbox states to values stored in local settings /// TBF.LocalSettings ls = Program.LocalSettings; Left = (ls.S640CommFormLeft != 0) ? ls.S640CommFormLeft : 150; Top = (ls.S640CommFormTop != 0) ? ls.S640CommFormTop : 150; /// /// Set checkbox states accroding to optoHeads[i].Disabled states /// for (int i = 0; i < textBoxesCount; i++) { if (!enabledInConfiguration[i]) { /// Opto head is disabled in configuration checkBoxes[i].Checked = false; checkBoxes[i].Enabled = false; pictures[i].BackColor = DisabledColor; eRegisterNumbers[i].Visible = false; radioAddresses[i].Visible = false; serialNumbers[i].Visible = false; } else if ((i >= waterMeters.Count) || waterMeters[i] == null || waterMeters[i].Disabled) { /// Opto head was disabled by an operator checkBoxes[i].Checked = false; checkBoxes[i].Enabled = false; pictures[i].BackColor = DisabledColor; eRegisterNumbers[i].Text = "xxx"; radioAddresses[i].Text = "xxx"; } else { /// Opto head is enabled checkBoxes[i].Checked = true; checkBoxes[i].Enabled = true; eRegisterNumbers[i].Text = "---"; radioAddresses[i].Text = "---"; } /// Reset opto-data indication pictures[i].BackColor = OptoNokColor; eRegisterNumbers[i].Enabled = false; eRegisterNumbers[i].Enabled = false; serialNumbers[i].Visible = enabledInConfiguration[i] && (serialNumbersMode != SerialNumbers.None); serialNumbers[i].Enabled = (serialNumbersMode == SerialNumbers.EnterManually); if (activities.Contains(S640Activity.End)) { assignedSNs[i].Visible = enabledInConfiguration[i] && (serialNumbersMode != SerialNumbers.None); assignedSNs[i].Enabled = (serialNumbersMode == SerialNumbers.EnterManually); assignedRadioAddresses[i].Visible = enabledInConfiguration[i] && (serialNumbersMode != SerialNumbers.None); assignedRadioAddresses[i].Enabled = (serialNumbersMode == SerialNumbers.EnterManually); } } startTimeSec = StateMachine.Time; StartActivity(0); timer = new System.Windows.Forms.Timer(); timer.Interval = 300; // ms timer.Tick += new EventHandler(timer_Tick); timer.Start(); } void Localize() { /// Close/Continue button is localized in other code Text = Strings.Water_Meter_States; retryButton.Text = Strings.RetryBtnText; sampleLabel1.Text = Strings.Optical_head_is_placed_correctly; sampleLabel2.Text = Strings.Missing_opto_pulses; samplePictureBox1.BackColor = OptoOKColor; samplePictureBox2.BackColor = OptoNokColor; } void StartActivity(int acIx) { startTime = DateTime.Now; activityLabel.Text = activities[acIx].ToString(); currentActivityIx = acIx; if (activities[acIx] == S640Activity.Start) { step = serialNumbersMode == SerialNumbers.FromProductionTracing ? Step.ReadSNsFromTracing : Step.WatchOptoHeads; } else { step = serialNumbersMode == SerialNumbers.EnterManually ? Step.EnterSNs : Step.ConfirmSNsAndRadioAddresses; } closeButton.Visible = false; retryButton.Visible = false; responseTextBox.Text = string.Empty; if (step == Step.ReadSNsFromTracing || step == Step.WatchOptoHeads) { /// Start watching optical heads --> reset OK loop counters if (commOkLoopsCount == null || commOkLoopsCount.Length != textBoxesCount) { commOkLoopsCount = new int[textBoxesCount]; } for (int i = 0; i < textBoxesCount; i++) commOkLoopsCount[i] = 0; progressBar1.Visible = (optoDataTimeout != 0); progressBar1.Minimum = 0; progressBar1.Maximum = Math.Max(optoDataTimeout, 1); progressBar1.Value = 0; } TBF.UiBridge.TestProgressEventArgs.SetEstimatedTimes(new int[] { 0, 0, 10, 0, 140, 0, 0, 0 }); TBF.UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[acIx], Progress.JustStarted)); sirtDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data sirtDataLogger.WarnFormat("Activity = {0}", activities[acIx]); sirtDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data } /// /// Invoked every 0.5 sec. /// void timer_Tick(object sender, EventArgs args) { ///-------------------------------------------------------------------------- if (step == Step.ReadSNsFromTracing) { if (ProcessData.TracingDB != null && ProcessData.OrderInfo is OrderInfo) { ISession session = ProcessData.TracingDB.SessionFactory.OpenSession(); refRecords = ProcessData.TracingDB.ReadRefRecords(session, ProcessData.OrderInfo as OrderInfo); records = ProcessData.TracingDB.ReadRecords(session, ProcessData.OrderInfo as OrderInfo); session.Close(); } step = Step.WatchOptoHeads; } ///-------------------------------------------------------------------------- else if (step == Step.WatchOptoHeads) { activityLabel.Text = "Heads are sensing opto-data"; bool allOK = true; for (int i = 0; i < textBoxesCount; i++) { if (enabledInConfiguration[i]) { if (!checkBoxes[i].Checked) { /// Disabled by the user pictures[i].BackColor = DisabledColor; eRegisterNumbers[i].Text = "xxx"; radioAddresses[i].Text = "xxx"; serialNumbers[i].Text = string.Empty; } else { /// Opto head is enabled if (optoHeads[i].PcbNumber == 0) { /// Communication is NOK right now pictures[i].BackColor = OptoNokColor; eRegisterNumbers[i].Text = "---"; radioAddresses[i].Text = "---"; serialNumbers[i].Text = string.Empty; commOkLoopsCount[i] = 0; allOK = false; } else { /// Communication is OK right now string pcbNumber = optoHeads[i].PcbNumber.ToString(); eRegisterNumbers[i].Text = pcbNumber; radioAddresses[i].Text = optoHeads[i].RadioAddress.ToString(); Record rec; ReferenceRecord refRec; if ((rec = records.FirstOrDefault(x => x.Code == pcbNumber)) != null && (refRec = refRecords.FirstOrDefault(x => x.Id == rec.ReferenceRecord.Id)) != null) { serialNumbers[i].Text = refRec.Code; } else { serialNumbers[i].Text = string.Empty; } pictures[i].BackColor = OptoOKColor; /// increment commOkLoopsCount[i] and check its value, considered OK just after 5 repeats commOkLoopsCount[i] = commOkLoopsCount[i] + 1; if (commOkLoopsCount[i] < 5) allOK = false; } } } } isAnySNMissing = false; if (allOK) { log.WarnFormat("allOk"); /// Update water meter properties for (int i = 0; i < textBoxesCount; i++) { if (i < waterMeters.Count && waterMeters[i] != null && !waterMeters[i].Disabled) { if (enabledInConfiguration[i] && checkBoxes[i].Checked) { /// Save PCB Number of the water meter waterMeters[i].SerialNrAux = optoHeads[i].PcbNumber.ToString(); /// PCB number (640) waterMeters[i].OriRadioAddress = optoHeads[i].RadioAddress.ToString(); /// New radio address (640) waterMeters[i].RadioAddress = optoHeads[i].RadioAddress.ToString(); /// New radio address (640) if (string.IsNullOrEmpty(serialNumbers[i].Text)) isAnySNMissing = true; } else { /// Disable the water meter waterMeters[i].Disabled = true; } } checkBoxes[i].Enabled = false; } step = Step.SaveStartPro; } else if (optoDataTimeout != 0 && DateTime.Now - startTime > new TimeSpan(0, 0, optoDataTimeout)) { /// Opto-data timeout occured activityLabel.Text = String.Format("{0}: {1} {2}", Strings.Start, Strings.Optical_heads, Strings.Timeout); log.Error("Start: Optical heads timeout"); step = Step.ConfirmError; } else if (optoDataTimeout != 0) { /// Count down progressBar1.Value = (int)Math.Round((DateTime.Now - startTime).TotalSeconds); } } ///-------------------------------------------------------------------------- else if (step == Step.SaveStartPro) { int count = 0; for (int i = 0; i < textBoxesCount; i++) { if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null) count++; } log.DebugFormat("Saving '{0}' file: {1} water meters found", StartFileName, count); if (debugLevel == DebugMode.Normal) { SaveProFile(Path.Combine(fileExchangePath, StartFileName), S640Activity.Start, optoHeads); } SaveProFile(Path.Combine(Constants.SirtLogDir, string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, StartFileName)), S640Activity.Start, optoHeads); savedTimestamp = DateTime.Now; progressBar1.Visible = (fileExchangeTimeout != 0); progressBar1.Minimum = 0; progressBar1.Maximum = Math.Max(fileExchangeTimeout, 1); progressBar1.Value = 0; for (int i = 0; i < textBoxesCount; i++) { eRegisterNumbers[i].Enabled = false; } bool focused = false; if (serialNumbersMode == SerialNumbers.EnterManually || isAnySNMissing) { for (int i = 0; i < textBoxesCount; i++) { if (serialNumbers[i].Visible && string.IsNullOrEmpty(serialNumbers[i].Text)) { serialNumbers[i].Enabled = true; if (!focused) { serialNumbers[i].Focus(); focused = true; } } } closeButton.Visible = true; closeButton.Enabled = true; closeButton.Text = Strings.Continue; step = Step.EnterSNsAndAwaitResponseToStartPro; } else { /// Update water meter properties UpdateAndDisableSerialNumbers(); step = Step.AwaitResponseToStartPro; } } ///-------------------------------------------------------------------------- else if (step == Step.EnterSNsAndAwaitResponseToStartPro) { activityLabel.Text = "Enter or scan housing S/N-s"; /// Don't do anything, move to the next step in closeButton_Click(...) } ///-------------------------------------------------------------------------- else if (step == Step.AwaitResponseToStartPro) { activityLabel.Text = "SIRT communication in progress"; if (debugLevel == DebugMode.Simulate) { /// Simulation: After 'Next' button click a similar action as when Start.pro file disappears closeButton.Text = "Next"; closeButton.Visible = true; retryButton.Visible = false; } else if (!File.Exists(Path.Combine(fileExchangePath, StartFileName))) { /// Normal flow of actions ... Start.pro file disappeared in time /// Updatetest results UpdateFirstTestResult(tests); UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed)); step = Step.Idle; NormalClose(); } else if (File.Exists(Path.Combine(fileExchangePath, ErrorFileName))) { /// Error file detected string destination = Path.Combine(Constants.SirtLogDir, string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, ErrorFileName)); File.Move(Path.Combine(fileExchangePath, ErrorFileName), destination); ParseFileAndDisplayErrors(destination); File.Delete(Path.Combine(fileExchangePath, StartFileName)); activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.Start, Strings.Error); step = Step.ConfirmError; } else if (fileExchangeTimeout != 0 && DateTime.Now - savedTimestamp > new TimeSpan(0, 0, fileExchangeTimeout)) { /// Timeout activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.Start, Strings.Timeout); log.Error("Start: SIRT timeout"); step = Step.ConfirmError; } else if (fileExchangeTimeout != 0) { /// Nothing special, timeout is counting down progressBar1.Value = (int)Math.Round((DateTime.Now - savedTimestamp).TotalSeconds); } else { /// Nothing special, there is no timeout, Close adn Retry buttons are visible progressBar1.Visible = false; closeButton.Text = Strings.CloseBtnText; closeButton.Visible = true; retryButton.Visible = true; } } ///-------------------------------------------------------------------------- else if (step == Step.EnterSNs) { /// Don't do anything just display values, move to the next step in closeButton_Click(...) if (!areValuesDisplayed) { DisplayValues(); areValuesDisplayed = true; } } ///-------------------------------------------------------------------------- else if (step == Step.ConfirmSNsAndRadioAddresses) { activityLabel.Text = "Confirm new S/N-s and radio addresses"; if (!areValuesDisplayed) { DisplayValues(); areValuesDisplayed = true; } if (!areNewSNsAndRadioAddressesAssigned) { AssignNewSNsAndRadioAddresses(waterMeters, optoHeads); closeButton.Visible = true; closeButton.Text = Strings.Continue; } } ///-------------------------------------------------------------------------- else if (step == Step.SaveEndePro) { activityLabel.Text = "SIRT communication in progress"; log.DebugFormat("Saving '{0}' file", EndFileName); if (debugLevel == DebugMode.Normal) { SaveProFile(Path.Combine(fileExchangePath, EndFileName), S640Activity.End, optoHeads); } SaveProFile(Path.Combine(Constants.SirtLogDir, string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, EndFileName)), S640Activity.Start, optoHeads); savedTimestamp = DateTime.Now; progressBar1.Visible = (fileExchangeTimeout != 0); progressBar1.Minimum = 0; progressBar1.Maximum = Math.Max(fileExchangeTimeout, 1); progressBar1.Value = 0; if (ProcessData.OracleDB != null && ProcessData.OrderInfo is TBF.Rig.Output.DB.SensusOracle.OrderDetails) { int updatedCount = ProcessData.OracleDB .UpdateOrderDetails(ProcessData.OrderInfo as TBF.Rig.Output.DB.SensusOracle.OrderDetails); } step = Step.AwaitResponseToEndePro; } ///-------------------------------------------------------------------------- else if (step == Step.AwaitResponseToEndePro) { if (debugLevel == DebugMode.Simulate) { /// Simulation: After 'Next' button click a similar action as when Ende.pro file disappears closeButton.Text = "Next"; closeButton.Visible = true; retryButton.Visible = false; } else if (!File.Exists(Path.Combine(fileExchangePath, EndFileName))) { /// Normal flow of actions ... Ende.pro file disappeared in time /// Update test results UpdateFirstTestResult(tests); UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed)); step = Step.Idle; NormalClose(); } else if (File.Exists(Path.Combine(fileExchangePath, ErrorFileName))) { /// Error.dat file detected string destination = Path.Combine(Constants.SirtLogDir, string.Format("{0:yyMMdd-HHmmss}-b{1}-{2}", DateTime.Now, ProcessData.BatchRslts.Batch.BatchNr, ErrorFileName)); File.Move(Path.Combine(fileExchangePath, ErrorFileName), destination); ParseFileAndDisplayErrors(destination); File.Delete(Path.Combine(fileExchangePath, EndFileName)); activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.End, Strings.Error); step = Step.ConfirmError; } else if (fileExchangeTimeout != 0 && DateTime.Now - savedTimestamp > new TimeSpan(0, 0, fileExchangeTimeout)) { activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.End, Strings.Timeout); log.Error("End: SIRT timeout"); step = Step.ConfirmError; } else if (fileExchangeTimeout != 0) { progressBar1.Value = (int)Math.Round((DateTime.Now - savedTimestamp).TotalSeconds); } else { progressBar1.Visible = false; closeButton.Text = Strings.CloseBtnText; closeButton.Visible = true; retryButton.Visible = true; } } ///-------------------------------------------------------------------------- else if (step == Step.ConfirmError) { progressBar1.Visible = false; retryButton.Visible = true; closeButton.Visible = true; closeButton.Enabled = true; closeButton.Text = Strings.CloseBtnText; } ///-------------------------------------------------------------------------- else if (step == Step.Idle) { /// Just wait until this form is closed } else { /// Invalid step log.ErrorFormat("Unexpected step: activity = {0} step = {1}", activities[currentActivityIx], step); } } private void closeButton_Click(object sender, EventArgs e) { if (step == Step.EnterSNsAndAwaitResponseToStartPro) { UpdateAndDisableSerialNumbers(); step = Step.AwaitResponseToStartPro; closeButton.Visible = false; } else if (debugLevel == DebugMode.Simulate && step == Step.AwaitResponseToStartPro) { UpdateFirstTestResult(tests); UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed)); NormalClose(); } else if (step == Step.EnterSNs) { UpdateAndDisableSerialNumbers(); step = Step.ConfirmSNsAndRadioAddresses; closeButton.Visible = false; } else if (step == Step.ConfirmSNsAndRadioAddresses) { step = Step.SaveEndePro; closeButton.Visible = false; } else if (debugLevel == DebugMode.Simulate && step == Step.AwaitResponseToEndePro) { UpdateFirstTestResult(tests); UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Completed)); NormalClose(); } else { log.Error("User is closing this form, communication failed"); UpdateFirstTestResult(tests, true); UiBridge.Bridge.OnTestProgress(null, new TBF.UiBridge.TestProgressEventArgs(tests[currentActivityIx], Progress.Aborted)); NormalClose(); } } /// /// Updates SerialNr of all enabled water meters from respective visible TextBoxes. /// void UpdateAndDisableSerialNumbers() { /// Update water meter properties for (int i = 0; i < textBoxesCount; i++) { if (serialNumbers[i].Visible) { if (i < waterMeters.Count && waterMeters[i] != null && !waterMeters[i].Disabled && enabledInConfiguration[i] && checkBoxes[i].Checked) { /// Save brass water meter body serial number waterMeters[i].SerialNr = serialNumbers[i].Text; } serialNumbers[i].Enabled = false; } } } void DisplayValues() { for (int i = 0; i < textBoxesCount; i++) { if (i < waterMeters.Count && waterMeters[i] != null && !waterMeters[i].Disabled && enabledInConfiguration[i] && checkBoxes[i].Checked) { /// Save PCB Number of the water meter eRegisterNumbers[i].Text = waterMeters[i].SerialNrAux; /// PCB number (640) radioAddresses[i].Text = waterMeters[i].OriRadioAddress; /// New radio address (640) serialNumbers[i].Text = waterMeters[i].SerialNr; /// Serial unmber (housing number } } } bool AssignNewSNsAndRadioAddresses(IList waterMeters, RegisterReaders.S640Stream.S640Stream[] optoHeads) { var order = ProcessData.OrderInfo; var oraOrder = order as TBF.Rig.Output.DB.SensusOracle.OrderDetails; /// if (oraOrder != null && (ProcessData.OracleDB == null || !ProcessData.OracleDB.ReadOrderDetails(ref oraOrder))) { return false; } if (order.CurrentSN < order.SNFirst) { order.CurrentSN = order.SNFirst - 1; } for (int i = 0; i < optoHeads.Length; i++) { int currentSerialNr = (order.CurrentSN < order.SNFirst) ? order.SNFirst : order.CurrentSN + 1; int currentRadioAddress = (order.CurrentRA < order.RAFirst) ? order.RAFirst : order.CurrentRA + 1; Results.Entities.WaterMeter wm = ProcessData.BatchRslts.Batch.WaterMeters[i]; if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && wm != null && !wm.Disabled) { if (!wm.PassedFromTests()) { /// Red background eRegisterNumbers[i].BackColor = Color.Pink; wm.AssignedSerialNr = -1; wm.Prefix = order.SNPrefix; wm.Suffix = order.SNSuffix; wm.CompleteSerialNr = string.Empty; assignedSNs[i].Text = wm.CompleteSerialNr; assignedRadioAddresses[i].Text = wm.RadioAddress; } else if (order.CurrentPcsCount >= order.PiecesCount) { /// Disable the water meter to prevent sealing wm.Disabled = true; } else { /// Assign numbers wm.AssignedSerialNr = currentSerialNr; wm.Prefix = order.SNPrefix; wm.Suffix = order.SNSuffix; wm.CompleteSerialNr = string.Format("{0}{1}{2}", order.SNPrefix, currentSerialNr.ToString(string.Format("D{0}", order.SNDigitsCount)), order.SNSuffix); assignedSNs[i].Text = wm.CompleteSerialNr; wm.RadioAddress = string.Format("{0}{1}{2}", order.RAPrefix, currentRadioAddress.ToString("D9"), order.RASuffix); assignedRadioAddresses[i].Text = wm.RadioAddress; order.CurrentSN = currentSerialNr; order.CurrentRA = currentRadioAddress; order.CurrentPcsCount++; } } } areNewSNsAndRadioAddressesAssigned = true; return true; } void SaveProFile(string filename, S640Activity activity, RegisterReaders.S640Stream.S640Stream[] optoHeads) { /// Variant: 1.from OrderDetails, 2.from Procedure.WatermetersStr, 3.empty string variant = (ProcessData.OrderInfo != null && !string.IsNullOrEmpty(ProcessData.OrderInfo.VariantCode)) ? ProcessData.OrderInfo.VariantCode /// 1 : !string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WatermetersStr) ? ProcessData.BatchRslts.Batch.WatermetersStr /// 2 : string.Empty; /// 3 /// Module parameter string moduleParam = (pPars.ModuleParameter.ToLower().Contains("vt_auftrag_pd") && ProcessData.OrderInfo != null) ? ProcessData.OrderInfo.ModuleParam : pPars.ModuleParameter; /// Purchase order and water meters count int count = 0; string purchaseOrder = null; for (int i = 0; i < optoHeads.Length; i++) { if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && waterMeters[i] != null && !waterMeters[i].Disabled && (activity == S640Activity.Start || waterMeters[i].PassedFromTests())) { count++; if (purchaseOrder == null && !string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder)) { purchaseOrder = ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder; } } } if (ProcessData.OrderInfo != null) { purchaseOrder = ProcessData.OrderInfo.POName; } using (StreamWriter file = new StreamWriter(filename)) { file.WriteLine(""); file.WriteLine(""); file.WriteLine(string.Format(" {0}", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz"))); file.WriteLine(string.Format(" ", (activity == S640Activity.Start) ? "Start" : "End", count, ProcessData.BenchInfo.TestBenchId, ProcessData.BenchInfo.TestBenchName, "SensusKey")); file.WriteLine(string.Format(" ", variant, (purchaseOrder != null) ? purchaseOrder : string.Empty, moduleParam)); file.WriteLine(" "); for (int i = 0; i < optoHeads.Length; i++) { if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null && !ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled && (activity == S640Activity.Start || ProcessData.BatchRslts.Batch.WaterMeters[i].PassedFromTests())) { Results.Entities.WaterMeter wm = ProcessData.BatchRslts.Batch.WaterMeters[i]; if (activity == S640Activity.Start) { file.WriteLine(string.Format(" ", wm.RadioAddress, wm.SerialNrAux)); } else if (activity == S640Activity.End) { #if ORACLE_DB file.WriteLine(string.Format(" ", wm.OriRadioAddress, wm.AssignedSerialNr.ToString(), wm.AssignedSerialNr.ToString(), wm.RadioAddress, wm.SerialNrAux)); #endif } } } file.WriteLine(" "); file.WriteLine(string.Format(" ", B2S(pPars.MetroEnable), pPars.PulseRatePiston.ToString("F3", CultureInfo.InvariantCulture), pPars.PulseRateLed.ToString(CultureInfo.InvariantCulture), pPars.OffsetFactor.ToString(CultureInfo.InvariantCulture), pPars.FactoryCalibration, pPars.Units, pPars.MeterSize, pPars.OffsetTime)); file.WriteLine(string.Format(" ", B2S(pPars.NewReadEnable), pPars.NewRead)); file.WriteLine(string.Format(" ", B2S(pPars.TransIntervalEnable), pPars.TransInterval)); file.WriteLine(string.Format(" ", B2S(pPars.LatIntervalEnable), pPars.LatInterval)); file.WriteLine(string.Format(" ", B2S(pPars.ResetAlarmEnable))); file.WriteLine(string.Format(" ", B2S(pPars.MetrologyTestModeEnable), pPars.MetrologyTestModeHours)); file.WriteLine(string.Format(" ", B2S(pPars.OpticalTelegramEnable), pPars.OpticalTelegramMinutes)); file.WriteLine(string.Format(" ", B2S(pPars.ChangeRadioEnable))); file.WriteLine(string.Format(" ", B2S(pPars.ChangeMeterIDEnable))); file.WriteLine(string.Format(" ", B2S(pPars.SoftSealEnable))); file.WriteLine(string.Format(" ", B2S(pPars.GoToSleepEnable))); file.WriteLine(string.Format(" ", B2S(pPars.SaveDBEnable))); file.WriteLine(""); } } /// /// Boolean to lowercase string /// string B2S(bool b) { return b ? "true" : "false"; } void ParseFileAndDisplayErrors(string fileName) { log.ErrorFormat("ParseFileAndDisplayErrors(\"{0}\")", fileName); string message = File.ReadAllText(fileName); responseTextBox.Text = message; } /// /// Update test result representing RFID communication success/failure /// /// void UpdateFirstTestResult(IList tests, bool commFailed = false) { 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 < textBoxesCount; i++) { Results.Entities.MeterTestRslt meterRslt = ProcessData.BatchRslts.GetMeterTestRslt(test.Name, i, Common.CompoundMeterId.Single); if (meterRslt != null && (i < ProcessData.BatchRslts.Batch.WaterMeters.Count) && ProcessData.BatchRslts.Batch.WaterMeters[i] != null && !ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled) { if (enabledInConfiguration[i] && !commFailed) { meterRslt.TestDone = true; meterRslt.Passed = true; } else { meterRslt.TestDone = true; meterRslt.Passed = false; } } } } } } private void NormalClose() { if (Program.LocalSettings.S640CommFormLeft != Location.X || Program.LocalSettings.S640CommFormTop != Location.Y) { /// Update local settings Program.LocalSettings.S640CommFormLeft = Location.X; Program.LocalSettings.S640CommFormTop = Location.Y; 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(OnForceClose), sender, args); } else OnForceClose(sender, args); }; } void OnForceClose(object sender, EventArgs args) { forcedClose = true; DialogResult = DialogResult.Cancel; Close(); } #endregion private void S640CommForm_FormClosing(object sender, FormClosingEventArgs e) { if (!forcedClose && !formCompleted) { e.Cancel = true; } } private void retryButton_Click(object sender, EventArgs e) { if (step == Step.ConfirmError) { StartActivity(0); } } private void textBox1_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB1); } private void textBox2_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB2); } private void textBox3_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB3); } private void textBox4_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB4); } private void textBox5_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB5); } private void textBox6_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB6); } private void textBox7_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB7); } private void textBox8_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB8); } private void textBox9_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB9); } private void textBox10_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB10); } private void textBox11_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB11); } private void textBox12_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB12); } private void textBox13_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB13); } private void textBox14_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB14); } private void textBox15_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB15); } private void textBox16_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB16); } private void textBox17_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB17); } private void textBox18_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB18); } private void textBox19_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB19); } private void textBox20_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, serialNrTB20); } private void textBox21_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox21); } private void textBox22_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox22); } private void textBox23_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox23); } private void textBox24_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox24); } private void textBox25_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox25); } private void textBox26_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox26); } private void textBox27_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox27); } private void textBox28_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox28); } private void textBox29_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox29); } private void textBox30_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox30); } private void textBox31_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox31); } private void textBox32_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox32); } private void textBox33_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox33); } private void textBox34_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox34); } private void textBox35_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox35); } private void textBox36_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox36); } private void textBox37_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox37); } private void textBox38_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox38); } private void textBox39_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox39); } private void textBox40_KeyPress(object sndr, KeyPressEventArgs e) { ProcKeyPress(sndr, e, textBox40); } /// /// Process a key press within any enabled text boxe /// /// /// /// TextBox control which received the event private void ProcKeyPress(object sender, KeyPressEventArgs e, TextBox currentFocusOwner) { if (e.KeyChar == '\r') { /// Process key ..... Next text field if (textBoxesCount < 2) return; /// There is just one enabled textBox for (int i = 0; i < textBoxesCount; i++) { if (serialNumbers[i] == currentFocusOwner) { int nextIx = i; do { nextIx = (++nextIx) % textBoxesCount; } while (!serialNumbers[nextIx].Visible); /// Change focus to the next enabled text box serialNumbers[nextIx].Focus(); return; } } } } private void checkBoxImage1_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage1, fromOptoTextBox1, radioAddressTB1, serialNrTB1); } private void checkBoxImage2_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage2, fromOptoTextBox2, radioAddressTB2, serialNrTB2); } private void checkBoxImage3_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage3, fromOptoTextBox3, radioAddressTB3, serialNrTB3); } private void checkBoxImage4_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage4, fromOptoTextBox4, radioAddressTB4, serialNrTB4); } private void checkBoxImage5_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage5, fromOptoTextBox5, radioAddressTB5, serialNrTB5); } private void checkBoxImage6_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage6, fromOptoTextBox6, radioAddressTB6, serialNrTB6); } private void checkBoxImage7_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage7, fromOptoTextBox7, radioAddressTB7, serialNrTB7); } private void checkBoxImage8_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage8, fromOptoTextBox8, radioAddressTB8, serialNrTB8); } private void checkBoxImage9_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage9, fromOptoTextBox9, radioAddressTB9, serialNrTB9); } private void checkBoxImage10_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage10, fromOptoTextBox10, radioAddressTB10, serialNrTB10); } private void checkBoxImage11_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage11, fromOptoTextBox11, radioAddressTB11, serialNrTB11); } private void checkBoxImage12_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage12, fromOptoTextBox12, radioAddressTB12, serialNrTB12); } private void checkBoxImage13_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage13, fromOptoTextBox13, radioAddressTB13, serialNrTB13); } private void checkBoxImage14_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage14, fromOptoTextBox14, radioAddressTB14, serialNrTB14); } private void checkBoxImage15_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage15, fromOptoTextBox15, radioAddressTB15, serialNrTB15); } private void checkBoxImage16_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage16, fromOptoTextBox16, radioAddressTB16, serialNrTB16); } private void checkBoxImage17_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage17, fromOptoTextBox17, radioAddressTB17, serialNrTB17); } private void checkBoxImage18_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage18, fromOptoTextBox18, radioAddressTB18, serialNrTB18); } private void checkBoxImage19_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage19, fromOptoTextBox19, radioAddressTB19, serialNrTB19); } private void checkBoxImage20_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage20, fromOptoTextBox20, radioAddressTB20, serialNrTB20); } private void checkBoxImage21_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage21, fromOptoTextBox21, radioAddressTB21, textBox21); } private void checkBoxImage22_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage22, fromOptoTextBox22, radioAddressTB22, textBox22); } private void checkBoxImage23_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage23, fromOptoTextBox23, radioAddressTB23, textBox23); } private void checkBoxImage24_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage24, fromOptoTextBox24, radioAddressTB24, textBox24); } private void checkBoxImage25_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage25, fromOptoTextBox25, radioAddressTB25, textBox25); } private void checkBoxImage26_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage26, fromOptoTextBox26, radioAddressTB26, textBox26); } private void checkBoxImage27_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage27, fromOptoTextBox27, radioAddressTB27, textBox27); } private void checkBoxImage28_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage28, fromOptoTextBox28, radioAddressTB28, textBox28); } private void checkBoxImage29_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage29, fromOptoTextBox29, radioAddressTB29, textBox29); } private void checkBoxImage30_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage30, fromOptoTextBox30, radioAddressTB30, textBox30); } private void checkBoxImage31_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage31, fromOptoTextBox31, radioAddressTB31, textBox31); } private void checkBoxImage32_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage32, fromOptoTextBox32, radioAddressTB32, textBox32); } private void checkBoxImage33_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage33, fromOptoTextBox33, radioAddressTB33, textBox33); } private void checkBoxImage34_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage34, fromOptoTextBox34, radioAddressTB34, textBox34); } private void checkBoxImage35_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage35, fromOptoTextBox35, radioAddressTB35, textBox35); } private void checkBoxImage36_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage36, fromOptoTextBox36, radioAddressTB36, textBox36); } private void checkBoxImage37_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage37, fromOptoTextBox37, radioAddressTB37, textBox37); } private void checkBoxImage38_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage38, fromOptoTextBox38, radioAddressTB38, textBox38); } private void checkBoxImage39_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage39, fromOptoTextBox39, radioAddressTB39, textBox39); } private void checkBoxImage40_Click(object sender, EventArgs e) { ProcessClick(checkBoxImage40, fromOptoTextBox40, radioAddressTB40, textBox40); } void ProcessClick(CheckBoxImage checkBox, TextBox eRegisterNrTB, TextBox radioAddrTB, TextBox snTextBox) { if (checkBox.Checked) { eRegisterNrTB.Text = radioAddrTB.Text = string.Empty; } else { eRegisterNrTB.Text = radioAddrTB.Text = "xxx"; } if (skipBadMeters) { snTextBox.Visible = checkBox.Checked; } } } }