From 771af696ae38c4ef5ca6733c818cdf9906eb8d58 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 4 Mar 2019 13:14:13 +0100 Subject: [PATCH] (1) TBF program shutdown modifications, (2) Obligatory tank draining before TBF exit, (3) Shutdown PC after TBF exit option, ver. 2.18.1156 --- TBF/BenchControl/Sequences/MainSeq.cs | 127 +++++++++- TBF/BenchControl/StateMachine.cs | 121 +++++---- TBF/Forms/ClosingTbfForm.Designer.cs | 100 ++++++++ TBF/Forms/ClosingTbfForm.cs | 28 +++ TBF/Forms/ClosingTbfForm.resx | 120 +++++++++ TBF/MainWnd.cs | 346 ++++++++++++-------------- TBF/MainWnd.cs.resx | 222 ++++++++--------- TBF/Properties/AssemblyInfo.cs | 6 +- TBF/Resources/Strings.Designer.cs | 20 +- TBF/Resources/Strings.cs.resx | 8 +- TBF/Resources/Strings.de.resx | 3 + TBF/Resources/Strings.pl.resx | 3 + TBF/Resources/Strings.resx | 8 +- TBF/TBF.csproj | 9 + TBF/UiBridge/Enums.cs | 52 ++-- 15 files changed, 773 insertions(+), 400 deletions(-) create mode 100644 TBF/Forms/ClosingTbfForm.Designer.cs create mode 100644 TBF/Forms/ClosingTbfForm.cs create mode 100644 TBF/Forms/ClosingTbfForm.resx diff --git a/TBF/BenchControl/Sequences/MainSeq.cs b/TBF/BenchControl/Sequences/MainSeq.cs index e5a7f95df..1dac9ea5c 100644 --- a/TBF/BenchControl/Sequences/MainSeq.cs +++ b/TBF/BenchControl/Sequences/MainSeq.cs @@ -14,6 +14,7 @@ using TBF.BenchControl.Operations; using TBF.BenchControl.GenericDevices; using TBF.Boxes; using TBF.Resources; +using System.Threading; namespace TBF.BenchControl.Sequences { @@ -228,7 +229,7 @@ namespace TBF.BenchControl.Sequences /// /// /// - public IList Execute(Test dummyArg) + public void Execute() { IList e; Selection selection; @@ -347,7 +348,7 @@ namespace TBF.BenchControl.Sequences //-------------------------------------------------------------------------------------------- Bridge.OnActivity(this, Strings.Resetting_scales); //-------------------------------------------------------------------------------------------- - Bridge.Bench2UI(ButtonsEtc.StopBtnEn); + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Resetting scales : Enable STOP button DoubleBox tara1 = new DoubleBox(0); DoubleBox tara2 = new DoubleBox(0); @@ -387,7 +388,17 @@ namespace TBF.BenchControl.Sequences do { - selection = MakeSelection(MKSelContext.ProcedureNotSelected); + do + { + selection = MakeSelection(MKSelContext.ProcedureNotSelected); + if (selection == Selection.Shutdown) + { + Shutdown(); + return; + } + } + while (selection == Selection.Shutdown); + switch (selection) { case Selection.Q1: selectedTestName = "Q1"; break; @@ -446,7 +457,7 @@ namespace TBF.BenchControl.Sequences /// StateMachine.ControlBoard.ManualUIAllowed = !StateMachine.Procedure.ManualCtrlDisabled; - Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// Enable STOP button + Bridge.Bench2UI(ButtonsEtc.StopBtnEn); /// A new cycle started : Enable STOP button int newBatchNr = Program.LocalSettings.BatchNr; log.FatalFormat("New measurement session started: batch = {0}, procedure = {1}", newBatchNr, StateMachine.Procedure.Name); @@ -1272,9 +1283,17 @@ namespace TBF.BenchControl.Sequences //-------------------------------- State.Create("MainSeq : ERROR state") + .AddOperation(checkUiOp) .AddOperation(StateMachine.BenchErrorOp) .EnterState(); - while (true) StateMachine.WaitRunDevsRunOps(); + do + { + e = StateMachine.WaitRunDevsRunOps(); + } + while (!e.Contains(Event.UiCmdShutdown)); + + Shutdown(true); + return; } @@ -1315,7 +1334,7 @@ namespace TBF.BenchControl.Sequences /// /// Selection.PurgeBegin, PurgeEnd, Break, Cycle, Test, Q1, Q2, Q3 or SaveResults /// - private Selection MakeSelection(MKSelContext context) + Selection MakeSelection(MKSelContext context) { log.WarnFormat("MakeSelection({0})", context); @@ -1384,7 +1403,8 @@ namespace TBF.BenchControl.Sequences if (draining3 && StateMachine.Tank3.IsEmpty()) break; /// Quit the selection loop and leave MakeSelection() - if (e.Contains(Event.UiCmdBreak) && context == MKSelContext.InsideProcedure) return Selection.Break; + if (e.Contains(Event.UiCmdShutdown) && (context == MKSelContext.ProcedureNotSelected)) return Selection.Shutdown; + if (e.Contains(Event.UiCmdBreak) && (context == MKSelContext.InsideProcedure)) 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; @@ -1404,9 +1424,16 @@ namespace TBF.BenchControl.Sequences Bridge.OnActivity(this, Strings.Error); ///------------------------------------ State.Create("MainSeq : ERROR state") + .AddOperation(checkUiOp) .AddOperation(StateMachine.BenchErrorOp) .EnterState(); - while (true) StateMachine.WaitRunDevsRunOps(); /// Endless loop + do + { + e = StateMachine.WaitRunDevsRunOps(); + } + while (!e.Contains(Event.UiCmdShutdown)); + + return Selection.Shutdown; } else { @@ -1471,6 +1498,90 @@ namespace TBF.BenchControl.Sequences } } + 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); + bool draining2 = (StateMachine.DrainValve2 != null); + bool draining3 = (StateMachine.DrainValve3 != 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.IsEmpty()) draining1 = false; + if (draining2 && StateMachine.Tank2.IsEmpty()) draining2 = false; + if (draining3 && 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 diff --git a/TBF/BenchControl/StateMachine.cs b/TBF/BenchControl/StateMachine.cs index 80a7b3cf3..f1e8a66f7 100644 --- a/TBF/BenchControl/StateMachine.cs +++ b/TBF/BenchControl/StateMachine.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2018 Sensus Slovensko a.s. +/// Copyright (c) 2013-2019 Sensus Slovensko a.s. /// using System; using System.Text; @@ -16,9 +16,17 @@ using TBF.Resources; namespace TBF.BenchControl { - public class QuitStateMachineException : Exception - { - } + public enum MachineState + { + Undefined = 0, + Disabled, + StartingUp, /// Start-up: Initialize() of all devices + start of the worker thread + FailedToStart, /// Most likely Initialize() of any device thrown an exception + Running, /// RunDeviceBefore() and RunDeviceAfter() of all devices, Start()/Run()/Stop() of operations + ShuttingDown, /// Shutdown: StopDevice() and StopDevice2() of all devices + Off, /// Off after the shutdown + } + /// /// This class controls real test bench behavior. @@ -67,11 +75,8 @@ namespace TBF.BenchControl static DateTime startDateTime; /// DateTime of time instance when the state machine worker thread starts static int currentTimeSec; /// Time from the start of the state machine in seconds - static bool quitStateMachine; /// flag to stop the worker thread - /// true when the state machine is running - static bool stateMachineRunning; - public static bool Running { get { return stateMachineRunning; } } + public static MachineState MachineState; /// see enum MachineState for explanation /// Worker thread and database session static Thread workerThread; @@ -136,9 +141,7 @@ namespace TBF.BenchControl { devices = new List(); states = new List(); - currentTimeSec = 0; - quitStateMachine = false; } /// @@ -504,13 +507,18 @@ namespace TBF.BenchControl /// public static void Start() { - if (stateMachineRunning) return; + if (MachineState != MachineState.StartingUp) + { + /// Unexpected MachineState (not MachineState.StartingUp) --> prevent worker thread from starting + /// + MachineState = MachineState.FailedToStart; + return; + } workerThread = new Thread(Worker); workerThread.CurrentCulture = Thread.CurrentThread.CurrentCulture; workerThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture; workerThread.Start(); - stateMachineRunning = true; } /// @@ -712,15 +720,6 @@ namespace TBF.BenchControl } - /// - /// Stops the state machine (and the worker thread) - /// - public static void Stop() - { - if (stateMachineRunning) quitStateMachine = true; - } - - /* * This is and example sequence of RunDeviceBefore() / RunOperations() / RunDeviceAfter() calls * as they are executed during normal run from the progran start to the end. @@ -757,32 +756,32 @@ namespace TBF.BenchControl /// static void Worker() { + MachineState = MachineState.Running; startDateTime = DateTime.Now; - CycleStartTimeStamp = startDateTime; /// To prevent it is undefined - + CycleStartTimeStamp = startDateTime; /// Do not leave CycleStartTimeStamp uninitialized wlog.InfoFormat(" currentTime = {0}s startDateTime = {1}", currentTimeSec.ToString(), startDateTime.ToString()); /// Run all devices for the first time foreach (var device in devices) device.RunDeviceBefore(); - try - { - SequenceBase.ReferenceFlowmetersCount = SequenceBase.FlowMeters.Count; - SequenceBase.CalibratedLtrPerRefPulse = new float[SequenceBase.ReferenceFlowmetersCount]; - foreach (var flowmtr in SequenceBase.FlowMeters) + SequenceBase.ReferenceFlowmetersCount = SequenceBase.FlowMeters.Count; + SequenceBase.CalibratedLtrPerRefPulse = new float[SequenceBase.ReferenceFlowmetersCount]; + foreach (var flowmtr in SequenceBase.FlowMeters) + { + int ix = flowmtr.Idx1; + if (ix > 0 && ix <= SequenceBase.ReferenceFlowmetersCount) { - int ix = flowmtr.Idx1; - if (ix > 0 && ix <= SequenceBase.ReferenceFlowmetersCount) - { - SequenceBase.CalibratedLtrPerRefPulse[ix - 1] = flowmtr.NominalFlow / 7200.0f; - } + SequenceBase.CalibratedLtrPerRefPulse[ix - 1] = flowmtr.NominalFlow / 7200.0f; } - - (new Sequences.MainSeq()).Execute(null); - } - catch (QuitStateMachineException) - { } + + /// + /// Run the main sequence + /// + (new Sequences.MainSeq()).Execute(); + + StateMachine.MachineState = MachineState.Off; /// Update StateMachine.MachineState + TBF.UiBridge.Bridge.Bench2UI(TBF.UiBridge.ButtonsEtc.Shutdown); /// Let UI know the state machine is shut down now } @@ -790,34 +789,35 @@ namespace TBF.BenchControl /// Do stuff that is repeated in the state execution loops most often /// /// List of Event-s returned from the state operations, null == quit - public static IList WaitRunDevsRunOps() + public static IList WaitRunDevsRunOps(bool lastTime = false) { Thread.Sleep(100); /// Insert 1/10 sec.delay between RunOperations() and RunDeviceAfter() - foreach (var device in devices) device.RunDeviceAfter(); + foreach (var device in devices) + { + device.RunDeviceAfter(); + } - if (WaitNextTick()) + WaitNextTick(); + + if (lastTime) { /// - /// Executed when the state machine is stopped + /// Executed when the state machine is being stopped /// - wlog.Fatal("quitStateMachine == true ... The last StopOperaions() start now"); State.StopOperations(); - stateMachineRunning = false; - wlog.Fatal("StopOperaions() completed ... stateMachineRunning = false)"); - - throw new QuitStateMachineException(); + return null; } - - foreach (var device in devices) device.RunDeviceBefore(); - Thread.Sleep(100); /// Insert 1/10 sec.delay between RunDeviceBefore() and RunOperations() + foreach (var device in devices) + { + device.RunDeviceBefore(); + } - IList events = State.RunOperations(); - return events; - /// - /// This is followed by a state change in the sequence - /// + Thread.Sleep(100); /// Insert 1/10 sec.delay between RunDeviceBefore() and RunOperations() + + return State.RunOperations(); /// Returns events from all running operations + /// This is followed by a state change in the sequence } @@ -825,20 +825,15 @@ namespace TBF.BenchControl /// Wait time period - synchronize /// /// true when interrupted by 'quitStateMachine', otherwise false - public static bool WaitNextTick() + public static void WaitNextTick() { currentTimeSec += Period; + DateTime nextTickDateTime = startDateTime + TimeSpan.FromSeconds(currentTimeSec); - TimeSpan timeFromStart = TimeSpan.FromSeconds(currentTimeSec); - DateTime nextLoopDateTime = startDateTime + timeFromStart; - - while (DateTime.Now < nextLoopDateTime) + while (DateTime.Now < nextTickDateTime) { Thread.Sleep(100); - if (quitStateMachine) return true; } - - return false; } } } diff --git a/TBF/Forms/ClosingTbfForm.Designer.cs b/TBF/Forms/ClosingTbfForm.Designer.cs new file mode 100644 index 000000000..7db9ee26c --- /dev/null +++ b/TBF/Forms/ClosingTbfForm.Designer.cs @@ -0,0 +1,100 @@ +namespace TBF.Forms +{ + partial class ClosingTbfForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.messageLabel = new System.Windows.Forms.Label(); + this.shutDownPCCheckBox = new System.Windows.Forms.CheckBox(); + this.yesButton = new System.Windows.Forms.Button(); + this.noButton = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // messageLabel + // + this.messageLabel.AutoSize = true; + this.messageLabel.Location = new System.Drawing.Point(39, 33); + this.messageLabel.Name = "messageLabel"; + this.messageLabel.Size = new System.Drawing.Size(220, 13); + this.messageLabel.TabIndex = 0; + this.messageLabel.Text = "Do you want to exit Test Bench Framework ?"; + // + // shutDownPCCheckBox + // + this.shutDownPCCheckBox.AutoSize = true; + this.shutDownPCCheckBox.Location = new System.Drawing.Point(42, 66); + this.shutDownPCCheckBox.Name = "shutDownPCCheckBox"; + this.shutDownPCCheckBox.Size = new System.Drawing.Size(294, 17); + this.shutDownPCCheckBox.TabIndex = 1; + this.shutDownPCCheckBox.Text = "Shut down computer after exiting Test Bench Framework"; + this.shutDownPCCheckBox.UseVisualStyleBackColor = true; + // + // yesButton + // + this.yesButton.DialogResult = System.Windows.Forms.DialogResult.Yes; + this.yesButton.Location = new System.Drawing.Point(104, 109); + this.yesButton.Name = "yesButton"; + this.yesButton.Size = new System.Drawing.Size(88, 32); + this.yesButton.TabIndex = 2; + this.yesButton.Text = "Yes"; + this.yesButton.UseVisualStyleBackColor = true; + this.yesButton.Click += new System.EventHandler(this.yesButton_Click); + // + // noButton + // + this.noButton.DialogResult = System.Windows.Forms.DialogResult.No; + this.noButton.Location = new System.Drawing.Point(212, 109); + this.noButton.Name = "noButton"; + this.noButton.Size = new System.Drawing.Size(88, 32); + this.noButton.TabIndex = 3; + this.noButton.Text = "No"; + this.noButton.UseVisualStyleBackColor = true; + // + // ClosingTbfForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(404, 153); + this.Controls.Add(this.noButton); + this.Controls.Add(this.yesButton); + this.Controls.Add(this.shutDownPCCheckBox); + this.Controls.Add(this.messageLabel); + this.Name = "ClosingTbfForm"; + this.Text = "Closing the program"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label messageLabel; + private System.Windows.Forms.CheckBox shutDownPCCheckBox; + private System.Windows.Forms.Button yesButton; + private System.Windows.Forms.Button noButton; + } +} \ No newline at end of file diff --git a/TBF/Forms/ClosingTbfForm.cs b/TBF/Forms/ClosingTbfForm.cs new file mode 100644 index 000000000..bbf484d4e --- /dev/null +++ b/TBF/Forms/ClosingTbfForm.cs @@ -0,0 +1,28 @@ +/// +/// Copyright (c) 2019 Sensus Slovensko a.s. +/// +using System; +using System.Windows.Forms; +using TBF.Resources; + +namespace TBF.Forms +{ + public partial class ClosingTbfForm : Form + { + public bool ShutDownPC; + + public ClosingTbfForm() + { + InitializeComponent(); + ShutDownPC = false; + Text = Strings.Closing_the_program; + messageLabel.Text = Strings.Do_you_want_to_exit_TBF; + shutDownPCCheckBox.Text = Strings.Shut_down_computer_after_exiting_TBF; + } + + private void yesButton_Click(object sender, EventArgs e) + { + ShutDownPC = shutDownPCCheckBox.Checked; + } + } +} diff --git a/TBF/Forms/ClosingTbfForm.resx b/TBF/Forms/ClosingTbfForm.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/TBF/Forms/ClosingTbfForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/TBF/MainWnd.cs b/TBF/MainWnd.cs index 98694f750..57170dc30 100644 --- a/TBF/MainWnd.cs +++ b/TBF/MainWnd.cs @@ -1,5 +1,5 @@ /// -/// Copyright (c) 2013-2018 Sensus Slovensko a.s. +/// Copyright (c) 2013-201 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; @@ -25,14 +25,19 @@ namespace TBF public UiControls.BenchControlPanel BenchControlPanel; public ProcedureInfo SelectedProcedure; public Procedure CurrentProcedure; - public bool CycleRunning; + public bool IsShutdownDisabled; + public bool IsShutdownPCAfterClosingTbf; /// /// This dialog is shown when emergency stop is activated /// TBF.Forms.EmergencyStopForm emergencyStopModelessDlg; - bool benchInitializationFailed; + /// + /// This dialog is shown when TBF program is shutting down + /// + TBF.Forms.ModelessActivityForm closingTbfMessageForm; + TestProgressControls testProgressControls; /// @@ -119,11 +124,12 @@ namespace TBF iPerlHeadsToolStripMenuItem.Visible = false; #endif - CycleRunning = true; + IsShutdownDisabled = true; + IsShutdownPCAfterClosingTbf = false; - benchInitializationFailed = false; + BenchControl.StateMachine.MachineState = Config.Data.CurrentBench.IsRealBench ? BenchControl.MachineState.StartingUp : BenchControl.MachineState.Disabled; /// - if (Config.Data.CurrentBench.IsRealBench) + if (BenchControl.StateMachine.MachineState == BenchControl.MachineState.StartingUp) { try { @@ -146,7 +152,7 @@ namespace TBF } catch (Exception exc) { - benchInitializationFailed = true; + BenchControl.StateMachine.MachineState = BenchControl.MachineState.FailedToStart; string errMsg; if (string.IsNullOrEmpty(BenchControl.TbfComponents.CurrentlyLoadedComponentName)) @@ -197,9 +203,8 @@ namespace TBF Left = (ls.MainWndLeft != 0) ? ls.MainWndLeft : 75; Top = (ls.MainWndTop != 0) ? ls.MainWndTop : 5; } - - if (Config.Data.CurrentBench.IsRealBench && !benchInitializationFailed) + if (TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.StartingUp) { var form = new TBF.Forms.ModelessActivityForm() { @@ -264,7 +269,7 @@ namespace TBF } catch (Exception exc) { - benchInitializationFailed = true; + TBF.BenchControl.StateMachine.MachineState = TBF.BenchControl.MachineState.FailedToStart; form.CloseForm(null, new EventArgs()); formThread.Join(); @@ -320,21 +325,18 @@ namespace TBF UpdateUser(); mainTabControl.SelectTab((int)MainTabPageId.Hydraulics); - if (Config.Data.CurrentBench.IsRealBench) + if (TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.StartingUp) { - if (!benchInitializationFailed) - { - BenchControl.StateMachine.Start(); - log.Info("Test bench started"); - } - else - { - BenchControlPanel.OnButtonsEtc(null, new ButtonsEtcEventArgs(TBF.UiBridge.ButtonsEtc.None)); - MessageBox.Show(Strings.Bench_is_not_running, - Strings.Warning, - System.Windows.Forms.MessageBoxButtons.OK, - System.Windows.Forms.MessageBoxIcon.Exclamation); - } + BenchControl.StateMachine.Start(); + log.Info("Test bench started"); + } + else if (TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.FailedToStart) + { + BenchControlPanel.OnButtonsEtc(null, new ButtonsEtcEventArgs(ButtonsEtc.None)); + MessageBox.Show(Strings.Bench_is_not_running, + Strings.Warning, + System.Windows.Forms.MessageBoxButtons.OK, + System.Windows.Forms.MessageBoxIcon.Exclamation); } } @@ -402,23 +404,48 @@ namespace TBF mainProgressBar.Value = 0; } + /// + /// This handler is onvoked when state of buttons changes + /// + /// + /// void OnButtonsEtc(object sender, UiBridge.ButtonsEtcEventArgs args) { + if ((args.Flags & ButtonsEtc.Shutdown) != 0) + { + /// + /// TBF program is shutting down and the state machine was proparly stopped + /// + UI2Settings(); + if (closingTbfMessageForm != null) closingTbfMessageForm.CloseForm(this, null); + + if (IsShutdownPCAfterClosingTbf) + { + var psi = new System.Diagnostics.ProcessStartInfo("shutdown", "/s /t 0"); + psi.CreateNoWindow = true; + psi.UseShellExecute = false; + System.Diagnostics.Process.Start(psi); + } + + Close(); + return; + } + if (((args.Flags & ButtonsEtc.ShowBenchEmpty) != 0) || ((args.Flags & ButtonsEtc.ShowBenchFilled) != 0)) { return; } - CycleRunning = ((args.Flags & UiBridge.ButtonsEtc.ProcedureCmbBoxEn) == 0); + procedureComboBox.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0); + iPerlHeadsToolStripMenuItem.Enabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) != 0); - procedureComboBox.Enabled = !CycleRunning; - iPerlHeadsToolStripMenuItem.Enabled = !CycleRunning; - - if (!CycleRunning && ProceduresUpdated) + if (procedureComboBox.Enabled && ProceduresUpdated) { ReloadProcedureComboBoxItems(); } + + IsShutdownDisabled = ((args.Flags & ButtonsEtc.ProcedureCmbBoxEn) == 0); } public void UpdateUser() @@ -607,37 +634,63 @@ namespace TBF } } - private void MainWnd_FormClosing(object sender, FormClosingEventArgs e) + /// + /// Save UI settings to Program.LocalSettings and save them to a file. + /// UI settings are: + /// MainWnd size and location and splitter distances. + /// + void UI2Settings() { - Program.LocalSettings.RightPaneHorizSplitterDistance = rightHorizSplitContainer.SplitterDistance; - Program.LocalSettings.TopPaneVerticalSplitterDistance = topVerticalSplitContainer.SplitterDistance; + LocalSettings ls = Program.LocalSettings; - Program.LocalSettings.ManiWndMaximized = (WindowState == FormWindowState.Maximized); - if (WindowState == FormWindowState.Normal) + if (ls != null) { - Program.LocalSettings.MainWndLeft = Location.X; - Program.LocalSettings.MainWndTop = Location.Y; - Program.LocalSettings.MainWndWidth = Size.Width; - Program.LocalSettings.MainWndHeight = Size.Height; - } - else - { - /// Maximized or minimized (when restarted, minimized window is restored as normal) - Program.LocalSettings.MainWndLeft = RestoreBounds.Left; - Program.LocalSettings.MainWndTop = RestoreBounds.Top; - Program.LocalSettings.MainWndWidth = RestoreBounds.Width; - Program.LocalSettings.MainWndHeight = RestoreBounds.Height; - } - Program.LocalSettings.Save(); + ls.RightPaneHorizSplitterDistance = rightHorizSplitContainer.SplitterDistance; + ls.TopPaneVerticalSplitterDistance = topVerticalSplitContainer.SplitterDistance; - if (DialogResult == DialogResult.None) - { - exitToolStripMenuItem_Click(sender, e); + ls.ManiWndMaximized = (WindowState == FormWindowState.Maximized); + if (WindowState == FormWindowState.Normal) + { + ls.MainWndLeft = Location.X; + ls.MainWndTop = Location.Y; + ls.MainWndWidth = Size.Width; + ls.MainWndHeight = Size.Height; + } + else + { + /// Maximized or minimized (when restarted, minimized window is restored as normal) + ls.MainWndLeft = RestoreBounds.Left; + ls.MainWndTop = RestoreBounds.Top; + ls.MainWndWidth = RestoreBounds.Width; + ls.MainWndHeight = RestoreBounds.Height; + } + ls.Save(); } } - private void exitToolStripMenuItem_Click(object sender, EventArgs e) + bool TryShutdownTBF() { + if (TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.Undefined || + TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.Disabled || + TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.FailedToStart || + TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.Off) + { + /// + /// StateMachine is not running --> Shutdown immediately without displaying a message box + /// + if (closingTbfMessageForm != null) closingTbfMessageForm.CloseForm(this, null); + return true; + } + + if (TBF.BenchControl.StateMachine.MachineState == TBF.BenchControl.MachineState.ShuttingDown) + { + /// + /// Already shutting down --> Prevent a new shutdown without displaying a message box + /// + return false; + } + + /// Save emergency stop form state bool oriEmgStopState = false; if (emergencyStopModelessDlg != null) { @@ -645,155 +698,76 @@ namespace TBF emergencyStopModelessDlg.Visible = false; } - if (BenchControl.StateMachine.Running && (messageLabel.ForeColor != Color.Red) && CycleRunning) + if ((messageLabel.ForeColor != Color.Red) && IsShutdownDisabled) { + /// + /// It is not possible to shutdown (most likely a cycle is not completed) --> Display a message and prevent shutdown now + /// MessageBox.Show(Strings.Finish_the_session_please, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - if (e is FormClosingEventArgs) - { - (e as FormClosingEventArgs).Cancel = true; - } - return; + if (emergencyStopModelessDlg != null) emergencyStopModelessDlg.Visible = oriEmgStopState; + return false; } - if (DialogResult.Yes == MessageBox.Show(Strings.Do_you_want_to_exit_TBF, - Strings.Closing_the_program, - MessageBoxButtons.YesNo, - MessageBoxIcon.Question)) + Forms.ClosingTbfForm closingForm = new Forms.ClosingTbfForm(); + DialogResult dr = closingForm.ShowDialog(); + + if (dr == DialogResult.Yes) { - if (BenchControl.StateMachine.Running) + /// + /// User confirmed TBF program shutdown --> 1. Show modeless form, 2. Stop MainSeq and StateMachine, 3. Prevent TBF exit now + /// + + IsShutdownPCAfterClosingTbf = closingForm.ShutDownPC; + + /// Show 'Closing_Test_Bench_Framework' modeless window in separate thread + closingTbfMessageForm = new TBF.Forms.ModelessActivityForm() { - /// Show 'Closing_Test_Bench_Framework' modeless window in separate thread - var form = new TBF.Forms.ModelessActivityForm() - { - Message = Strings.Closing_Test_Bench_Framework, - FontFamily = "Arial", - FontSize = 24, - FontStyle = FontStyle.Regular, - BackgroundColor = Color.PeachPuff, - StartActivityHandler = true, - }; - Thread formThread = new Thread(() => form.ShowDialog()); - formThread.Start(); + Message = Strings.Closing_Test_Bench_Framework, + FontFamily = "Arial", + FontSize = 24, + FontStyle = FontStyle.Regular, + BackgroundColor = Color.PeachPuff, + StartActivityHandler = true, + }; + Thread formThread = new Thread(() => closingTbfMessageForm.ShowDialog()); + formThread.Start(); - /// Stop the system - BenchControl.StateMachine.Stop(); - while (BenchControl.StateMachine.Running) { } /// wait until the last StopOperaions() completes - BenchControl.StateMachine.StopDevices(); - BenchControl.StateMachine.StopDevices2(); - - UiBridge.Bridge.OnEmergencyStopChanged(this, UiBridge.EmergencyStopEventArgs.State.CloseForm); + /// Stop MainSeq and StateMachine + Bridge.Ui2Bench(UI2BenchCmd.Shutdown); - /// Close 'Closing_Test_Bench_Framework' modeless window - form.CloseForm(null, new EventArgs()); - formThread.Join(); - } - - /// Close the main window - DialogResult = DialogResult.OK; - Close(); - return; + /// Prevent TBF program exit now + return false; } - else if (e is FormClosingEventArgs) + else { - (e as FormClosingEventArgs).Cancel = true; + /// User aborted the shutdown --> Restore emergency stop form state and prevent shutdown now + if (emergencyStopModelessDlg != null) emergencyStopModelessDlg.Visible = oriEmgStopState; + return false; } - - if (emergencyStopModelessDlg != null) emergencyStopModelessDlg.Visible = oriEmgStopState; } + private void MainWnd_FormClosing(object sender, FormClosingEventArgs e) + { + if (TryShutdownTBF()) + { + UI2Settings(); /// Save settings and exit TBF + } + else + { + e.Cancel = true; /// Prevent TBF exit + } + } - //private void printToolStripMenuItem_Click(object sender, EventArgs e) - //{ - //TBF.Forms.PrintOrderForm dlg = new TBF.Forms.PrintOrderForm(); - //if (dlg.ShowDialog() == DialogResult.OK) - //{ - // string purchaseOrder = dlg.PurchaseOrder; - // string tester = dlg.Tester; + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + if (TryShutdownTBF()) + { + /// Save settings and exit TBF + UI2Settings(); + Close(); + } + } - // NHibernate.ISession session = Config.FluentCommon.CreateSession(Users.Entities.DBKind.Config); - - // IList testResults = session.QueryOver() - // .Where(x => (x.PurchaseOrder == purchaseOrder)) - // .List(); - - // if (testResults.Count == 0) - // { - // MessageBox.Show(Strings.No_results_to_print, Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - // return; - // } - - // if (dlg.OnlyGoodResults) - // { - // /// Proceed from the end of the list so that items can be removed by index - // for (int i = testResults.Count - 1; i >= 0; i--) - // { - // // TODO: Complete - // } - // } - - // if (dlg.OnlyLastResult) - // { - // /// Remove test results if there exist a later test results for the same sn - // /// Proceed from the end of the list so that items can be removed by index - // for (int i = testResults.Count - 1; i >= 0; i--) - // { - // string name = testResults[i].Name; - // int batchNr = testResults[i].BatchNr; - // foreach (var tr in testResults) - // { - // if (tr.Name == name && tr.BatchNr > batchNr) - // { - // bool allWMsAreTheSame = true; - - // int cnt = Math.Min(testResults[i].Meters.Count, tr.Meters.Count); - // for (int j = 0; j < cnt; j++) - // { - // if (testResults[i].Meters[j].SerialNr != tr.Meters[j].SerialNr) - // { - // allWMsAreTheSame = false; - // break; - // } - // } - - // if (allWMsAreTheSame) - // { - // /// Remove as there exists a more recent measurement with the same meters - // testResults.RemoveAt(i); - // break; - // } - // } - // } - // } - // } - - // IList procedure = session.QueryOver() - // .Where(x => (x.ProcedureState == ProcedureState.Active)) - // .And(x => (x.Name == testResults[0].ProcedureName)) - // .List(); - - // if (procedure.Count != 1) - // { - // MessageBox.Show(Strings.No_results_to_print, Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - // return; - // } - - // if ((testResults != null) && (testResults.Count != 0) && (testResults[0].MetersKind == MetersKind.Single)) - // { - // PrintOrderDocument doc = new PrintOrderDocument(procedure[0], testResults, tester); - // doc.DefaultPageSettings.Landscape = true; - // doc.Print(); - // } - // else if((testResults != null) && (testResults.Count != 0) && (testResults[0].MetersKind == MetersKind.Combined)) - // { - // /// Do nothing right now - // } - // else - // { - // MessageBox.Show(Strings.No_results_to_print, Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); - // return; - // } - //} - //} private void upgradeTSMenuItem_Click(object sender, EventArgs e) { diff --git a/TBF/MainWnd.cs.resx b/TBF/MainWnd.cs.resx index 036177039..2b9610157 100644 --- a/TBF/MainWnd.cs.resx +++ b/TBF/MainWnd.cs.resx @@ -121,115 +121,115 @@ 57, 20 - - Testovací stolice Framework - - - O - - - Proces - - - Prosím, spusťte proceduru - - - Komponenty - - - Metrologie - - - Cesty - - - Přechody - - - Stolice - - - Databáze - - - Nastavení - - - Výstup - - - Pomoc - - - Hydraulika - - - Domů - - - Vložit - - - Jazyk - - - Záznamy - - - Záznamy - - - Záhlaví hlavního menu - - - Měření - - - Měření - - - Heslo - - - Obrázky - - - Obrázky - - - Vytisknout - - - Postup - - - Postupy - - - Proces - - - Proces - - - Probíhá - - - Výsledky - - - Výsledky - - - Výsledky - - - Stavový pruh 1 - - - Uživatel : admin - - - Uživatelé - + + Testovací stolice Framework + + + O + + + Proces + + + Prosím, spusťte proceduru + + + Komponenty + + + Metrologie + + + Cesty + + + Přechody + + + Stolice + + + Databáze + + + Nastavení + + + Ukončit + + + Pomoc + + + Hydraulika + + + Domů + + + Vložit + + + Jazyk + + + Záznamy + + + Záznamy + + + Záhlaví hlavního menu + + + Měření + + + Měření + + + Heslo + + + Obrázky + + + Obrázky + + + Vytisknout + + + Postup + + + Postupy + + + Proces + + + Proces + + + Probíhá + + + Výsledky + + + Výsledky + + + Výsledky + + + Stavový pruh 1 + + + Uživatel : admin + + + Uživatelé + \ No newline at end of file diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index 55a15fe2b..8ad3bd8aa 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Sensus")] [assembly: AssemblyProduct("TestBenchFramework")] -[assembly: AssemblyCopyright("Copyright © 2013 - 2018 Sensus Slovensko, a.s.")] +[assembly: AssemblyCopyright("Copyright © 2013 - 2019 Sensus Slovensko, a.s.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.18.1154.0")] -[assembly: AssemblyFileVersion("2.18.1154.0")] +[assembly: AssemblyVersion("2.18.1156.0")] +[assembly: AssemblyFileVersion("2.18.1156.0")] diff --git a/TBF/Resources/Strings.Designer.cs b/TBF/Resources/Strings.Designer.cs index 36d85a060..92e6c1b52 100644 --- a/TBF/Resources/Strings.Designer.cs +++ b/TBF/Resources/Strings.Designer.cs @@ -1195,7 +1195,7 @@ namespace TBF.Resources { } /// - /// Looks up a localized string similar to Do you want to exit the Test Bench Framework?. + /// Looks up a localized string similar to Do you want to exit Test Bench Framework ?. /// internal static string Do_you_want_to_exit_TBF { get { @@ -4263,6 +4263,24 @@ namespace TBF.Resources { } } + /// + /// Looks up a localized string similar to Shut down computer after exiting Test Bench Framework. + /// + internal static string Shut_down_computer_after_exiting_TBF { + get { + return ResourceManager.GetString("Shut_down_computer_after_exiting_TBF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shutting down devices. + /// + internal static string Shutting_down_devices { + get { + return ResourceManager.GetString("Shutting_down_devices", resourceCulture); + } + } + /// /// Looks up a localized string similar to Side. /// diff --git a/TBF/Resources/Strings.cs.resx b/TBF/Resources/Strings.cs.resx index 6dd6e6303..7482db30c 100644 --- a/TBF/Resources/Strings.cs.resx +++ b/TBF/Resources/Strings.cs.resx @@ -406,7 +406,7 @@ Vyhodnocení - Výstup + Ukončit NOK @@ -1380,4 +1380,10 @@ Ztlumit sirénu + + Vypínání zařízení + + + Vypnout počítač po ukončení Test Bench Framework + \ No newline at end of file diff --git a/TBF/Resources/Strings.de.resx b/TBF/Resources/Strings.de.resx index 05717a9a6..0ce37ede8 100644 --- a/TBF/Resources/Strings.de.resx +++ b/TBF/Resources/Strings.de.resx @@ -1467,4 +1467,7 @@ Stummschaltung des Alarms + + Geräte herunterfahren + \ No newline at end of file diff --git a/TBF/Resources/Strings.pl.resx b/TBF/Resources/Strings.pl.resx index 45ef33b68..134b7d493 100644 --- a/TBF/Resources/Strings.pl.resx +++ b/TBF/Resources/Strings.pl.resx @@ -1605,4 +1605,7 @@ Wynik + + Zamykanie urządzeń + \ No newline at end of file diff --git a/TBF/Resources/Strings.resx b/TBF/Resources/Strings.resx index fe086366e..3e0841a9a 100644 --- a/TBF/Resources/Strings.resx +++ b/TBF/Resources/Strings.resx @@ -1280,7 +1280,7 @@ Closing the program - Do you want to exit the Test Bench Framework? + Do you want to exit Test Bench Framework ? The following components are in simulation mode: @@ -1936,4 +1936,10 @@ Mute the alarm + + Shutting down devices + + + Shut down computer after exiting Test Bench Framework + \ No newline at end of file diff --git a/TBF/TBF.csproj b/TBF/TBF.csproj index 90c461131..4af1ab971 100644 --- a/TBF/TBF.csproj +++ b/TBF/TBF.csproj @@ -1446,6 +1446,12 @@ WaterMeterCfgCtrl.cs + + Form + + + ClosingTbfForm.cs + Form @@ -2851,6 +2857,9 @@ AboutDlg.cs + + ClosingTbfForm.cs + DatabaseSettingsDlg.cs diff --git a/TBF/UiBridge/Enums.cs b/TBF/UiBridge/Enums.cs index 9c170b201..f766ca635 100644 --- a/TBF/UiBridge/Enums.cs +++ b/TBF/UiBridge/Enums.cs @@ -35,32 +35,32 @@ namespace TBF.UiBridge Next, /// Used for debugging } - public enum ButtonsEtc - { - None = 0, - ProcedureCmbBoxEn = (1 << 0), - TestCmbBoxEn = (1 << 1), - StopBtnEn = (1 << 2), - StartTestBtnsEn = (1 << 3), - StartCycleBtnEn = (1 << 4), - PurgeBeginBtnEn = (1 << 5), - PurgeEndBtnEn = (1 << 6), - DrainTankBtn1En = (1 << 7), - DrainTankBtn1Hi = (1 << 8), - DrainTankBtn2En = (1 << 9), - DrainTankBtn2Hi = (1 << 10), - DrainTankBtn3En = (1 << 11), - DrainTankBtn3Hi = (1 << 12), - Break = (1 << 13), - ResetResultsBtnEn = (1 << 14), - AcceptResultsBtnEn = (1 << 15), - CalibrationBtnEn = (1 << 16), - SensitivityTestBtnEn = (1 << 17), - CustomBtnEn = (1 << 18), + public enum ButtonsEtc + { + None = 0, + ProcedureCmbBoxEn = (1 << 0), + TestCmbBoxEn = (1 << 1), + StopBtnEn = (1 << 2), + StartTestBtnsEn = (1 << 3), + StartCycleBtnEn = (1 << 4), + PurgeBeginBtnEn = (1 << 5), + PurgeEndBtnEn = (1 << 6), + DrainTankBtn1En = (1 << 7), + DrainTankBtn1Hi = (1 << 8), + DrainTankBtn2En = (1 << 9), + DrainTankBtn2Hi = (1 << 10), + DrainTankBtn3En = (1 << 11), + DrainTankBtn3Hi = (1 << 12), + Break = (1 << 13), + ResetResultsBtnEn = (1 << 14), + AcceptResultsBtnEn = (1 << 15), + CalibrationBtnEn = (1 << 16), + SensitivityTestBtnEn = (1 << 17), + CustomBtnEn = (1 << 18), - /// If one of the following flags is set, flags 0x1 through 0x2000 are ignored - /// - ShowBenchEmpty = 0x1000000, - ShowBenchFilled = 0x2000000, + /// If one of the following flags is set, flags (1 << 0) through (1 << 18) are ignored + ShowBenchEmpty = (1 << 24), + ShowBenchFilled = (1 << 25), + Shutdown = (1 << 26), } }