/// /// Copyright (c) 2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Drawing; using System.Globalization; using System.Windows.Forms; using log4net; using Common; using Config.Entities; using TBF.Resources; using TBF.BenchControl.Sequences; using System.IO; namespace TBF.BenchControl.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 = 40; 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 WatchOptoHeads, SaveStartPro, AwaitResponseToStartPro, /// End 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; /// Label[] labels; PictureBox[] pictures; TextBox[] messages; CheckBoxImage[] checkBoxes; 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; ProcParams pPars; /// IList activities; IList tests; /// int currentActivityIx; /// Step step; DateTime savedTimestamp; 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, wmLabel21, wmLabel22, wmLabel23, wmLabel24, wmLabel25, wmLabel26, wmLabel27, wmLabel28, wmLabel29, wmLabel30, wmLabel31, wmLabel32, wmLabel33, wmLabel34, wmLabel35, wmLabel36, wmLabel37, wmLabel38, wmLabel39, wmLabel40, }; pictures = new PictureBox[UIBoxesCount] { 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, }; messages = new TextBox[UIBoxesCount] { 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, }; checkBoxes = new CheckBoxImage[UIBoxesCount] { 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, }; ckbIndex = new int[UIBoxesCount]; /// Initialized by ShuffleTextBoxes() ... to be used in the future in case of test benches with two lines } /// /// Constructor for one S640Communication test /// /// Number of text boxes for serial numbers public S640CommForm(S640Activity activity, I640Cfg config, Generic.IProcedureParams procParams, Test test) : this(new List { activity }, config, procParams, new List { test }) { } /// /// Constructor for multiple S640Communication tests /// /// Number of text boxes for serial numbers public S640CommForm(IList activities, I640Cfg config, Generic.IProcedureParams procParams, IList tests) : this() { this.activities = activities; debugLevel = config.DebugLevel; optoDataTimeout = config.OptoDataTimeout; fileExchangePath = string.IsNullOrEmpty(config.FileExchangePath) ? string.Empty : config.FileExchangePath; fileExchangeTimeout = config.FileExchangeTimeout; this.tests = tests; this.pPars = procParams as ProcParams; 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); 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]; pictures[dest] = pictures[l * lineSize + l * gap + i]; messages[dest] = messages[l * lineSize + l * gap + i]; checkBoxes[dest] = checkBoxes[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 = pictures[i].Visible = messages[i].Visible = checkBoxes[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 /// long optoHeadsConfig = Program.LocalSettings.OptoHeadsEnabled; for (int i = 0; i < textBoxesCount; i++) { if ((optoHeadsConfig & (1L << i)) == 0 || optoHeads[i] == null) { /// Opto head is disabled in configuration checkBoxes[i].Checked = false; checkBoxes[i].Enabled = false; pictures[i].BackColor = DisabledColor; messages[i].Text = Strings.Opto_head_is_disabled_in_configuration; } else if ((i >= ProcessData.BatchRslts.Batch.WaterMeters.Count) || ProcessData.BatchRslts.Batch.WaterMeters[i] == null || ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled) { /// Opto head was disabled by an operator checkBoxes[i].Checked = false; checkBoxes[i].Enabled = false; pictures[i].BackColor = DisabledColor; messages[i].Text = Strings.Head_was_disabled_by_the_user; } else { /// Opto head is enabled checkBoxes[i].Checked = true; checkBoxes[i].Enabled = true; messages[i].Text = "---"; } /// Reset opto-data indication pictures[i].BackColor = OptoNokColor; } 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() { Text = Strings.Water_Meter_States; closeButton.Text = Strings.CloseBtnText; 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 activityIx) { startTime = DateTime.Now; activityLabel.Text = activities[activityIx].ToString(); currentActivityIx = activityIx; step = (activities[activityIx] == S640Activity.Start) ? Step.WatchOptoHeads : Step.SaveEndePro; closeButton.Visible = false; retryButton.Visible = false; responseTextBox.Text = string.Empty; if (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[activityIx], Progress.JustStarted)); sirtDataLogger.InfoFormat(""); /// Makes the log more readable when there is a lot of data sirtDataLogger.WarnFormat("Activity = {0}", activities[activityIx]); 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.WatchOptoHeads) { long optoHeadsConfig = Program.LocalSettings.OptoHeadsEnabled; bool allOK = true; for (int i = 0; i < textBoxesCount; i++) { if ((optoHeadsConfig & (1L << i)) == 0 || optoHeads[i] == null) { /// Opto head is disabled in configuration checkBoxes[i].Checked = false; checkBoxes[i].Enabled = false; pictures[i].BackColor = DisabledColor; messages[i].Text = Strings.Opto_head_is_disabled_in_configuration; } else if (!checkBoxes[i].Checked) { /// Opto head was disabled by the user pictures[i].BackColor = DisabledColor; messages[i].Text = Strings.Head_was_disabled_by_the_user; } else { /// Opto head is enabled checkBoxes[i].Checked = true; checkBoxes[i].Enabled = true; if (optoHeads[i].PcbNumber == 0) { /// Communication is NOK right now pictures[i].BackColor = OptoNokColor; messages[i].Text = "---"; commOkLoopsCount[i] = 0; allOK = false; } else { /// Communication is OK right now messages[i].Text = string.Format("pcb={0} radio={1}", optoHeads[i].PcbNumber, optoHeads[i].RadioAddress); 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; } } } if (allOK) { log.WarnFormat("allOk"); /// Update water meter properties for (int i = 0; i < textBoxesCount; i++) { if (i < ProcessData.BatchRslts.Batch.WaterMeters.Count && ProcessData.BatchRslts.Batch.WaterMeters[i] != null && !ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled) { if ((optoHeadsConfig & (1L << i)) != 0 && checkBoxes[i].Checked && optoHeads[i] != null) { /// Save PCB Number of the water meter ProcessData.BatchRslts.Batch.WaterMeters[i].SerialNr = optoHeads[i].PcbNumber.ToString(); /// PCB number (640) or body number (620) ProcessData.BatchRslts.Batch.WaterMeters[i].RadioAddress = optoHeads[i].RadioAddress.ToString(); /// Radio address (640) } else { /// Disable the water meter ProcessData.BatchRslts.Batch.WaterMeters[i].Disabled = true; } } } step = Step.SaveStartPro; } else if (optoDataTimeout != 0 && DateTime.Now - startTime > new TimeSpan(0, 0, optoDataTimeout)) { 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) { progressBar1.Value = (int)Math.Round((DateTime.Now - startTime).TotalSeconds); } } ///-------------------------------------------------------------------------- else if (step == Step.SaveStartPro) { activityLabel.Text = string.Format("Start: SIRT Communication"); 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; step = Step.AwaitResponseToStartPro; } ///-------------------------------------------------------------------------- else if (step == Step.AwaitResponseToStartPro) { if (!File.Exists(Path.Combine(fileExchangePath, StartFileName))) { /// File disappeared in time 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)) { activityLabel.Text = String.Format("{0}: SIRT {1}", Strings.Start, Strings.Timeout); log.Error("Start: SIRT timeout"); step = Step.ConfirmError; } else if (fileExchangeTimeout != 0) { progressBar1.Value = (int)Math.Round((DateTime.Now - savedTimestamp).TotalSeconds); } else { progressBar1.Visible = false; closeButton.Visible = true; retryButton.Visible = true; } } ///-------------------------------------------------------------------------- else if (step == Step.SaveEndePro) { activityLabel.Text = string.Format("End: SIRT Communication"); 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; step = Step.AwaitResponseToEndePro; } ///-------------------------------------------------------------------------- else if (step == Step.AwaitResponseToEndePro) { if (!File.Exists(Path.Combine(fileExchangePath, EndFileName))) { /// File disappeared in time 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 { closeButton.Visible = true; } } ///-------------------------------------------------------------------------- else if (step == Step.ConfirmError) { progressBar1.Visible = false; closeButton.Visible = true; retryButton.Visible = true; } ///-------------------------------------------------------------------------- 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); } } void SaveProFile(string filename, S640Activity activity, IList optoHeads) { string variant = string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WatermetersStr) ? string.Empty : ProcessData.BatchRslts.Batch.WatermetersStr; int count = 0; string purchaseOrder = null; for (int i = 0; i < optoHeads.Count; i++) { if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null) { count++; if (purchaseOrder == null && !string.IsNullOrEmpty(ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder)) { purchaseOrder = ProcessData.BatchRslts.Batch.WaterMeters[i].PurchaseOrder; } } } 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, pPars.ModuleParameter)); file.WriteLine(" "); for (int i = 0; i < optoHeads.Count; i++) { if (optoHeads[i] != null && optoHeads[i].PcbNumber != 0 && ProcessData.BatchRslts.Batch.WaterMeters[i] != null) { if (activity == S640Activity.Start) { file.WriteLine(string.Format(" ", optoHeads[i].RadioAddress.ToString(), optoHeads[i].PcbNumber.ToString())); } else if (activity == S640Activity.End) { file.WriteLine(string.Format(" ", optoHeads[i].RadioAddress.ToString(), optoHeads[i].RadioAddress.ToString(), /// TODO: Here should be the assigned serial number optoHeads[i].RadioAddress.ToString(), /// TODO: Here should be the new radio address optoHeads[i].PcbNumber.ToString())); } } } 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 ((Program.LocalSettings.OptoHeadsEnabled & (1L << i)) != 0 && optoHeads[i] != null && !commFailed) { meterRslt.TestDone = true; meterRslt.Passed = true; } else { meterRslt.TestDone = true; meterRslt.Passed = false; } } } } } } private void closeButton_Click(object sender, EventArgs e) { 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(); } 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); } } } }