/// /// Copyright (c) 2020-2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.IO; using System.Threading; using Config.Entities; using TBF.BenchControl.GenericDevices; using TBF.BenchControl.Operations; using TBF.Boxes; using TBF.Resources; using TBF.UiBridge; using Results.Entities; namespace TBF.BenchControl.Sequences { partial class MainSeq { /// /// Wrapper /// IList ServeCalendarEventsInvokeXY(Config.CalendarEvent.AutoAction selectedAction, int maxCount = 1) { return TBF.UI.Calendar.CalendarTabPageCtrl.ServeCalendarEventsInvokeXY(selectedAction, maxCount); } /// /// Unconditionally wait for OK button /// void WaitForOkButton() { State.Create("MainSeq : Press OK to start the system") .AddOperation(new BenchControl.Operations.MessageBoxOp(Strings.Start_the_test_bench, System.Drawing.Color.OliveDrab)) .EnterState(); while (!StateMachine.WaitRunDevsRunOps().Contains(Event.OK)) { } } /// /// Unconditionally set valves to default position /// void SetValvesToDefaultState() { State.Create("MainSeq : Setting valves to default positions") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { } } /// /// Test communication with all scales that support S/N read operation /// /// Name of a scale that failed /// Message in case of a failure /// true = Test passed, all scales communicate OK bool TestCommunicationWithScales(out string scaleName, out string message) { /// /// Read S/N-s from scales (cannot be stopped, but is limitted to Scales count x 3s (=timeout) /// IScaleOrTank[] tanks = new IScaleOrTank[] { StateMachine.Tank1, StateMachine.Tank2, StateMachine.Tank3 }; foreach (var tank in tanks) { if (tank is IScale) { IScale scale = tank as IScale; string sn = string.Empty; IOperation getSNOp = scale.GetSerNumOp(ref sn); if (getSNOp != null) { const int nrRetries = 3; for (int i = 1; i <= nrRetries; i++) { IList e; bool error = false; bool timeout = false; State.Create(string.Format("MainSeq : Reading S/N of scale {0} trial {1}", scale.Name, i)) .AddOperation(getSNOp) .AddOperation(new Operations.TimerOp(2)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) { if (i == nrRetries) { /// /// All retries completed => the scale failed /// scaleName = scale.Name; message = Strings.Scale_communication_error; return false; } else { /// The scale failed => try one more time error = true; break; } } if (e.Contains(Event.Busy) && e.Contains(Event.TimerExpired)) { if (i == nrRetries) { /// /// All retries completed, the scale failed /// scaleName = scale.Name; message = Strings.Scale_communication_timeout; return false; } else { /// The scale failed => try one more time timeout = true; break; } } } while (e.Contains(Event.Busy)); if (!error && !timeout) { /// This scale communicates OK, break "for (int i = ... " loop if (!string.IsNullOrEmpty(sn)) log.WarnFormat("Scale {0} : s/n = {1}", scale.Name, sn); break; /// } /// Wait one state machine tick (1 second), kreep retrying, stay inside "for (int i = ... " loop State.Create(string.Format("MainSeq : Reading S/N of scale {0}", scale.Name)).EnterState(); StateMachine.WaitRunDevsRunOps(); } } } } /// /// All scales communicate OK, test passed /// scaleName = string.Empty; message = string.Empty; return true; } /// /// /// /// true = OK, false = error bool DrainTanks() { IList e; /// /// Enable stop draining buttons /// Bridge.Bench2UI(((StateMachine.DrainValve1 != null) ? ButtonsEtc.DrainTankBtn1Hi : 0) | ((StateMachine.DrainValve2 != null) ? ButtonsEtc.DrainTankBtn2Hi : 0) | ((StateMachine.DrainValve3 != null) ? ButtonsEtc.DrainTankBtn3Hi : 0)); /// /// Determine lists of drain valves and drain times (max. of all tank drain times) /// IList fullDrainValves = new List(); IList secondHalfDrainValves = new List(); IList allDrainValves = new List(); int totalDrainTime = 0; int maxDrainTimeFor2VlvTanks = 0; bool areTwoDrainPhases = false; foreach (IScaleOrTank tank in new IScaleOrTank[] { StateMachine.Tank1, StateMachine.Tank2, StateMachine.Tank3 }) { if (tank != null && tank.DrainValve != null) { if (tank.EmptyTimeSec > totalDrainTime) totalDrainTime = tank.EmptyTimeSec; if (tank.DrainValve2 != null) { areTwoDrainPhases = true; if (tank.EmptyTimeSec > maxDrainTimeFor2VlvTanks) maxDrainTimeFor2VlvTanks = tank.EmptyTimeSec; if (!secondHalfDrainValves.Contains(tank.DrainValve)) secondHalfDrainValves.Add(tank.DrainValve); if (!fullDrainValves.Contains(tank.DrainValve2)) fullDrainValves.Add(tank.DrainValve2); if (!allDrainValves.Contains(tank.DrainValve)) allDrainValves.Add(tank.DrainValve); if (!allDrainValves.Contains(tank.DrainValve2)) allDrainValves.Add(tank.DrainValve2); } else { if (!fullDrainValves.Contains(tank.DrainValve)) fullDrainValves.Add(tank.DrainValve); if (!allDrainValves.Contains(tank.DrainValve)) allDrainValves.Add(tank.DrainValve); } } } /// /// Drain the tanks, two phases if necessary /// if (totalDrainTime > 0) { IntBox timerTime = new IntBox(); /// Contains remaining time in each phase int firstPhaseTime = maxDrainTimeFor2VlvTanks / 2; State.Create(areTwoDrainPhases ? "MainSeq : Drain tanks - phase 1" : "MainSeq : Drain tanks") .AddOperation(checkUiOp) .AddOperation(new TimerOp(areTwoDrainPhases ? firstPhaseTime : totalDrainTime, timerTime)) .AddOperation(StateMachine.ControlBoard.SetValvesOp(fullDrainValves, null)) .EnterState(); do { int remTime = areTwoDrainPhases ? (timerTime.Val + totalDrainTime - firstPhaseTime) : timerTime.Val; Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec)); e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) return false; bool stopDrainingCmd = e.Contains(Event.UiCmdStopDrainingTank1) || e.Contains(Event.UiCmdStopDrainingTank2) || e.Contains(Event.UiCmdStopDrainingTank3); if (stopDrainingCmd && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) break; } while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy)); if (areTwoDrainPhases) { State.Create("MainSeq : Drain tanks - phase 2") .AddOperation(checkUiOp) .AddOperation(new TimerOp(totalDrainTime - firstPhaseTime, timerTime)) .AddOperation(StateMachine.ControlBoard.SetValvesOp(secondHalfDrainValves, null)) .EnterState(); do { int remTime = timerTime.Val; Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec)); e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) return false; bool stopDrainingCmd = e.Contains(Event.UiCmdStopDrainingTank1) || e.Contains(Event.UiCmdStopDrainingTank2) || e.Contains(Event.UiCmdStopDrainingTank3); if (stopDrainingCmd && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) break; } while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy)); } Bridge.OnActivity(this, Strings.Emptying_tank); State stopDraining = State.Create("MainSeq : Stop draining water tanks") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, allDrainValves)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) return false; } while (e.Contains(Event.ValvesBusy)); } return true; /// OK } /// /// This function is called after a procedure was selected and all components procedure parameters of components were loaded /// void ClearSessionData() { /// /// Clear iperlhead data (including PCB Number, avoid double use) /// foreach (var cmpnt in StateMachine.Components) { if (cmpnt is TestMethods.iPerlCommunication.iPerlHead.IperlHead) { (cmpnt as TestMethods.iPerlCommunication.iPerlHead.IperlHead).ClearData(); } } IsQ2PreCorrectionCalculated = false; CalculatedQ2PreCorrectionLR = 0; CalculatedQ2PreCorrectionRL = 0; RawTestInfos = null; CompleteTestInfos = null; } /// /// Idle loop to make a procedure or test selection. /// Handles tank emptying, camera test. /// /// Context where MakeSelection() is called /// /// Selection.PurgeBegin, PurgeEnd, Break, Cycle, Test, Q1, Q2, Q3 or SaveResults /// Selection MakeSelection(MKSelContext context) { log.WarnFormat("MakeSelection({0})", context); bool restoreIntrptdSessionEnabled = (context == MKSelContext.ProcedureNotSelected) && File.Exists(ProcessData.PDataFileName); /// Tank emptying valves states bool draining1 = false; bool draining2 = false; bool draining3 = false; /// Measured masses to control emptying DoubleBox mass1 = new DoubleBox(); DoubleBox mass2 = new DoubleBox(); DoubleBox mass3 = new DoubleBox(); IList e; while (true) { bool draining = draining1 || draining2 || draining3; /// /// Activity message /// Bridge.OnActivity(this, draining ? Strings.Emptying_tank : ((context == MKSelContext.ProcedureNotSelected) ? Strings.Please_select_a_procedure : Strings.Please_select_a_cycle_a_test_or_empty)); bool saveResultsActive = (context == MKSelContext.InsideProcedure) && (StateMachine.Procedure != null) && (!StateMachine.Procedure.MustBeComplete || BatchRslts.AllTestsDone()); /// Enable appropriate UI controls and buttons Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ((context == MKSelContext.InsideProcedure) ? ButtonsEtc.Break : 0) | (restoreIntrptdSessionEnabled ? ButtonsEtc.RestoreSession : 0) | (saveResultsActive ? ButtonsEtc.AcceptResultsBtnEn : 0) | (draining ? 0 : ButtonsEtc.StartCycleBtnEn) | (draining ? 0 : ButtonsEtc.StartTestBtnsEn) | (draining ? 0 : ButtonsEtc.PurgeBeginBtnEn) | (draining ? 0 : ((context == MKSelContext.InsideProcedure) ? ButtonsEtc.PurgeEndBtnEn : 0)) | ((StateMachine.DrainValve1 == null) ? 0 : (draining1 ? ButtonsEtc.DrainTankBtn1Hi : ButtonsEtc.DrainTankBtn1En)) | ((StateMachine.DrainValve2 == null) ? 0 : (draining2 ? ButtonsEtc.DrainTankBtn2Hi : ButtonsEtc.DrainTankBtn2En)) | ((StateMachine.DrainValve3 == null) ? 0 : (draining3 ? ButtonsEtc.DrainTankBtn3Hi : ButtonsEtc.DrainTankBtn3En))); State.Create("MainSeq : Select an activity") .AddOperation(checkUiOp) .AddOperation(StateMachine.BenchWaitingOp) .AddOperation((StateMachine.Tank1 is IScale) ? (StateMachine.Tank1 as IScale).ReadMassOp(ref mass1) : null) .AddOperation((StateMachine.Tank2 is IScale) ? (StateMachine.Tank2 as IScale).ReadMassOp(ref mass2) : null) .AddOperation((StateMachine.Tank3 is IScale) ? (StateMachine.Tank3 as IScale).ReadMassOp(ref mass3) : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); /// Handled inside MakeSelection() inside the selection loop if (e.Contains(Event.Error)) break; if (!draining1 && e.Contains(Event.UiCmdDrainTank1)) break; if (!draining2 && e.Contains(Event.UiCmdDrainTank2)) break; if (!draining3 && e.Contains(Event.UiCmdDrainTank3)) break; if (draining1 && e.Contains(Event.UiCmdStopDrainingTank1)) break; if (draining2 && e.Contains(Event.UiCmdStopDrainingTank2)) break; if (draining3 && e.Contains(Event.UiCmdStopDrainingTank3)) break; if (draining1 && StateMachine.Tank1.IsEmpty()) break; if (draining2 && StateMachine.Tank2.IsEmpty()) break; if (draining3 && StateMachine.Tank3.IsEmpty()) break; /// Quit the selection loop and leave MakeSelection() if (e.Contains(Event.UiCmdShutdown)) return Selection.Shutdown; if (context == MKSelContext.InsideProcedure && e.Contains(Event.UiCmdBreak)) return Selection.Break; if (e.Contains(Event.UiCmdPurgeBegin)) return Selection.PurgeBegin; if (e.Contains(Event.UiCmdPurgeEnd)) return Selection.PurgeEnd; if (e.Contains(Event.UiCmdStartCycle)) return Selection.Cycle; if (e.Contains(Event.UiCmdStartTest)) return Selection.Test; if (e.Contains(Event.UiCmdStartQ1)) return Selection.Q1; if (e.Contains(Event.UiCmdStartQ2)) return Selection.Q2; if (e.Contains(Event.UiCmdStartQ3)) return Selection.Q3; if (e.Contains(Event.UiCmdAcceptResults)) return Selection.SaveResults; if (e.Contains(Event.UiCmdReloadBatch)) return Selection.RestoreBatch; if (e.Contains(Event.UiCmdReloadAndFixBatch)) return Selection.RestoreAndFixBatch; if (restoreIntrptdSessionEnabled && e.Contains(Event.UiCmdRestoreSession)) return Selection.RestoreInterruptedSession; } while (true); if (e.Contains(Event.Error)) { ///------------------------------------ Bridge.OnActivity(this, Strings.Error); ///------------------------------------ State.Create("MainSeq : ERROR state") .AddOperation(checkUiOp) .AddOperation(StateMachine.BenchErrorOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.UiCmdShutdown)); return Selection.Shutdown; } else { string stateText = "MainSeq : "; IList openValves = new List(); IList closeValves = new List(); if (draining1 && (StateMachine.Tank1.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank1))) { draining1 = false; closeValves.Add(StateMachine.DrainValve1); stateText = stateText + "close tank 1, "; } else if (draining2 && (StateMachine.Tank2.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank2))) { draining2 = false; closeValves.Add(StateMachine.DrainValve2); stateText = stateText + "close tank 2, "; } else if (draining3 && (StateMachine.Tank3.IsEmpty() || e.Contains(Event.UiCmdStopDrainingTank3))) { draining3 = false; closeValves.Add(StateMachine.DrainValve3); stateText = stateText + "close tank 3, "; } else if (!draining1 && e.Contains(Event.UiCmdDrainTank1)) { draining1 = true; openValves.Add(StateMachine.DrainValve1); stateText = stateText + "open tank 1, "; } else if (!draining2 && e.Contains(Event.UiCmdDrainTank2)) { draining2 = true; openValves.Add(StateMachine.DrainValve2); stateText = stateText + "open tank 2, "; } else if (!draining3 && e.Contains(Event.UiCmdDrainTank3)) { draining3 = true; openValves.Add(StateMachine.DrainValve3); stateText = stateText + "open tank 3, "; } draining = draining1 || draining2 || draining3; if (draining) Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ((StateMachine.DrainValve1 == null) ? 0 : (draining1 ? ButtonsEtc.DrainTankBtn1Hi : ButtonsEtc.DrainTankBtn1En)) | ((StateMachine.DrainValve2 == null) ? 0 : (draining2 ? ButtonsEtc.DrainTankBtn2Hi : ButtonsEtc.DrainTankBtn2En)) | ((StateMachine.DrainValve3 == null) ? 0 : (draining3 ? ButtonsEtc.DrainTankBtn3Hi : ButtonsEtc.DrainTankBtn3En))); State.Create(stateText) .AddOperation(StateMachine.ControlBoard.SetValvesOp(openValves, closeValves)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (e.Contains(Event.ValvesBusy)); } } } void Shutdown(bool skipTankDraining = false) { log.WarnFormat(string.Format("Shutdown(skipTankDraining={0})", skipTankDraining)); StateMachine.MachineState = MachineState.ShuttingDown; /// TBF shut down cannot be aborted from now on Bridge.Bench2UI(0); /// All buttons off if (!skipTankDraining) { /// Drain time int maxDrainTime = 0; if ((StateMachine.Tank1 != null) && (StateMachine.Tank1.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank1.EmptyTimeSec; if ((StateMachine.Tank2 != null) && (StateMachine.Tank2.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank2.EmptyTimeSec; if ((StateMachine.Tank3 != null) && (StateMachine.Tank3.EmptyTimeSec > maxDrainTime)) maxDrainTime = StateMachine.Tank3.EmptyTimeSec; /// Drain valves IList drainValves = new List(); if (StateMachine.DrainValve1 != null) drainValves.Add(StateMachine.DrainValve1); if (StateMachine.DrainValve2 != null) drainValves.Add(StateMachine.DrainValve2); if (StateMachine.DrainValve3 != null) drainValves.Add(StateMachine.DrainValve3); /// Open all drain valves if (drainValves.Count > 0) { Bridge.OnActivity(this, Strings.Emptying_tank); /// Activity message State.Create("Open all drain valves") .AddOperation(StateMachine.ControlBoard.SetValvesOp(drainValves, null)) .EnterState(); while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { } } /// Tank emptying valves states bool draining1 = (StateMachine.DrainValve1 != null && StateMachine.Tank1 != null); bool draining2 = (StateMachine.DrainValve2 != null && StateMachine.Tank2 != null); bool draining3 = (StateMachine.DrainValve3 != null && StateMachine.Tank3 != null); int drainingStartTime = StateMachine.Time; /// Quit the following loop when time expires or all tanks are empty while ((StateMachine.Time < drainingStartTime + maxDrainTime) && (draining1 || draining2 || draining3)) { int remTime = drainingStartTime + maxDrainTime - StateMachine.Time; Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remTime / 60, "min", remTime % 60, Strings.sec)); DoubleBox mass1 = new DoubleBox(); DoubleBox mass2 = new DoubleBox(); DoubleBox mass3 = new DoubleBox(); /// State.Create("MainSeq : Reading mass") .AddOperation(checkUiOp) .AddOperation((StateMachine.Tank1 is IScale) ? (StateMachine.Tank1 as IScale).ReadMassOp(ref mass1) : null) .AddOperation((StateMachine.Tank2 is IScale) ? (StateMachine.Tank2 as IScale).ReadMassOp(ref mass2) : null) .AddOperation((StateMachine.Tank3 is IScale) ? (StateMachine.Tank3 as IScale).ReadMassOp(ref mass3) : null) .EnterState(); while (StateMachine.WaitRunDevsRunOps().Contains(Event.Busy)) { } if (draining1 && StateMachine.Tank1 != null && StateMachine.Tank1.IsEmpty()) draining1 = false; if (draining2 && StateMachine.Tank2 != null && StateMachine.Tank2.IsEmpty()) draining2 = false; if (draining3 && StateMachine.Tank3 != null && StateMachine.Tank3.IsEmpty()) draining3 = false; } /// Close all drain valves if (drainValves.Count > 0) { State.Create("Close all drain valves") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, drainValves)) .EnterState(); while (StateMachine.WaitRunDevsRunOps().Contains(Event.ValvesBusy)) { } } } /// /// Shut down the state machine /// Bridge.OnActivity(this, Strings.Shutting_down_devices); /// Activity message State.Create("No operations").EnterState(); /// Stop all operations StateMachine.WaitRunDevsRunOps(true); BenchControl.StateMachine.StopDevices(); /// Stop all devices - phase 1 Thread.Sleep(100); BenchControl.StateMachine.StopDevices2(); /// Stop all devices - phase 2 } /// /// Create a new empty batch results from the procedure /// /// New batch number /// Selected procedure /// Created BatchResults Results.BatchResults CreateNewBatchResults(int newBatchNr, Procedure procedure) { /// /// Prepare new water meters /// foreach (var wm in WaterMeters) wm.ClearData(); /// Clean water meter data bool compound = (StateMachine.Procedure.MetersKind == MetersKind.Combined); bool heatMeters = (StateMachine.Procedure.MetersKind == MetersKind.HeatMeter); int waterMetersCount = Math.Min(WaterMeters.Count, heatMeters ? Config.Data.HeatMetersCount : (compound ? Config.Data.CompoundWMsCount : Config.Data.WMsCount)); /// Results.Entities.WaterMeterData[] waterMeterData = new Results.Entities.WaterMeterData[waterMetersCount]; /// int[] waterMeterParts = new int[waterMetersCount]; for (int wmNr = 0; wmNr < waterMetersCount; wmNr++) { int ix = compound ? (2 * wmNr) : wmNr; if (WaterMeters.Count > ix) { waterMeterParts[wmNr] = Utils.PartNr(wmNr + 1, compound); waterMeterData[wmNr] = new Results.Entities.WaterMeterData() { ProductName = WaterMeters[ix].ProductName, Producer = WaterMeters[ix].Producer, L = WaterMeters[ix].L, DN = WaterMeters[ix].DN, Mounting = WaterMeters[ix].Mounting, NewQnames = WaterMeters[ix].NewQnames, Q4_Qmax = WaterMeters[ix].Q4_Qmax, Q3_Qn = WaterMeters[ix].Q3_Qn, Q2_Qt = WaterMeters[ix].Q2_Qt, Q1_Qmin = WaterMeters[ix].Q1_Qmin, MetrologicalClass = WaterMeters[ix].MetrologicalClass, TemperatureClass = WaterMeters[ix].TemperatureClass, PressureLossClass = WaterMeters[ix].PressureLossClass, MaxAdmissiblePressure = WaterMeters[ix].MaxAdmissiblePressure, FlowProfileSensitivityClass = WaterMeters[ix].FlowProfileSensitivityClass, ApprovalInfo = WaterMeters[ix].ApprovalInfo, Certificate = WaterMeters[ix].Certificate, PulsesPerLtr = WaterMeters[ix].PulsesPerLtr, Medium = WaterMeters[ix].Medium, Text1 = WaterMeters[ix].Text1, Text2 = WaterMeters[ix].Text2, Text3 = WaterMeters[ix].Text3, Text4 = WaterMeters[ix].Text4, Text5 = WaterMeters[ix].Text5, Compound = compound, HeatMeter = heatMeters, #if ORACLE_DB WMTypeId = (ProcessData.OracleDB != null) ? ProcessData.OracleDB.WMTypeId : 0, #endif }; } int auxIx = 2 * wmNr + 1; if (compound && WaterMeters.Count > auxIx) { waterMeterData[wmNr].ProducerAux = WaterMeters[auxIx].Producer; waterMeterData[wmNr].Q3_Qn_Aux = WaterMeters[auxIx].Q3_Qn; waterMeterData[wmNr].MetrologicalClassAux = WaterMeters[auxIx].MetrologicalClass; waterMeterData[wmNr].ApprovalInfoAux = WaterMeters[auxIx].ApprovalInfo; } } /// Prepare empty results return Results.BatchResults.NewFromProcedure(newBatchNr, (BenchInfo != null) ? BenchInfo.TestBenchId : 1, (BenchInfo != null) ? BenchInfo.TestBenchName : "testbench", (BenchInfo != null) ? BenchInfo.Address1 : string.Empty, (BenchInfo != null) ? BenchInfo.Address2 : string.Empty, (BenchInfo != null) ? BenchInfo.Address3 : string.Empty, (BenchInfo != null) ? BenchInfo.Address4 : string.Empty, (BenchInfo != null) ? BenchInfo.Address5 : string.Empty, (Users.GlobalData.CurrentUser != null) ? Users.GlobalData.CurrentUser.ToEncodedStr() : "none", (Users.GlobalData.CurrentUser != null) ? Users.GlobalData.CurrentUser.Number : 0, Program.Version, StateMachine.Procedure, waterMeterData, waterMeterParts, Config.Formulas.RealDensity(), Config.Formulas.AtTemperature(), Config.Formulas.Buoyancy()); } /// /// Reload batch results from Results database given the batch number /// /// Original batch number /// New unique batch number /// Reloaded procedure /// void RestoreBatchResults(int oriBatchNr, ref Results.BatchResults batchResults) { Batch oriBatch = Results.DB.LoadBatch(oriBatchNr); if (oriBatch == null) return; batchResults.Batch.StartTime = oriBatch.StartTime.AddMinutes(1); batchResults.Batch.TestBenchId = (BenchInfo != null) ? BenchInfo.TestBenchId : 1; batchResults.Batch.TestBenchName = (BenchInfo != null) ? BenchInfo.TestBenchName : "testbench"; foreach (var testRslt in batchResults.Batch.TestRslts) { foreach (var oriTstRslt in oriBatch.TestRslts) { if (testRslt.Name() == oriTstRslt.Name() && testRslt.Part == oriTstRslt.Part && testRslt.RepetitionNr == oriTstRslt.RepetitionNr) { testRslt.CopyContentFrom(oriTstRslt); break; } } } for (int i = 0; i < batchResults.Batch.WaterMeters.Count; i++) { WaterMeter wm = batchResults.Batch.WaterMeters[i]; wm.Disabled = true; foreach (var wm2 in oriBatch.WaterMeters) { if (wm.WMPosition == wm2.WMPosition) { wm.CopyContentFrom(wm2); wm.Disabled = false; #if ORACLE_DB wm.WaterMeterData.WMTypeId = wm2.WaterMeterData.WMTypeId; #endif break; } } } } void CollectSimultSteps() { /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with purging /// simultWithPurgingCount = 0; simultWithPurgingCfg = null; simultWithPurgingTests.Clear(); simultWithPurgingParams.Clear(); /// foreach (var ti in StateMachine.TestInstances) { Generic.IComponent testMethodComp = TbfComponents.FindComponent(ti.Test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.LoadTestParamsFromDB(ti.Test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; MetersPath sensPath = StateMachine.GetMetersPath(ti.Test); if (simultTest == null || !simultTest.SimultWithPrevious || sensPath == null) break; if (simultWithPurgingCount == 0) { simultWithPurgingCfg = simultTest.Cfg; } else if (simultTest.Cfg != simultWithPurgingCfg) { break; } simultWithPurgingTests.Add(ti.Test); simultWithPurgingParams.Add(testMethodComp.Cfg.GetRuntimeTestParamsProvider().Clone() as Generic.ITestParams); simultWithPurgingCount++; } /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with evacuation /// simultWithEvacuationCount = 0; simultWithEvacuationCfg = null; simultWithEvacuationTests.Clear(); simultWithEvacuationParams.Clear(); /// for (int i = StateMachine.TestInstances.Length - 1; i >= simultWithPurgingCount; i--) { var test = StateMachine.TestInstances[i].Test; Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.LoadTestParamsFromDB(test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; MetersPath sensPath = StateMachine.GetMetersPath(test); if (simultTest == null || !simultTest.SimultWithNext || sensPath == null) break; if (simultWithEvacuationCount == 0) { simultWithEvacuationCfg = simultTest.Cfg; } else if (simultTest.Cfg != simultWithEvacuationCfg) { break; } simultWithEvacuationTests.Insert(0, test); simultWithEvacuationParams.Insert(0, testMethodComp.Cfg.GetRuntimeTestParamsProvider().Clone() as Generic.ITestParams); simultWithEvacuationCount++; } } /// /// Executes steps of a evacuation sequence /// /// /// Event.Done Transition sequence completed OK /// Event.UiCmdStop Transition sequence interrupted by the STOP on-screen button /// Event.Error Error (e.g. RegulValveTimeOut returned by Run() of SetRegulValvePositionOp) /// Event DoEvacuation(TransitionSequence purgeEnd) { IList e; if (simultWithEvacuationCount > 0) { /// Open iPerlCommunicationForm ProcessData.RegisterReaders = StateMachine.GetMetersPath(simultWithEvacuationTests[0]).RegisterReaders; Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithEvacuationCfg, simultWithEvacuationTests, simultWithEvacuationParams }); } //-------------------------------------------------------- benchFilled = false; /// because evacuation sequence started /// switch (Transition(purgeEnd, TransitionContext.PurgeEnd)) { case Event.Error: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); return Event.Error; case Event.UiCmdStop: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); return Event.UiCmdStop; default: break; } if (simultWithEvacuationCount > 0) { /// /// Wait until iPerl communications are completed /// bool completed = !(modelessDlg is IHasCompleted) || (modelessDlg as IHasCompleted).Completed; if (!completed) { State.Create("MainSeq : Wait until the entry form is closed") .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.UiCmdStop)) { CloseIPerlCommForm(); return Event.UiCmdStop; } completed = (modelessDlg as IHasCompleted).Completed; } while (!completed); } modelessDlg = null; } Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); return Event.Done; } } }