/// /// Copyright (c) 2019-2022 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Threading; using System.Windows.Forms; using log4net; using Common; using SharedDatabase; using SharedDatabase.Entities; using SharedDatabase.Forms; using TBF.Rig.Modbus.Common; using NHibernate; using Oracle.DataAccess.Client; // ODP.NET Oracle managed provider using RecordProcessing; using GenericTest.Resources; namespace GenericTest { public partial class GenericTestDlg : Form { static readonly ILog log = LogManager.GetLogger(typeof(GenericTestDlg)); static readonly ILog results = LogManager.GetLogger("Results"); static readonly ILog badResults = LogManager.GetLogger("BadResults"); const int ErrorBeepFrequency = 500; /// Hz const int ErrorBeepDuration = 1000; /// ms #if RF_TEST public RecordProcessing.RecordType RcrdType = RecordType.RF_Test; public const string WorkflowStep = "rf_power"; public const string DfltWorkplaceName = "RF Test"; #elif RF_TEST_400_900 public RecordProcessing.RecordType RcrdType = RecordType.RF_Test_400_900; public const string WorkflowStep = "rf_power"; public const string DfltWorkplaceName = "RF Test"; #elif COMM_TEST public RecordProcessing.RecordType RcrdType = RecordType.CommTest; public const string WorkflowStep = "comm_test"; public const string DfltWorkplaceName = "Comm Test"; #elif FLOWTUBE_TEST_HE public RecordProcessing.RecordType RcrdType = RecordType.FlowtubeTestHe; public const string WorkflowStep = "helium_test"; public const string DfltWorkplaceName = "Helium Test"; #elif FLOWTUBE_TEST_AIR public RecordProcessing.RecordType RcrdType = RecordType.FlowtubeTestAir; public const string WorkflowStep = "helium_test"; public const string DfltWorkplaceName = "Helium Test"; #elif LASER_NANJING public RecordProcessing.RecordType RcrdType = RecordType.LaserNanjing; public const string WorkflowStep = "laser"; public const string DfltWorkplaceName = "Laser 1"; #else public RecordProcessing.RecordType RcrdType = RecordType.None; public const string WorkflowStep = "generic_test"; public const string DfltWorkplaceName = "Generic Test"; #endif const int ActivityMsgsCount = 7; ActivityEventArgs[] activityEvents; /// Activity messages displayed in the main window Common.Forms.ModelessForm modelessForm; NHibernate.ISession dbSession; /// MySQL database session static OracleConnection oracleConn; /// Oracle database connection (server is in Stara Tura) #if RF_TEST_400_900 static OracleConnection oracleConn2; /// Oracle database connection for Flexnet ID (server is in Ludwigshafen) #endif IList workflowSummaries; /// Workflows from the database with last step verification information DateTime lastUpdateOfWorkflows; RecordProcessing.RecordProcessing recordProcessing; bool isSensorReadRunning; int modbusAddress; Modbus modbus; System.Windows.Forms.Timer sensorReadTimer; double[] sensorBuffer; double[] sensorCoefficients; int validReadingsCount; double immediateSensorValue; double filteredSensorValue; #region GenericTestDlg constructor, event handlers and utilities /// /// Constructor /// public GenericTestDlg() { InitializeComponent(); try { string culture = Program.LocalSettings.Language.Replace('_', '-'); System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture); } catch (Exception exc) { string msg = exc.Message; MessageBox.Show("Selected language is not supported.\nUsing English.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en"); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en"); } Localize(); UpdateTitle(); /// Open a modeless form that is closed after initialization and loading the main window modelessForm = new Common.Forms.ModelessForm("Loading workflows from a database"); new Thread(() => Application.Run(modelessForm)).Start(); activityEvents = new ActivityEventArgs[ActivityMsgsCount]; activityListView.Columns.Add(Strings.Time, 60); #if FLOWTUBE_TEST_AIR || FLOWTUBE_TEST_HE activityListView.Columns.Add(Strings.Serial_number, 160); #else activityListView.Columns.Add(Strings.Serial_number, 95); #endif activityListView.Columns.Add(Strings.Message, 800); ActivityHandler += delegate(object sndr, ActivityEventArgs args) { if (InvokeRequired) Invoke(new EventHandler(DoOnActivity), sndr, args); else DoOnActivity(sndr, args); }; isSensorReadRunning = false; immediateSensorValue = 0; filteredSensorValue = 0; ReadProcesses_RegisterWorkplace_Etc(); } void Localize() { messageLabel.Text = string.IsNullOrEmpty(Program.LocalSettings.Workplace) ? "Laser" : Program.LocalSettings.Workplace; startButton.Text = Strings.Start; stopButton.Text = Strings.Stop; settingsButton.Text = Strings.Settings; logoutButton.Text = Strings.Logout; } private void GenericTestDlg_Load(object sender, EventArgs e) { Settings2UI(); StartSpoolProcessing(); UpdateStartStopButtons(); if (Program.LocalSettings.DoReadSensor) { StarSensorReading(); } if (modelessForm != null) modelessForm.CloseForm(); /// Close the modeless information form } private void startButton_Click(object sender, EventArgs e) { StartSpoolProcessing(); UpdateStartStopButtons(); } private void stopButton_Click(object sender, EventArgs e) { StopSpoolProcessing(); UpdateStartStopButtons(); } private void settingsButton_Click(object sender, EventArgs e) { if (new LoginDlg(Program.SettingsAccessLevel, this).ShowDialog() == DialogResult.OK) { /// Logged in at 'TraceabilityManagement' level CurrentUser.Restore(this); /// Restore the original user (= tester) string oriWorkplace = Program.LocalSettings.Workplace; /// if (new SettingsDlg().ShowDialog() == DialogResult.OK) { if (Program.LocalSettings.Workplace != oriWorkplace) { UpdateTitle(); TracingDB.UnregisterWorkplaceObsolete(dbSession, oriWorkplace); TracingDB.RegisterWorkplaceObsolete(dbSession, Program.LocalSettings.Workplace, CurrentUser.UserName(), "1.2.3.4", "", WorkflowStep, DateTime.Now + new TimeSpan(365, 0, 0, 0)); dbSession.Flush(); } } } } private void GenericTestDlg_FormClosing(object sender, FormClosingEventArgs e) { DialogResult dr = MessageBox.Show("Naozaj chcete zavrieť tento program?" + Environment.NewLine + "Výsledky sa nebudú ukladať do Oracle DB a tlačiť na tlačiarni", "Upozornenie", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (dr == DialogResult.Yes) { if (isSensorReadRunning) { StopSensorReading(); } UI2Settings(); TracingDB.UnregisterWorkplaceObsolete(dbSession, Program.LocalSettings.Workplace); dbSession.Flush(); StopSpoolProcessing(); } else { e.Cancel = true; } } /// /// Load UI settings from 'LocalSettings' /// void Settings2UI() { LocalSettings ls = Program.LocalSettings; WindowState = (ls != null && ls.MainWndMaximized) ? FormWindowState.Maximized : FormWindowState.Normal; Width = (ls != null && ls.MainWndWidth > 0) ? ls.MainWndWidth : 1000; Height = (ls != null && ls.MainWndHeight > 0) ? ls.MainWndHeight : 260; Left = (ls != null && ls.MainWndLeft > 0) ? ls.MainWndLeft : 50; Top = (ls != null && ls.MainWndTop > 0) ? ls.MainWndTop : 50; if (ls.DoReadSensor) { sensorNameLabel.Text = ls.SensorName; immediateSensorValueLabel.Text = string.Empty; filteredSensorValueLabel.Text = string.Empty; } else { splitContainer1.SplitterDistance = 0; } } /// /// Save UI settings to 'LocalSettings' /// void UI2Settings() { bool isMaximized = (WindowState == FormWindowState.Maximized); int left = (WindowState == FormWindowState.Normal) ? Location.X : RestoreBounds.Left; int top = (WindowState == FormWindowState.Normal) ? Location.Y : RestoreBounds.Top; int width = (WindowState == FormWindowState.Normal) ? Size.Width : RestoreBounds.Width; int height = (WindowState == FormWindowState.Normal) ? Size.Height : RestoreBounds.Height; LocalSettings ls = Program.LocalSettings; if (ls != null && (ls.MainWndMaximized != isMaximized || ls.MainWndLeft != left || ls.MainWndTop != top || ls.MainWndWidth != width || ls.MainWndHeight != height)) { /// At least one MainWnd dimension differs => Update local settings and save them ls.MainWndMaximized = isMaximized; ls.MainWndLeft = left; ls.MainWndTop = top; ls.MainWndWidth = width; ls.MainWndHeight = height; ls.Save(); } } void UpdateStartStopButtons() { bool r = (recordProcessing != null) ? recordProcessing.Running : false; startButton.Enabled = !r; stopButton.Enabled = r; } void StartSpoolProcessing() { if (recordProcessing != null) { recordProcessing.StartProcessing(); OnActivity(null, new ActivityEventArgs(Program.Version, Strings.Processing_tester_results_started, ActivityCode.StartStop, Color.Yellow, 5000, Color.LightGoldenrodYellow)); } } void StopSpoolProcessing() { if (recordProcessing != null) { recordProcessing.StopProcessing(); OnActivity(null, new ActivityEventArgs(Program.Version, Strings.Processing_tester_results_was_stopped, ActivityCode.StartStop, Color.Yellow, 5000, Color.LightGoldenrodYellow)); } } #endregion GenericTestDlg constructor, event handlers and utilities #region Sensor processing void StarSensorReading() { const int IntervalSec = 5; LocalSettings ls = Program.LocalSettings; try { int bufferLen = Math.Max(1, 60 * (int)ls.SensorFilterTimeMinutes / IntervalSec); sensorBuffer = new double[bufferLen]; sensorCoefficients = new double[bufferLen]; validReadingsCount = 0; double sum = 0; for (int i = 0; i < bufferLen; i++) { sensorCoefficients[i] = Math.Cos((i * Math.PI) / (2 * bufferLen)); sum += sensorCoefficients[i]; } for (int i = 0; i < bufferLen; i++) { sensorCoefficients[i] /= sum; /// normalize } modbusAddress = (ls.SensorAddress >= 1) && (ls.SensorAddress <= 254) ? ls.SensorAddress : 0; var modbusCfg = new ModbusCfg { Name = "Modbus", ParentName = string.Empty, ComPortNr = ls.SensorComPortNr, BaudRate = 9600, Parity = System.IO.Ports.Parity.None, DataBits = 8, StopBits = System.IO.Ports.StopBits.One, Handshake = System.IO.Ports.Handshake.None }; modbus = new Modbus(modbusCfg); modbus.Initialize(); sensorReadTimer = new System.Windows.Forms.Timer(); sensorReadTimer.Interval = 1000 * IntervalSec; /// Convert interval to ms sensorReadTimer.Tick += (Object s, EventArgs e) => { ReadSensor(); }; sensorReadTimer.Start(); modbus.SendMessage((byte)modbusAddress, (byte)TBF.Rig.Modbus.Function.ReadHoldingRegisters, (ushort)0x0030, (ushort)2, "Temperature"); isSensorReadRunning = true; } catch (Exception exc) { MessageBox.Show(string.Format("Cannot read sensor {0}, COM{1}, address {2}\r\n{3}", ls.SensorName, ls.SensorComPortNr, ls.SensorAddress, exc.Message)); } } void StopSensorReading() { if (isSensorReadRunning) { sensorReadTimer.Stop(); if (modbus != null) modbus.StopDevice(); } } void ReadSensor() { if (modbus != null) { modbus.RunDeviceBefore(); if (modbus.ReceivedTelegrams[modbusAddress].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[modbusAddress].Dequeue(); if (telegram.Length == 9 && telegram[1] == 3 && telegram[2] == 4) { int intValue = (int)telegram[3] * 256 + (int)telegram[4]; immediateSensorValue = (double)intValue / 10.0; filteredSensorValue = UpdateBufferAndGetFilteredValue(immediateSensorValue, sensorBuffer, sensorCoefficients, ref validReadingsCount); immediateSensorValueLabel.Text = string.Format("{0:F1} °C", immediateSensorValue); filteredSensorValueLabel.Text = string.Format("{0:F1} °C", filteredSensorValue); } } modbus.SendMessage((byte)modbusAddress, (byte)TBF.Rig.Modbus.Function.ReadHoldingRegisters, (ushort)0x0030, (ushort)2, "Temperature"); } } double UpdateBufferAndGetFilteredValue(double value, double[] buffer, double[] coefficients, ref int validCount) { if (validCount < buffer.Length) { for (int i = validCount; i > 0; i--) buffer[i] = buffer[i - 1]; buffer[0] = value; validCount++; double sumOfCoefficients = 0; double sumOfValues = 0; for (int i = 0; i < validCount; i++) { sumOfCoefficients += coefficients[i]; sumOfValues += (coefficients[i] * buffer[i]); } return sumOfValues / sumOfCoefficients; } else { for (int i = buffer.Length - 1; i > 0; i--) buffer[i] = buffer[i - 1]; buffer[0] = value; double sumOfValues = 0; for (int i = 0; i < validCount; i++) { sumOfValues += (coefficients[i] * buffer[i]); } return sumOfValues; } } #endregion Sensor processing #region Displaying activities and timer public static event EventHandler ActivityHandler; /// /// Called from the state machine when test process data change and UI needs to be updated. /// public static void OnActivity(object sender, ActivityEventArgs data) { if (ActivityHandler == null) return; try { ActivityHandler(sender, data); } catch (Exception) { } } private static System.Windows.Forms.Timer timer; private static Color delayedFadedColor; private static string messageText; /// private void DoOnActivity(object sender, ActivityEventArgs args) { #if FLOWTUBE_TEST_AIR || FLOWTUBE_TEST_HE string msg = string.Format("{0} - {1}", (string.IsNullOrEmpty(args.SN) ? "00000000000000000000" : args.SN), args.Message); string rslt = string.Format("{0} ; {1}", (string.IsNullOrEmpty(args.SN) ? "00000000000000000000" : args.SN), args.Message); #else string msg = string.Format("{0} - {1}", (string.IsNullOrEmpty(args.SN) ? "000000000000" : args.SN), args.Message); string rslt = string.Format("{0} ; {1}", (string.IsNullOrEmpty(args.SN) ? "000000000000" : args.SN), args.Message); #endif /// Logging level depends on data.IsError value if (args.ActivityCode == ActivityCode.StartStop) { /// Activity: Start/Stop log.Fatal(msg); } else if (args.ActivityCode == ActivityCode.Passed) { /// Activity: Passed log.Info(msg); results.Fatal(rslt); } else if (args.ActivityCode == ActivityCode.Failed) { /// Activity: Failed Console.Beep(ErrorBeepFrequency, ErrorBeepDuration); if (Program.LocalSettings.MaximizeWindowOnError) { /// Maximize windows and gain focus here this.WindowState = FormWindowState.Maximized; this.TopMost = true; this.Focus(); this.BringToFront(); } log.Error(msg); results.Fatal(rslt); badResults.Fatal(rslt); } else { /// Activity: Undefined return; } /// Shift activities in FIFO bufer, nw item is at index 0 (at the topP for (int i = ActivityMsgsCount - 1; i > 0; i--) { activityEvents[i] = activityEvents[i - 1]; } activityEvents[0] = args; messageLabel.Text = string.Format("{0} {1}", (string.IsNullOrEmpty(args.SN) ? "000000000000" : args.SN), args.Message); horizSplitContainer.Panel1.BackColor = args.Color; UpdateMultiLineActivityLog(); /// Start a timer if (timer == null) { timer = new System.Windows.Forms.Timer(); timer.Tick += (s, e) => { DelayTimerExpired(); }; } delayedFadedColor = args.FadedColor; messageText = messageLabel.Text; timer.Interval = args.Interval; timer.Start(); } void UpdateMultiLineActivityLog() { activityListView.Items.Clear(); for (int i = 0; i < ActivityMsgsCount; i++) { if (activityEvents[i] != null) { ListViewItem lvi = new ListViewItem(activityEvents[i].TimeStamp.ToLongTimeString()); lvi.SubItems.Add(string.IsNullOrEmpty(activityEvents[i].SN) ? "000000000000" : activityEvents[i].SN); lvi.SubItems.Add(activityEvents[i].Message); lvi.BackColor = activityEvents[i].FadedColor; activityListView.Items.Add(lvi); } } } void DelayTimerExpired() { /// Delayed action if (messageLabel.Text == messageText) { horizSplitContainer.Panel1.BackColor = delayedFadedColor; } timer.Stop(); timer.Enabled = false; } #endregion Displaying activities and timer /// /// Called from the main window constructor on program start-up /// void ReadProcesses_RegisterWorkplace_Etc() { /// /// Loads processes from the database. /// In case of problems (missing database) makes it possible to create a new one. /// bool testResultsFolderExists = false; DialogResult settingsDR = DialogResult.OK; do { if (settingsDR == DialogResult.OK) { testResultsFolderExists = Directory.Exists(Program.LocalSettings.TestResultsFolder); if (!testResultsFolderExists) { string failedMsg = string.Format(Strings.Opening_folder_0_failed, Program.LocalSettings.TestResultsFolder); log.Fatal(failedMsg); DialogResult rslt = MessageBox.Show(failedMsg + Environment.NewLine + Strings.Do_you_want_to_change_settings, Strings.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (rslt != DialogResult.Yes) { /// Settings ware not changed -> exit throw new QuitAppException(failedMsg); } settingsDR = new SettingsDlg().ShowDialog(); } } if (settingsDR == DialogResult.OK) { try { dbSession = TracingDB.CreateSession(Program.LocalSettings.ConnectionString); workflowSummaries = TracingDB.ReadWorkflowSummariesFromDB(dbSession, WorkflowStep); lastUpdateOfWorkflows = DateTime.Now; } catch (Exception exc) { log.FatalFormat("{0}:{1}{2}", Strings.Opening_database_failed, Environment.NewLine, exc.Message); DialogResult rslt = MessageBox.Show(Strings.Opening_database_failed + Environment.NewLine + Environment.NewLine + exc.Message + Environment.NewLine + Environment.NewLine + Strings.Do_you_want_to_change_settings, Strings.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (rslt != DialogResult.Yes) { /// Settings ware not changed -> exit throw new QuitAppException(Strings.Opening_database_failed); } settingsDR = new SettingsDlg().ShowDialog(); } } if ((settingsDR == DialogResult.OK) && Program.LocalSettings.DoSaveTestResultToOracle && (Program.LocalSettings.OracleMode != Mode.Debug)) { #if RF_TEST || RF_TEST_400_900 /// /// Connect to Oracle database in Stara Tura /// try { if ((Program.LocalSettings.OracleMode == Mode.Production) || (Program.LocalSettings.OracleMode == Mode.NoWritesToDB)) { oracleConn = new OracleConnection("Data Source=STARA01.WORLD;User Id=deltachef;Password=deltachef;"); } else if (Program.LocalSettings.OracleMode == Mode.Test) { oracleConn = new OracleConnection("Data Source=STARA_TEST.WORLD;User Id=deltachef;Password=deltachef;"); } /// Do something with the database to see if the connection works well oracleConn.Open(); string rslt = "none"; OracleCommand cmd = new OracleCommand("SELECT standort FROM anbieter_sd WHERE anbid = 4", oracleConn); OracleDataReader dr = cmd.ExecuteReader(); if (dr.Read()) rslt = dr.GetString(0); dr.Close(); oracleConn.Close(); } catch (Exception exc) { log.FatalFormat("{0}:{1}{2}", Strings.Opening_database_failed, Environment.NewLine, exc.Message); DialogResult rslt = MessageBox.Show(Strings.Opening_database_failed + Environment.NewLine + Environment.NewLine + exc.Message + Environment.NewLine + Environment.NewLine + Strings.Do_you_want_to_change_settings, Strings.Warning, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (rslt != DialogResult.Yes) { /// Settings ware not changed -> exit throw new QuitAppException(Strings.Opening_database_failed); } settingsDR = new SettingsDlg().ShowDialog(); } #endif #if RF_TEST_400_900 /// /// Connect to Oracle database in Ludwigshafen /// try { oracleConn2 = new OracleConnection("Data Source=ALDT01.WORLD;User Id=deltachef;Password=deltachef;"); /// Do something with the database to see if the connection works well oracleConn2.Open(); string rslt = "none"; OracleCommand cmd = new OracleCommand("SELECT pcb_number " + "FROM ip_flexnet_functional_test_pd " + "WHERE flexnet_uid = '330024' " + "ORDER BY changedate DESC", oracleConn2); OracleDataReader dr = cmd.ExecuteReader(); if (dr.Read()) rslt = dr.GetString(0); dr.Close(); oracleConn2.Close(); } catch (Exception exc) { log.FatalFormat("{0}:{1}{2}", Strings.Opening_database_failed, Environment.NewLine, exc.Message); DialogResult rslt = MessageBox.Show("LUDWIGSHAFEN ORACLE DB" + Environment.NewLine + Strings.Opening_database_failed + Environment.NewLine + Environment.NewLine + exc.Message, Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); /// Settings were not changed -> exit throw new QuitAppException(Strings.Something_failed); } #endif } } while (settingsDR != DialogResult.Cancel && (dbSession == null || !testResultsFolderExists)); if (settingsDR == DialogResult.Cancel) { /// Settings were not changed -> exit throw new QuitAppException(Strings.Something_failed); } if (!string.IsNullOrEmpty(Program.LocalSettings.UsersDBConnString)) { CurrentUser.LocalUsersDB = new DBSettings(DBType.MySql, Program.LocalSettings.UsersDBConnString); } UpdateTitle(); TracingDB.RegisterWorkplaceObsolete(dbSession, Program.LocalSettings.Workplace, CurrentUser.UserName(), "1.2.3.4", "", WorkflowStep, DateTime.Now + new TimeSpan(15, 0, 0, 0)); /// Registration is valid approx. 2 weeks /// Activate processing of test results created by a thirdparty test program switch (RcrdType) { case RecordType.RF_Test: case RecordType.RF_Test_400_900: recordProcessing = new RecordProcessing.RecordProcessing(RcrdType, RecordPostproc.Compress, Program.LocalSettings.TestResultsFolder, false, "*.xml", Program.LocalSettings.ArchiveFolder, true); break; case RecordType.CommTest: recordProcessing = new RecordProcessing.RecordProcessing(RecordType.CommTest, RecordPostproc.None, Program.LocalSettings.TestResultsFolder, true, "*.log"); break; case RecordType.FlowtubeTestHe: recordProcessing = new RecordProcessing.RecordProcessing(RecordType.FlowtubeTestHe, RecordPostproc.Move, Program.LocalSettings.TestResultsFolder, false, "*.csv", Program.LocalSettings.ArchiveFolder, true); break; case RecordType.FlowtubeTestAir: /// Format of records and processing is similar to RecordType.RF_Test recordProcessing = new RecordProcessing.RecordProcessing(RecordType.FlowtubeTestAir, RecordPostproc.Compress, Program.LocalSettings.TestResultsFolder, false, "*.xml", Program.LocalSettings.ArchiveFolder, true); break; case RecordType.LaserNanjing: recordProcessing = new RecordProcessing.RecordProcessing(RecordType.LaserNanjing, RecordPostproc.Move, Program.LocalSettings.TestResultsFolder, false, "*.csv", Program.LocalSettings.ArchiveFolder, true); break; case RecordType.None: default: recordProcessing = null; break; } if (recordProcessing != null) { recordProcessing.SubmitRecordHandler += delegate(object sender, RecordProcessing.SubmitRecordEventArgs args) { if (InvokeRequired) { Invoke(new EventHandler(ProcessOneRecord), sender, args); } else { ProcessOneRecord(sender, args); } }; } } /// /// Submits a reference part code from a record from a 3-rd party program /// /// /// Argument containing record fr void ProcessOneRecord(object sender, RecordProcessing.SubmitRecordEventArgs args) { IRecord testerRecord = args.Record; VerifState verifState = VerifState.Undefined; if ((testerRecord == null) || string.IsNullOrEmpty(testerRecord.SN) || (testerRecord.SN.Length < 3)) { /// PCB number is missing or too short verifState = VerifState.SNisMissing; OnActivity(null, new ActivityEventArgs(string.Empty, Strings.Serial_number_is_missing, ActivityCode.Failed, Color.Orange, 5000, Color.Wheat)); return; } #if RF_TEST_400_900 try { /// /// Replace Flexnet UID by PCB Number from Oracle database /// string pcbNrFromFlexnetUid = string.Empty; oracleConn2.Open(); OracleCommand cmd = new OracleCommand(string.Format("SELECT pcb_number " + "FROM ip_flexnet_functional_test_pd " + "WHERE flexnet_uid = '{0}' " + "ORDER BY changedate DESC", testerRecord.SN), oracleConn2); OracleDataReader dr = cmd.ExecuteReader(); if (dr.Read()) pcbNrFromFlexnetUid = dr.GetString(0); dr.Close(); oracleConn2.Close(); if (!string.IsNullOrEmpty(pcbNrFromFlexnetUid)) testerRecord.SN = pcbNrFromFlexnetUid; } catch (Exception) { } #endif if (Program.LocalSettings.DoCheckSNsValidity && (Program.LocalSettings.ValidSNPrefixes != null) && !Program.LocalSettings.ValidSNPrefixes.Contains(testerRecord.SN.Substring(0, 3))) { /// PCB number did not pass a validity check (is not on a list of valid PCB numbers) verifState = VerifState.SNisInvalid; OnActivity(null, new ActivityEventArgs(testerRecord.SN, Strings.Serial_number_is_invalid, ActivityCode.Failed, Color.Orange, 5000, Color.Wheat)); return; } /// /// A valid serial number is available => proceed /// ITransaction transaction = null; bool savingToTracingDBFailed = false; /// Writing to tracoing DB failed (equipment error) bool verificationFailed = false; /// Reading/writing from/to tracing DB OK, but verification failed (product error) try { /// /// Tracing DB read/write is done inside this try/catch /// transaction = dbSession.BeginTransaction(); /// Get a process of the last reference record with this PCB number var refRecord = TracingDB.FindReferenceRecord(dbSession, testerRecord.SN, 1); WorkflowSummary wSum = (refRecord == null) ? null : workflowSummaries.FirstOrDefault(x => x.Workflow.Name == refRecord.Workflow); if (refRecord == null || wSum == null) { verifState = VerifState.NoRefRecordOrNoMatchingWorkflow; verificationFailed = true; savingToTracingDBFailed = false; } else { if (!Program.LocalSettings.DoCheckPreviousTracingRecords) { /// The process was determined but checking previous records is disbled => everything is OK so far verifState = VerifState.VerificationIsDisabled; verificationFailed = false; } else { /// Process is known AND the system is checking previous records => verify previous step StepRecord prevStep = refRecord.StepRecords.FirstOrDefault(x => (x.Workstep == wSum.PreviousWorkstepName && x.Result == 0)); verificationFailed = (prevStep == null); verifState = (prevStep != null) ? VerifState.VerificationPassed : VerifState.VerificationFailed; } /// result: 0=OK, 1=test failed, 2=OK but previous step is missing, 3=failed and previous step is missing int result = ((testerRecord.Status == Status.Passed) ? 0 : 1) + ((verifState == VerifState.VerificationFailed) ? 2 : 0); string workplace = Program.LocalSettings.Workplace; string user = "user"; /// StepRecord stepRecord = new StepRecord(refRecord, wSum.WorkstepName, workplace, user, result); refRecord.Timestamp = stepRecord.Timestamp; refRecord.StepRecords.Add(stepRecord); dbSession.SaveOrUpdate(stepRecord); dbSession.SaveOrUpdate(refRecord); transaction.Commit(); savingToTracingDBFailed = false; } } catch (Exception) { if ((transaction != null) && !transaction.WasCommitted) transaction.Rollback(); savingToTracingDBFailed = true; } /// /// Write the test result to Oracle DB /// bool savingToOracleDBFailed = false; if (Program.LocalSettings.DoSaveTestResultToOracle && testerRecord.CanSaveRecordToOracle() && (Program.LocalSettings.OracleMode != Mode.Debug) && (Program.LocalSettings.OracleMode != Mode.NoWritesToDB) && (testerRecord.Status != Status.Interrupted)) { #if RF_TEST /// Conditions for writing data to Oracle DB are satisfied savingToOracleDBFailed = !testerRecord.SaveRecordToOracle(oracleConn); if (savingToOracleDBFailed) log.ErrorFormat("Saving test result to Oracle failed : {0}", testerRecord.ToString()); #elif RF_TEST_400_900 /// Conditions for writing data to Oracle DB are satisfied savingToOracleDBFailed = !testerRecord.SaveRecordToOracle(oracleConn2); if (savingToOracleDBFailed) log.ErrorFormat("Saving test result to Oracle failed : {0}", testerRecord.ToString()); #endif } /// /// Print the test result on a printer /// bool printingFailed = false; if (Program.LocalSettings.DoPrintLabels && testerRecord.CanPrintRecord() && (!Program.LocalSettings.DoPrintGoodLabelsOnly || !(savingToTracingDBFailed || verificationFailed || savingToOracleDBFailed || testerRecord.Status != Status.Passed))) { /// Conditions for printing results are satisfied #if RF_TEST || RF_TEST_400_900 /// Get battery info from Tracing database if ((proc != null) && (testerRecord is RecordProcessing.Records.RFTestRecord)) { RecordProcessing.Records.RFTestRecord rfRecord = testerRecord as RecordProcessing.Records.RFTestRecord; foreach (var part in proc.Parts) { if (!string.IsNullOrEmpty(part.OraDBType)) { string[] oraItems = part.OraDBType.Split(new char[] { ' ' }); string oraType = oraItems[0]; string oraDescr = (oraItems.Length > 1) ? oraItems[1] : string.Empty; if ((oraType == "Batt") || (oraType == "Batt1") || (oraType == "Batt2")) { rfRecord.BattSapPartNr = part.Name; rfRecord.BattSupplier = oraDescr; /// Should be "TADIRAN" or "VITZROCELL" /// Prepare battery producer information to be printed on labels if (rfRecord.BattSupplier.ToUpper() == "VITZROCELL") rfRecord.PrintedInfo = "Vi"; else if (rfRecord.BattSupplier.ToUpper() == "TADIRAN") rfRecord.PrintedInfo = "T"; else rfRecord.PrintedInfo = "-"; } //if (oraType == "Flowtube") //{ // rfRecord.FlowtubeSapPartNr = part.Name; // rfRecord.IsPorexFlowtube = Program.LocalSettings.DoCheckPorexSapNumbers // && !string.IsNullOrEmpty(Program.LocalSettings.PorexSapNumbers) // && Program.LocalSettings.PorexSapNumbers.Contains(part.Name); //} } } } #endif printingFailed = !testerRecord.PrintRecord(); if (printingFailed) log.ErrorFormat("Printing result failed : {0}", testerRecord.ToString()); } /// /// Display the test result and related activity on the screen. /// Process the most severe errors first. /// if (verificationFailed) { /// Verification is enabled, but a record from the previous workplace is missing OnActivity(null, new ActivityEventArgs(testerRecord.SN, Strings.Previous_workflow_step_is_missing_or_failed, ActivityCode.Failed, Color.Blue, 5000, Color.LightBlue)); } else if (savingToTracingDBFailed) { OnActivity(null, new ActivityEventArgs(testerRecord.SN, Strings.Saving_to_Tracing_DB_failed, ActivityCode.Failed, Color.Orange, 5000, Color.Wheat)); } else if (savingToOracleDBFailed) { OnActivity(null, new ActivityEventArgs(testerRecord.SN, Strings.Saving_to_Oracle_DB_failed, ActivityCode.Failed, Color.Orange, 5000, Color.Wheat)); } else if (printingFailed) { OnActivity(null, new ActivityEventArgs(testerRecord.SN, Strings.Printing_failed, ActivityCode.Failed, Color.Orange, 5000, Color.Wheat)); } else if (testerRecord.Status != Status.Passed) { /// Test result is 'Failed' or 'Interrupted' OnActivity(null, new ActivityEventArgs(testerRecord.SN, string.Format(Strings.Test_failed_0, testerRecord.ResultStr), ActivityCode.Failed, Color.Red, 5000, Color.Pink)); } else { /// Test passed OnActivity(null, new ActivityEventArgs(testerRecord.SN, string.Format(Strings.OK_0, testerRecord.ResultStr), ActivityCode.Passed, Color.Green, 5000, Color.LightGreen)); } } private void logoutButton_Click(object sender, EventArgs e) { /// /// User login /// while (true) { if (new SharedDatabase.Forms.LoginDlg().ShowDialog() == DialogResult.OK) { break; } } UpdateTitle(); //wplaceRegistration.UpdateRegistration(dbSession, // Program.LocalSettings.WorkplaceId, // Users.GlobalData.CurrentUser.UserName, // "1.2.3.4", // (currentProcess != null) ? currentProcess.Name : string.Empty, // (currentWorkstep != null) ? currentWorkstep.Name : string.Empty, // DateTime.Now + new TimeSpan(8, 0, 0)); } void UpdateTitle() { Text = string.Format("{0} v.{1} ({2}, {3})", DfltWorkplaceName, Program.Version, Program.LocalSettings.Workplace, CurrentUser.UserName()); } } }