/// /// Copyright (c) 2013-2015 Sensus Metering Systems /// using System; using System.Collections.Generic; using log4net; using Config.Entities; using TBF.UiBridge; using TBF.BenchControl; using TBF.BenchControl.Operations; using TBF.BenchControl.GenericDevices; using TBF.Boxes; using TBF.Resources; namespace TBF.BenchControl.Sequences { public class MainSeq : SequenceBase { private static readonly ILog log = LogManager.GetLogger(typeof(MainSeq)); public override string ToString() { return "Sequences.MainSeq"; } System.Windows.Forms.Form modelessDlg; /// delegate void iPerlCommFormDlgt(MainSeq myRef, Generic.IComponentCfg cfg, IList testNames, IList multiTestParams); /// void OpenIPerlCommForm(MainSeq myRef, Generic.IComponentCfg cfg, IList testNames, IList multiTestParams) { try { /// 1st argument IList wMtrs = new List(); foreach (var rr in sensPath.RegisterReaders) { if (rr is GenericDevices.IWaterMeter) wMtrs.Add(rr as GenericDevices.IWaterMeter); } /// 2nd argument TestMethods.iPerlCommunication.TestMethodCfg iPerlCfg = cfg as TestMethods.iPerlCommunication.TestMethodCfg; /// 3rd argument: as is /// 4th argument IList iPerlCommParams = new List(); foreach (var tp in multiTestParams) iPerlCommParams.Add(tp as TestMethods.iPerlCommunication.iPerlCommunicationParams); myRef.modelessDlg = new TestMethods.iPerlCommunication.iPerlCommunicationForm(wMtrs, iPerlCfg, testNames, iPerlCommParams); myRef.modelessDlg.Show(); } catch (Exception e) { log.FatalFormat("---------------( MainSeq : OpenIperlCommForm crashed !!! )---------------"); log.FatalFormat("Message : {0}", e.Message); if (e.InnerException != null) { log.FatalFormat("InnerMessage : {0}", e.InnerException.Message); } log.FatalFormat("StackTrace : {0}{1}", Environment.NewLine, e.StackTrace); log.Fatal("--------------------------------------"); } } void CloseIPerlCommForm() { UiBridge.Bridge.OnCloseModelessForm(this, null); modelessDlg = null; } /// Constructor public MainSeq() { } /// /// Main sequence /// /// /// public IList Execute(Test dummyArg) { /// Operations running in more then one state checkUiOp = new CheckUIOp(true); IList e; Selection selection; bool benchFilled = false; int simultWithPurgingCount = 0; Generic.IComponentCfg simultWithPurgingCfg = null; IList simultWithPurgingParams = new List(); int simultWithEvacuationCount = 0; Generic.IComponentCfg simultWithEvacuationCfg = null; IList simultWithEvacuationParams = new List(); StateMachine.LoadProcedure(true); // TODO: Implement as an operation so that the worker thread is not blocked Bridge.Bench2UI(ButtonsEtc.StopBtnEn); //-------------------------------------------------------------------------------------------- Bridge.OnActivity(this, Strings.Starting_system); State.Create("MainSeq : Setting valves to default positions") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (e.Contains(Event.ValvesBusy)); //-------------------------------------------------------------------------------------------- IntBox remainingTime = new IntBox(); State startNew = State.Create("MainSeq : Emptying tanks, Starting cameras") .AddOperation(checkUiOp); foreach (var cmpnt in StateMachine.Components) { Cameras.IdcCamera.IdcCamera camera = cmpnt as Cameras.IdcCamera.IdcCamera; if ((camera != null) && (camera.Cfg.DebugLevel != DebugMode.DetectedOff)) { startNew.AddOperation(camera.StartNewOp()); } } IList allEmptyingValves = new List(); if (StateMachine.EmptyTankValve1 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve1); if (StateMachine.EmptyTankValve2 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve2); if (StateMachine.EmptyTankValve3 != null) allEmptyingValves.Add(StateMachine.EmptyTankValve3); // Determine the tank emptying time (the maximum for all balances) int balanceEmptyTime = 0; if (StateMachine.Balance1 != null && StateMachine.Balance1.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance1.EmptyTimeSec; } if (StateMachine.Balance2 != null && StateMachine.Balance2.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance2.EmptyTimeSec; } if (StateMachine.Balance3 != null && StateMachine.Balance3.EmptyTimeSec > balanceEmptyTime) { balanceEmptyTime = StateMachine.Balance3.EmptyTimeSec; } if (balanceEmptyTime > 0) { startNew.AddOperation(new TimerOp(balanceEmptyTime, remainingTime)) .AddOperation(StateMachine.ControlBoard.SetValvesOp(allEmptyingValves, null)); } startNew.EnterState(); do { Bridge.OnActivity(this, string.Format("{0} ... {1} {2} {3} {4}", Strings.Emptying_tank, remainingTime.Val / 60, "min", remainingTime.Val % 60, Strings.sec)); e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop) && !e.Contains(Event.ValvesBusy) && !e.Contains(Event.CameraBusy)) { goto stop_emptying; } } while (e.Contains(Event.TimerBusy) || e.Contains(Event.CameraBusy) || e.Contains(Event.ValvesBusy)); if (e.Contains(Event.CameraOpFailed)) goto error; /// TODO: resolve in some other way Bridge.OnActivity(this, Strings.Emptying_tank); stop_emptying: //-------------------------------------------------------------------------------------------- State stopEmptying = State.Create("MainSeq : Stop emptying of water tanks") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, allEmptyingValves)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.ValvesBusy)); //-------------------------------------------------------------------------------------------- State taraAll = State.Create("MainSeq : Reset all balances").AddOperation(checkUiOp); FloatBox tara = new FloatBox(0); if (StateMachine.Balance1 != null) taraAll.AddOperation(StateMachine.Balance1.TaringOp(ref tara)); if (StateMachine.Balance2 != null) taraAll.AddOperation(StateMachine.Balance2.TaringOp(ref tara)); if (StateMachine.Balance3 != null) taraAll.AddOperation(StateMachine.Balance3.TaringOp(ref tara)); taraAll.EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.Busy)); //-------------------------------------------------------------------------------------------- Bridge.OnActivity(this, Strings.Measuring_the_weight); State.Create("MainSeq : Mesuring the weight for the 1st time") .AddOperation(checkUiOp) .AddOperation(new MettlerToledo.ReadMassesOp()) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (!e.Contains(Event.BalanceDone)); //-------------------------------------------------------------------------------------------- select_procedure: /// Make sure the CycleBeginForm is closed (aftrer an abnormal procedure/test end, etc.) CloseBeginForm(); selection = MakeSelection(MKSelContext.ProcedureNotSelected); //-------------------------------- Bridge.Bench2UI(ButtonsEtc.StopBtnEn); StateMachine.LoadProcedure(false); if (StateMachine.Procedure == null) goto select_procedure; /// /// Procedure selected at this point, a new batch was started /// /// Prepare new water meters bool compound = (StateMachine.Procedure.MetersKind == MetersKind.Combined); int nrWMs = Math.Min(WaterMeters.Count, compound ? Config.Data.CompoundWMsCount : Config.Data.WMsCount); /// Results.Entities.WaterMeterData[] waterMeterData = new Results.Entities.WaterMeterData[nrWMs]; /// int[] waterMeterParts = new int[nrWMs]; for (int i = 0; i < nrWMs; i++) { waterMeterParts[i] = Utils.PartNr(i + 1, compound); waterMeterData[i] = new Results.Entities.WaterMeterData() { ProductName = StateMachine.Procedure.Name, Producer = WaterMeters[i].Producer, MetrologicalClass = WaterMeters[i].MetrologicalClass, ApprovalInfo = WaterMeters[i].ApprovalInfo, Qn = WaterMeters[i].Qn, Compound = compound, }; } /// Prepare empty results BatchRslts = Results.BatchResults.NewFromProcedure(Program.LocalSettings.BatchNr, BenchInfo.TestBenchId, User.CurrentUser.Name, Program.Version, StateMachine.Procedure, waterMeterData, waterMeterParts); StateMachine.CycleStartTimeStamp = BatchRslts.Batch.StartTime; foreach (var wm in WaterMeters) wm.ClearData(); /// Clean water meter data StateMachine.LoadProcedureParams(StateMachine.Procedure); Bridge.OnProcedureSelected(this, new ProcedureSelectedEventArgs(StateMachine.Procedure)); /// Display 'Cycle Begin Form' if (OpenCycleBeginForm()) goto stop; /// Find purge suquences TransitionSequence purgeBegin = null; TransitionSequence purgeEnd = null; foreach (var transition in StateMachine.TransitionSequences) { if (transition.Name == StateMachine.Procedure.TransitionStart) purgeBegin = transition; if (transition.Name == StateMachine.Procedure.TransitionEnd) purgeEnd = transition; } if (selection == Selection.Q1 || selection == Selection.Q2 || selection == Selection.Q3 || selection == Selection.Test) { goto assume_bench_filled; } else if (selection == Selection.Cycle && benchFilled) { //-------------------------------- State.Create("MainSeq : Answer a question") .AddOperation(new Operations.AskYesNoOp(Strings.Fill_with_water)) .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.No)) goto assume_bench_filled; if (e.Contains(Event.UiCmdStop)) goto select_procedure; } while (!e.Contains(Event.Yes)); } fill_the_bench: /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with purging /// simultWithPurgingCount = 0; simultWithPurgingCfg = null; simultWithPurgingParams.Clear(); /// foreach (var test in StateMachine.Tests) { Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.UpdateTestParams(test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; if (simultTest == null || !simultTest.SimultWithPrevious) break; if (simultWithPurgingCount == 0) { simultWithPurgingCfg = simultTest.Cfg; sensPath = StateMachine.GetMetersPath(test); } else if (simultTest.Cfg != simultWithPurgingCfg) { break; } simultWithPurgingParams.Add(testMethodComp.Cfg.GetTestParams().Clone() as Generic.ITestParams); simultWithPurgingCount++; } /// /// Collect steps (e.g. iPerl communication) to be done simultaneously with evacuation /// simultWithEvacuationCount = 0; simultWithEvacuationCfg = null; simultWithEvacuationParams.Clear(); /// for (int i = StateMachine.Tests.Count - 1; i >= simultWithPurgingCount; i--) { var test = StateMachine.Tests[i]; Generic.IComponent testMethodComp = TbfComponents.FindComponent(test.Method); if (testMethodComp == null) break; testMethodComp.Cfg.UpdateTestParams(test); ISimultTestMethod simultTest = testMethodComp as ISimultTestMethod; if (simultTest == null || !simultTest.SimultWithNext) break; if (simultWithEvacuationCount == 0) { simultWithEvacuationCfg = simultTest.Cfg; sensPath = StateMachine.GetMetersPath(test); } else if (simultTest.Cfg != simultWithEvacuationCfg) { break; } simultWithEvacuationParams.Insert(0, testMethodComp.Cfg.GetTestParams().Clone() as Generic.ITestParams); simultWithEvacuationCount++; } /// if (simultWithPurgingCount > 0) { /// Make sure the entry form is closed if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop; /// Open iPerlCommunicationForm Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithPurgingCfg, simultWithPurgingParams }); } /// /// Purging @ cycle start /// Event evt = Transition(purgeBegin, TransitionContext.PurgeBegin); /// switch (evt) { case Event.Error: if (simultWithPurgingCount > 0) CloseIPerlCommForm(); goto error; case Event.UiCmdStop: if (simultWithPurgingCount > 0) CloseIPerlCommForm(); goto stop; default: break; } if (simultWithPurgingCount > 0) { /// /// Wait until iPerl communications are completed /// bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.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(); goto stop; } completed = (modelessDlg as GenericDevices.IHasCompleted).Completed; } while (!completed); } modelessDlg = null; } assume_bench_filled: benchFilled = true; Bridge.Bench2UI(ButtonsEtc.ShowBenchFilled); if (selection != Selection.PurgeBegin) { goto cycle_or_test_selected; } select_cycle_or_test: //---------------------------------------------------------- selection = MakeSelection(MKSelContext.InsideProcedure); /// if (selection == Selection.PurgeBegin) goto fill_the_bench; if (selection == Selection.PurgeEnd) goto evacuation; if (selection == Selection.Break) { Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); goto select_procedure; } if (selection == Selection.SaveResults) goto save_results; cycle_or_test_selected: UiBridge.Bridge.OnError(this, string.Empty); /// Clear an error message (if any) if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop_within_cycle; /// Make sure the entry form is closed Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide buttons if (selection == Selection.Cycle) { TimeEstimateTotal = 0; for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count - simultWithEvacuationCount; i++) { Test test = StateMachine.Tests[i]; TimeEstimateTotal += (test.Repeats * (test.TstTime + 10.0f)); /// Try to fetch all test paths and transitions /// to detect configuration errors as early as possible. string errorMsg; if (!StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } } TimeEstimateBeginRpts = 0; for (int i = simultWithPurgingCount; i < StateMachine.Tests.Count - simultWithEvacuationCount; i++) { Test test = StateMachine.Tests[i]; /// Fetch the test paths and transitions string errorMsg; if (!StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } /// Update format for the water mass Mass.Format = outPath.Balance.Format; startMass.Format = outPath.Balance.Format; endMass.Format = outPath.Balance.Format; TimeEstimateOneTest = test.TstTime + 10.0f; //-------------------------------------------------------------- ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind)) { StateMachine.LoadTestParams(test); if (BenchInfo != null && sensPath.RegisterReaders != null) { foreach (var rr in sensPath.RegisterReaders) if (rr is WaterMeters.iPerl.WaterMeter) (rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchName; } e = testMethodSequence.Execute(test); if (e.Contains(Event.ConfigurationError)) goto select_cycle_or_test; if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.OpArgumentError)) goto config_error; if (e.Contains(Event.UiCmdStop)) goto stop_within_cycle; } else { UiBridge.Bridge.OnError(this, string.Format("{0} cannot be used", test.Method)); goto select_cycle_or_test; } TimeEstimateBeginRpts += (test.Repeats * TimeEstimateOneTest); } } else { Test test = TBF.BenchControl.StateMachine.GetTest(selection); if (test == null) { UiBridge.Bridge.OnError(this, string.Format("No test specified")); goto select_cycle_or_test; } /// Fetch the test paths and transitions string errorMsg; if (!StateMachine.GetPaths(test, out inPath, out benchPath, out outPath, out sensPath, out transitionBefore, out transitionAfter, out errorMsg)) { UiBridge.Bridge.OnError(this, errorMsg); goto select_cycle_or_test; } /// Update format for the water mass Mass.Format = outPath.Balance.Format; startMass.Format = outPath.Balance.Format; endMass.Format = outPath.Balance.Format; TimeEstimateTotal = test.Repeats * (test.TstTime + 10.0f); TimeEstimateOneTest = test.TstTime + 10.0f; TimeEstimateBeginRpts = 0; ITestMethod testMethodSequence = TbfComponents.FindComponent(test.Method) as ITestMethod; if (testMethodSequence != null && testMethodSequence.CanTest(StateMachine.Procedure.MetersKind)) { StateMachine.LoadTestParams(test); if (BenchInfo != null && sensPath.RegisterReaders != null) { foreach (var rr in sensPath.RegisterReaders) if (rr is WaterMeters.iPerl.WaterMeter) (rr as WaterMeters.iPerl.WaterMeter).BenchName = BenchInfo.TestBenchName; } e = testMethodSequence.Execute(test); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.OpArgumentError)) goto config_error; if (e.Contains(Event.UiCmdStop)) goto stop_within_cycle; } else { UiBridge.Bridge.OnError(this, string.Format("{0} cannot be used", test.Method)); goto select_cycle_or_test; } } if (BatchRslts.AllTestsDone()) { Bridge.Bench2UI(ButtonsEtc.AcceptResultsBtnEn | ButtonsEtc.ResetResultsBtnEn); } else { Bridge.Bench2UI(ButtonsEtc.ResetResultsBtnEn); } goto select_cycle_or_test; evacuation: save_results: UiBridge.Bridge.OnError(this, string.Empty); /// Clear an error message (if any) Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Hide the most of buttons if (State.LastEvents.Contains(Event.ModelessFormIsOpen)) { if (UIFlowControl.Stop == WaitBeginFormClosed()) goto stop; } else if (State.LastEvents.Contains(Event.ModelessFormClosed)) { CloseBeginForm(); } Bridge.OnActivity(this, "Enter protocol data"); //-------------------------------- string protocolTitle = string.Empty; GenericDevices.IDataEntry dataEntryCmpnt = TbfComponents.FindComponent(StateMachine.Procedure.DataEntry) as GenericDevices.IDataEntry; if (dataEntryCmpnt != null) { if (dataEntryCmpnt is IHasCycleEndForm) { /// Open the modeless form for the end of the cycle State.Create("MainSeq : Enter end data") .AddOperation((dataEntryCmpnt as GenericDevices.IHasCycleEndForm).ShowCycleEndFormOp(WaterMeters)) .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.UiCmdStop)) goto stop; } while (!e.Contains(Event.ModelessFormClosed)); } if (dataEntryCmpnt is IHasProtocolTitle) { protocolTitle = (dataEntryCmpnt as IHasProtocolTitle).ProtocolTitle; } dataEntryCmpnt.UpdateTestResults(WaterMeters, results); } //------------------------------------------------------ Bridge.OnActivity(this, "Saving and printing results"); IResultsWriter writer = TbfComponents.FindComponent(StateMachine.Procedure.ResultsWriter) as IResultsWriter; IResultsPrinter printer = TbfComponents.FindComponent(StateMachine.Procedure.ResultsPrinter) as IResultsPrinter; State savingAndPrintingRslts = State.Create("MainSeq : Saving and printing results"); if (writer != null) { savingAndPrintingRslts.AddOperation(writer.WriteResultsOp((BenchInfo != null) ? BenchInfo.TestBenchName : string.Empty, StateMachine.Procedure, WaterMeters, results)); } if (printer != null && !printer.SupressPrinting) { savingAndPrintingRslts.AddOperation(printer.PrintResultsOp(BenchInfo, WaterMeters, StateMachine.Procedure, results, protocolTitle)); } savingAndPrintingRslts.AddOperation(checkUiOp).EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto stop; } while (e.Contains(Event.Busy)); /// TODO: Reimplement !!!!!!!!!!! ///// ///// Save to database and to 'summary results' logger ///// //IList sortedResults = Utils.GetSortedTestResults(StateMachine.Procedure, results, 0); //foreach (var rslt in sortedResults) //{ // if (rslt != null) // { // Config.FluentCommon.SaveToDb(StateMachine.WtSession, rslt); // summaryResults.Info(TestResult2CsvLine(rslt)); // } //} Program.LocalSettings.BatchNr++; Program.LocalSettings.Save(); if (simultWithEvacuationCount > 0) { /// Open iPerlCommunicationForm Program.MainWnd.Invoke(new iPerlCommFormDlgt(OpenIPerlCommForm), new object[] { this, simultWithEvacuationCfg, simultWithEvacuationParams }); } //-------------------------------------------------------- switch (Transition(purgeEnd, TransitionContext.PurgeEnd)) { case Event.Error: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); goto error; case Event.UiCmdStop: if (simultWithEvacuationCount > 0) CloseIPerlCommForm(); goto stop; default: break; } if (simultWithEvacuationCount > 0) { /// /// Wait until iPerl communications are completed /// bool completed = !(modelessDlg is GenericDevices.IHasCompleted) || (modelessDlg as GenericDevices.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(); goto stop; } completed = (modelessDlg as GenericDevices.IHasCompleted).Completed; } while (!completed); } modelessDlg = null; } benchFilled = false; Bridge.Bench2UI(ButtonsEtc.ShowBenchEmpty); goto select_procedure; stop_within_cycle: //-------------------------------- State.Create("MainSeq : Turning IDLE -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; } while (!e.Contains(Event.ValvesSet)); goto select_cycle_or_test; stop: //-------------------------------- State.Create("MainSeq : Turning IDLE -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; } while (!e.Contains(Event.ValvesSet)); goto select_procedure; config_error: //-------------------------------- State.Create("MainSeq : Procedure configuration error") .AddOperation(checkUiOp) .AddOperation(new Operations.MessageBoxOp("Test configration error")) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.OK)); goto select_cycle_or_test; error: //-------------------------------- State.Create("MainSeq : ERROR -> Closing the valves") .AddOperation(checkUiOp) .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.DefaultValvesOpen, StateMachine.DefaultValvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet) && !e.Contains(Event.Error)); //-------------------------------- State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } /// /// MakeSelection() call context /// enum MKSelContext { ProcedureNotSelected, InsideProcedure, } /// /// Selection done in MakeSelection() /// public enum Selection { /// Handled inside MakeSelection() None, EmptyTank1, EmptyTank2, EmptyTank3, CloseTank1, CloseTank2, CloseTank3, CameraTest, /// Used as return values Cycle, Test, Q1, Q2, Q3, Stop, PurgeBegin, PurgeEnd, Break, SaveResults, } /// /// Idle loop to make a procedure or test selection. /// Handles tank emptying, camera test. /// /// Context where MakeSelection() is called /// /// Selection.Cycle /// Selection.Test /// Selection.Q1 /// Selection.Q2 /// Selection.Q3 /// Selection.Stop /// Selection.PurgeBegin /// Selection.PurgeEnd /// private Selection MakeSelection(MKSelContext context) { /// Tank emptying valves states bool emptying1 = false; bool emptying2 = false; bool emptying3 = false; /// Measured masses to control emptying FloatBox mass1 = new FloatBox(); FloatBox mass2 = new FloatBox(); FloatBox mass3 = new FloatBox(); IList e; Selection selection; while (true) { /// Display an appropriate activity message if (emptying1 || emptying2 || emptying3) { Bridge.OnActivity(this, Strings.Emptying_tank); } else if (context == MKSelContext.ProcedureNotSelected) { Bridge.OnActivity(this, Strings.Please_select_a_procedure); } else if (context == MKSelContext.InsideProcedure) { Bridge.OnActivity(this, Strings.Please_select_a_cycle_a_test_or_empty); } /// Enable appropriate UI controls and buttons Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | ((emptying1 || emptying2 || emptying3) ? 0 : (ButtonsEtc.StartCycleBtnEn | ButtonsEtc.StartTestBtnsEn | ButtonsEtc.PurgeBeginBtnEn | ((context == MKSelContext.InsideProcedure) ? ButtonsEtc.PurgeEndBtnEn : 0) | ButtonsEtc.SensitivityTestBtnEn | ((Cameras.Count > 0) ? ButtonsEtc.CalibrationBtnEn : 0) | ButtonsEtc.Break)) | (((StateMachine.Balance1 != null) && (StateMachine.EmptyTankValve1 != null) && !emptying1) ? ButtonsEtc.EmptyTankBtn1En : 0) | (((StateMachine.Balance2 != null) && (StateMachine.EmptyTankValve2 != null) && !emptying2) ? ButtonsEtc.EmptyTankBtn2En : 0) | (((StateMachine.Balance3 != null) && (StateMachine.EmptyTankValve3 != null) && !emptying3) ? ButtonsEtc.EmptyTankBtn3En : 0)); selection = Selection.None; State.Create("MainSeq : Select an activity") .AddOperation(checkUiOp) .AddOperation((StateMachine.Balance1 != null) ? StateMachine.Balance1.ReadMassOp(ref mass1) : null) .AddOperation((StateMachine.Balance2 != null) ? StateMachine.Balance2.ReadMassOp(ref mass2) : null) .AddOperation((StateMachine.Balance3 != null) ? StateMachine.Balance3.ReadMassOp(ref mass3) : null) .AddOperation(StateMachine.ControlBoard.UpdateTankWeightOp()) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; else if (e.Contains(Event.UiCmdStop)) selection = Selection.Stop; else if (e.Contains(Event.UiCmdCameraTest)) selection = Selection.CameraTest; else if (e.Contains(Event.UiCmdEmptyTank1)) selection = Selection.EmptyTank1; else if (e.Contains(Event.UiCmdEmptyTank2)) selection = Selection.EmptyTank2; else if (e.Contains(Event.UiCmdEmptyTank3)) selection = Selection.EmptyTank3; else if (emptying1 && StateMachine.Balance1.IsEmpty(mass1.Val)) selection = Selection.CloseTank1; else if (emptying2 && StateMachine.Balance2.IsEmpty(mass2.Val)) selection = Selection.CloseTank2; else if (emptying3 && StateMachine.Balance3.IsEmpty(mass3.Val)) selection = Selection.CloseTank3; else if (e.Contains(Event.UiCmdPurgeBegin)) return Selection.PurgeBegin; /// Value used to branch the code later on else if (e.Contains(Event.UiCmdPurgeEnd)) return Selection.PurgeEnd; else if (e.Contains(Event.UiCmdBreak) && context == MKSelContext.InsideProcedure) return Selection.Break; else if (e.Contains(Event.UiCmdStartTest)) return Selection.Test; else if (e.Contains(Event.UiCmdStartQ1)) return Selection.Q1; else if (e.Contains(Event.UiCmdStartQ2)) return Selection.Q2; else if (e.Contains(Event.UiCmdStartQ3)) return Selection.Q3; else if (e.Contains(Event.UiCmdStartCycle)) return Selection.Cycle; else if (e.Contains(Event.UiCmdAcceptResults)) return Selection.SaveResults; } while (selection == Selection.None); if (selection == Selection.CameraTest) { CameraTest(); } else if (selection == Selection.Stop) { if (emptying1 || emptying2 || emptying3) { IList valvesClose = new List(); if (emptying1) valvesClose.Add(StateMachine.EmptyTankValve1); if (emptying2) valvesClose.Add(StateMachine.EmptyTankValve2); if (emptying3) valvesClose.Add(StateMachine.EmptyTankValve3); State.Create("MainSeq : Close emptying valve(s)") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, valvesClose)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying1 = emptying2 = emptying3 = false; } selection = Selection.None; } else if ((selection == Selection.EmptyTank1) && !emptying1) { emptying1 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying2 ? 0 : ButtonsEtc.EmptyTankBtn2En) | (emptying3 ? 0 : ButtonsEtc.EmptyTankBtn3En)); State.Create("MainSeq : Open tank 1") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve1, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if ((selection == Selection.EmptyTank2) && !emptying2) { emptying2 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying1 ? 0 : ButtonsEtc.EmptyTankBtn1En) | (emptying3 ? 0 : ButtonsEtc.EmptyTankBtn3En)); State.Create("MainSeq : Open tank 2") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve2, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if ((selection == Selection.EmptyTank3) && !emptying3) { emptying3 = true; Bridge.OnActivity(this, Strings.Emptying_tank); Bridge.Bench2UI(((context == MKSelContext.ProcedureNotSelected) ? ButtonsEtc.ProcedureCmbBoxEn : 0) | ButtonsEtc.TestCmbBoxEn | ButtonsEtc.StopBtnEn | (emptying1 ? 0 : ButtonsEtc.EmptyTankBtn1En) | (emptying2 ? 0 : ButtonsEtc.EmptyTankBtn2En)); State.Create("MainSeq : Open tank 3") .AddOperation(StateMachine.ControlBoard.SetValvesOp(StateMachine.EmptyTankValve3, null)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); } else if (selection == Selection.CloseTank1) { State.Create("MainSeq : Close tank 1") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve1)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying1 = false; } else if (selection == Selection.CloseTank2) { State.Create("MainSeq : Close tank 2") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve2)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying2 = false; } else if (selection == Selection.CloseTank3) { State.Create("MainSeq : Close tank 3") .AddOperation(StateMachine.ControlBoard.SetValvesOp(null, StateMachine.EmptyTankValve3)) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); } while (!e.Contains(Event.ValvesSet)); emptying3 = false; } } error: Bridge.OnActivity(this, Strings.Error); State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } /// /// Perform a camera test /// void CameraTest() { IList e; camera_test: Bridge.OnActivity(this, "Camera test"); //--------------------------------------------------------- Bridge.Bench2UI(ButtonsEtc.StartTestBtnsEn | ButtonsEtc.StopBtnEn); State.Create("MainSeq : 1 = Grab, 2 = Live, 3 = Focus, Stop = Quit camera test") .AddOperation(checkUiOp) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) return; if (e.Contains(Event.UiCmdStartQ1)) goto grab; if (e.Contains(Event.UiCmdStartQ2)) goto live; if (e.Contains(Event.UiCmdStartQ3)) goto focus; } while (true); grab: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to continue") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].GrabOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].GrabOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].GrabOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].GrabOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].GrabOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].GrabOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); live: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to stop.") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].LiveOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].LiveOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].LiveOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].LiveOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].LiveOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].LiveOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); focus: Bridge.Bench2UI(ButtonsEtc.StopBtnEn); State.Create("MainSeq : Press 'Stop' to stop.") .AddOperation(checkUiOp) .AddOperation((Cameras.Count > 0 && Cameras[0] != null && (Cameras[0].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[0].FocusOp() : null) .AddOperation((Cameras.Count > 1 && Cameras[1] != null && (Cameras[1].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[1].FocusOp() : null) .AddOperation((Cameras.Count > 2 && Cameras[2] != null && (Cameras[2].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[2].FocusOp() : null) .AddOperation((Cameras.Count > 3 && Cameras[3] != null && (Cameras[3].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[3].FocusOp() : null) .AddOperation((Cameras.Count > 4 && Cameras[4] != null && (Cameras[4].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[4].FocusOp() : null) .AddOperation((Cameras.Count > 5 && Cameras[5] != null && (Cameras[5].Cfg.DebugLevel != DebugMode.DetectedOff)) ? Cameras[5].FocusOp() : null) .EnterState(); do { e = StateMachine.WaitRunDevsRunOps(); if (e.Contains(Event.Error)) goto error; if (e.Contains(Event.UiCmdStop)) goto camera_test; } while (true); error: Bridge.OnActivity(this, Strings.Error); State.Create("MainSeq : ERROR state") .EnterState(); while (true) StateMachine.WaitRunDevsRunOps(); } } }