From 2c91ded0db73c1e5446ccffdbdefdaec50dd304b Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 16 May 2022 14:57:39 +0200 Subject: [PATCH] Safe wrappers in ProcessData, clean-up. --- TBF/BenchControl/StateMachine.cs | 857 ------------------------------- TBF/Rig/Sequences/ProcessData.cs | 7 + 2 files changed, 7 insertions(+), 857 deletions(-) delete mode 100644 TBF/BenchControl/StateMachine.cs diff --git a/TBF/BenchControl/StateMachine.cs b/TBF/BenchControl/StateMachine.cs deleted file mode 100644 index db7c3c54f..000000000 --- a/TBF/BenchControl/StateMachine.cs +++ /dev/null @@ -1,857 +0,0 @@ -/// -/// Copyright (c) 2013-2021 Sensus Slovensko a.s. -/// -using System; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using log4net; -using NHibernate; -using Common; -using Config.Entities; -using TBF.BenchControl.Generic; -using TBF.BenchControl.GenericDevices; -using TBF.BenchControl.Sequences; -using Dirichlet.Numerics; -using TBF.Resources; - -namespace TBF.BenchControl -{ - 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. - /// It is based on a state machine - /// - public static class StateMachine - { - private static readonly ILog log = LogManager.GetLogger(typeof(StateMachine)); - private static readonly ILog wlog = LogManager.GetLogger(typeof(StateMachine)); - - /// Private devices and components - static IList components; /// list of all components - static IList devices; /// list of devices - /// - /// Bench paths - static IList feedingPaths; - static IList benchPaths; - static IList outputPaths; - static IList metersPaths; - static IList heatMetersPaths; - public static IList TransitionSequences; - public static IList TransitionSteps; - - /// Public components - public static Elde.ControlBoardDev ControlBoard; - public static GenericDevices.IAmbient Ambient; - public static IOperation BenchWaitingOp; - public static IOperation BenchErrorOp; - public static GenericDevices.IScaleOrTank Tank1; - public static GenericDevices.IScaleOrTank Tank2; - public static GenericDevices.IScaleOrTank Tank3; - public static GenericDevices.IValve DrainValve1; - public static GenericDevices.IValve DrainValve2; - public static GenericDevices.IValve DrainValve3; - public static IList MasterValves; /// list of directly controlled valves - public static IList CoupledValves; /// list of coupled valves - public static IList ExtendedValves; /// list of extended valves - - public static IList LoopStartNames; - public static IList LoopEndNames; - - /// Time and synchronization -#if TURA_IPERL || TURA_IPERL_NEW - public const int Period = 2; /// State machine period in sec. -#else - public const int Period = 1; /// State machine period in sec. -#endif - - 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 - - public static MachineState MachineState; /// see enum MachineState for explanation - - /// Worker thread and database session - static Thread workerThread; - - static IList states; /// list of states - - public static DateTime CycleStartTimeStamp; - - public static IList DefaultValvesOpen - { - get - { - return GenericDevices.ValveBase.Merge( - Utils.ValvesOpen((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null), - Utils.ValvesOpen((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null), - Utils.ValvesOpen((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null) - ); - } - } - - public static IList DefaultValvesClose - { - get - { - return GenericDevices.ValveBase.Merge( - Utils.ValvesClose((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null), - Utils.ValvesClose((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null), - Utils.ValvesClose((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null) - ); - } - } - - /// - /// Loaded by LoadProcedure() or IOperation LoadProcedureOp(...) - /// - public static Procedure Procedure; /// Procedure - public static TestInstance[] TestInstances; /// Tests - public static bool IsRemoteProcedure; - - - /// Hardware devices connected to the PC controlling the bench. - public static IList Components { get { return components; } } - public static IList Devices { get { return devices; } } - - /// - /// DateTime of time instance when the state machine worker thread starts - /// - public static DateTime StartDateTime { get { return startDateTime; } } - - /// - /// Current state name - /// - public static int Time - { - get { return currentTimeSec; } - set { currentTimeSec = value; } - } - - /// - /// Constructor - /// - static StateMachine() - { - devices = new List(); - states = new List(); - currentTimeSec = 0; - } - - /// - /// Add a device to the state machine. - /// - /// Device - public static void AddDevice(IDevice device) - { - if (device != null && !devices.Contains(device)) devices.Add(device); - } - - /// - /// Add a state to the state machine. - /// In this way a sequence can be created programtically. - /// - /// State - public static void AddState(State state) - { - if (state != null && !states.Contains(state)) states.Add(state); - } - - /// - /// Remove the state from the state machine. - /// - /// State - public static void RemoveState(State state) - { - if (state != null && state != State.CurrentState && states.Contains(state)) states.Remove(state); - } - - /// - /// Get a state from a label - /// - /// - /// The matching state or null - static State GetStateFromLabel(string label) - { - if (label == null) return null; - - foreach (State state in states) - { - if (state.Label != null && state.Label.Equals(label)) return state; - } - return null; - } - - /// - /// Start the state machine in the state 'label' in a desired mode of operation. - /// This method is called in the UI thread and creates a new state machine thread. - /// This method call should be embedded in: try { StateMachine.Start(...); } catch { } - /// to handle configuration problems. Calls CreateDevices(mode) and CreateStates(). - /// - /// Mode of operation - /// A copy of bench data used by the state machine - /// Identifies the initial state -#if DN100 - public static void InitializeBoardEtc(ControlCom2VB.ControlCom2panel ctrlBrdComponent) -#elif FUZHOU_150 || MUNICH - public static void InitializeBoardEtc(ControlComponent3Munich.UserControl1 ctrlBrdComponent) -#elif FUZHOU_300 - public static void InitializeBoardEtc(ControlComponent3F300.UserControl1 ctrlBrdComponent) -#elif BERLIN || GELSENWASSER || GENESIS || IZRAEL_200 || PETERSBURG_200 || PUCHONG_200 || SLM_150 - public static void InitializeBoardEtc(ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent) -#else /// all newer benches - public static void InitializeBoardEtc(ControlComponent_Torino2015.UserControl1 ctrlBrdComponent) -#endif - { - /// Load the list of components (entities) from the database. - /// Then create the components (derived from IComponent). - components = BenchControl.TbfComponents.LoadComponentsFromDB(TBF.DB.CreateSession(Common.DBKind.Config)); - MasterValves = GenericDevices.ValveBase.MasterValves(components); - CoupledValves = GenericDevices.ValveBase.CoupledValves(components); - ExtendedValves = GenericDevices.ValveBase.ExtendedValves(components); - - /// Find all balances (to initialize tank capacities in the control board) - /// Find the control board - IList tanks = new List(); - ProcessData.IperlHeads = new List(); - SequenceBase.FlowMeters = new List(); - SequenceBase.RegulValves = new List(); - SequenceBase.FeedingRegulValves = new List(); - SequenceBase.OutputRegulValves = new List(); - SequenceBase.PumpsWithFM = new List(); - SequenceBase.WaterMeters = new List(); - SequenceBase.Cameras = new List(); - LoopStartNames = new List(); - LoopEndNames = new List(); - UInt128 valvesToInvert = 0; - foreach (var cmpnt in components) - { - if (cmpnt is Elde.ControlBoardDev) ControlBoard = cmpnt as Elde.ControlBoardDev; - if (cmpnt is IBenchInfo) ProcessData.BenchInfo = cmpnt as IBenchInfo; - if (cmpnt is IErrorFlags) ProcessData.ErrorFlagsComp = cmpnt as IErrorFlags; - if (cmpnt is IStatisticsMonitoring) ProcessData.StatisticsMonitoringComp = cmpnt as IStatisticsMonitoring; - - if ((cmpnt is Output.DB.SensusOracle.Database) && (ProcessData.OracleDB == null)) - { - /// The 1st Oracle database component found --> store the reference - ProcessData.OracleDB = cmpnt as Output.DB.SensusOracle.Database; - } - if ((cmpnt is Output.DB.ProductionTracing.Tracing) && (ProcessData.TracingDB == null)) - { - /// The 1st production tracing database component found --> store the reference - ProcessData.TracingDB = cmpnt as Output.DB.ProductionTracing.Tracing; - } - - if (cmpnt is TestMethods.iPerlCommunication.iPerlHead.IperlHead) - { - ProcessData.IperlHeads.Add(cmpnt as TestMethods.iPerlCommunication.iPerlHead.IperlHead); - } - if (cmpnt is IFlowMeter) SequenceBase.FlowMeters.Add(cmpnt as IFlowMeter); - if ((cmpnt is IRegValve) && !(cmpnt is BenchControl.Elde.RegulValveTandem.RegulValveTandem)) - { - IRegValve rv = cmpnt as IRegValve; - SequenceBase.RegulValves.Add(rv); - if (rv.Category == ValveCategory.Feeding) SequenceBase.FeedingRegulValves.Add(rv); - if (rv.Category == ValveCategory.Output) SequenceBase.OutputRegulValves.Add(rv); - } - if (cmpnt is IPumpFM && !(cmpnt is Elde.PumpTandem.Pump)) - { - SequenceBase.PumpsWithFM.Add(cmpnt as IPumpFM); - } - if (cmpnt is IWaterMeter) SequenceBase.WaterMeters.Add(cmpnt as IWaterMeter); - if (cmpnt is ICamera) SequenceBase.Cameras.Add(cmpnt as ICamera); - if (cmpnt is GenericDevices.IAmbient) Ambient = cmpnt as GenericDevices.IAmbient; - - if (cmpnt is GenericDevices.IParallelOutput && cmpnt.Name.ToLower().Contains("tower")) - { - BenchWaitingOp = (cmpnt as GenericDevices.IParallelOutput).ShowBenchWaitingOp(); - BenchErrorOp = (cmpnt as GenericDevices.IParallelOutput).ShowBenchErrorOp(); - } - - if (cmpnt is ITestMethod && cmpnt.ClassName == "TestMethods.OuterLoop.Start") LoopStartNames.Add(cmpnt.Name); - if (cmpnt is ITestMethod && cmpnt.ClassName == "TestMethods.OuterLoop.End") LoopEndNames.Add(cmpnt.Name); - - if (cmpnt is IScaleOrTank) - { - IScaleOrTank tank = cmpnt as IScaleOrTank; - tanks.Add(tank); - if (Tank1 == null) Tank1 = tank; - else if (Tank2 == null) Tank2 = tank; - else if (Tank3 == null) Tank3 = tank; - } - - Elde.Valve.Valve eldeValve = (cmpnt as Elde.Valve.Valve); - if ((eldeValve != null) && eldeValve.Inverted) valvesToInvert |= eldeValve.Mask; - } - - /// Pre-initialize the control board (= buffer the arguments ctrlBrdComponent, tankCapacities) - if (ControlBoard != null) - { - /// Create an array with tank capacities from 'tanks' list - double[] tankCapacities = new double[tanks.Count]; - for (int i = 0; i < tankCapacities.Length; i++) tankCapacities[i] = tanks[i].Capacity; - - ControlBoard.InitializeEldeComponent(ctrlBrdComponent, valvesToInvert, tankCapacities); - } - else - { - throw new Exception("Control board component is missing"); - } - } - - - public static string CurrentlyInitializedComponentName; - /// - public static string InitializeComponents() - { - CurrentlyInitializedComponentName = "-"; - - bool anyComponentIsInSimulMode = false; - StringBuilder inSimulMode = new StringBuilder(); - - /// Add all devices to the state machine and initialize them - foreach (var cmpnt in components) - { - if (cmpnt.DebugLevel == DebugMode.Simulate) - { - inSimulMode.AppendFormat("{0}{1}", anyComponentIsInSimulMode ? ", " : "", cmpnt.Name); - anyComponentIsInSimulMode = true; - } - - if (cmpnt is IDevice) - { - devices.Add(cmpnt as IDevice); /// Only components that were initialized are added - UiBridge.Bridge.OnActivity(null, cmpnt.Name); /// Info - } - - CurrentlyInitializedComponentName = cmpnt.Name; - cmpnt.Initialize(); - cmpnt.StartChangeHandler(); /// Start handling parameter change events - } - - CurrentlyInitializedComponentName = "---"; - - /// - /// (1) Propagate debug levels from parents to children when necessary - /// (2) Set drain valves DrainValve1, DrainValve2 and DrainValve3 - /// - foreach (var cmpnt in components) - { - if (cmpnt.Cfg is IChildComponentCfg && !string.IsNullOrEmpty(cmpnt.Cfg.ParentName) && - (cmpnt.Cfg.DebugLevel == DebugMode.Inherit || cmpnt.Cfg.DebugLevel == DebugMode.AutoDetect)) - { - foreach (var par in components) - { - if (par.Cfg.Name.Equals(cmpnt.Cfg.ParentName)) { cmpnt.Cfg.DebugLevel = par.Cfg.DebugLevel; break; } - } - } - - if (cmpnt is IScaleOrTank) - { - IScaleOrTank tank = cmpnt as IScaleOrTank; - - if (tank == Tank1 && DrainValve1 == null) - { - DrainValve1 = tank.DrainValve; - log.WarnFormat("InitializeComponents() ... Scale1={0} DrainValve1={1}", - tank.Name, (DrainValve1 != null) ? DrainValve1.Name : "---"); - } - else if (tank == Tank2 && DrainValve2 == null) - { - DrainValve2 = tank.DrainValve; - log.WarnFormat("InitializeComponents() ... Scale2={0} DrainValve2={1}", - tank.Name, (DrainValve2 != null) ? DrainValve2.Name : "---"); - } - else if (tank == Tank3 && DrainValve3 == null) - { - DrainValve3 = tank.DrainValve; - log.WarnFormat("InitializeComponents() ... Scale3={0} DrainValve3={1}", - tank.Name, (DrainValve3 != null) ? DrainValve3.Name : "---"); - } - } - } - - if (anyComponentIsInSimulMode) - return inSimulMode.ToString(); - else - return null; - } - - /// - /// Stop devices that were started by InitializeDevices(). - /// Works correctly also after exeption from InitializeDevices() as only ... - /// ... correctly started devices were added in 'devices' list. - /// - public static void StopDevices() - { - for (int i = devices.Count - 1; i >= 0; i--) - { - var dev = devices[i]; - UiBridge.Bridge.OnActivity(null, string.Format("1. {0}", dev.Name)); /// Info - dev.StopDevice(); - } - } - - /// - /// Stop devices that were started by InitializeDevices(). - /// Works correctly also after exeption from InitializeDevices() as only ... - /// ... correctly started devices were added in 'devices' list. - /// - public static void StopDevices2() - { - for (int i = devices.Count - 1; i >= 0; i--) - { - var dev = devices[i]; - UiBridge.Bridge.OnActivity(null, string.Format("2. {0}", dev.Name)); /// Info - dev.StopDevice2(); - } - } - - /// - /// Checks remote and local configuration DB paths and transitions for compatibility - /// - /// true when DB-s are compatible - public static bool IsRemoteDBCompatible(out string message) - { - IList remoteFeedingPaths; - IList remoteBenchPaths; - IList remoteOutputPaths; - IList remoteMetersPaths; - IList remoteTransitions; - - try - { - ISession remoteSession = TBF.DB.CreateSession(Common.DBKind.RemoteConfig); - remoteFeedingPaths = remoteSession.QueryOver().List(); - remoteBenchPaths = remoteSession.QueryOver().List(); - remoteOutputPaths = remoteSession.QueryOver().List(); - remoteMetersPaths = remoteSession.QueryOver().List(); - remoteTransitions = remoteSession.QueryOver().List(); - } - catch (Exception) - { - message = "Cannot open remote database"; - return false; - } - - ISession localSession = TBF.DB.CreateSession(Common.DBKind.Config); - var localFeedingPaths = localSession.QueryOver().List(); - var localBenchPaths = localSession.QueryOver().List(); - var localOutputPaths = localSession.QueryOver().List(); - var localMetersPaths = localSession.QueryOver().List(); - var localTransitions = localSession.QueryOver().List(); - - string subMsg; - if (!IsCompatible(localFeedingPaths, remoteFeedingPaths, out subMsg)) - { - message = string.Format("Feeding: {0}", subMsg); - return false; - } - - if (!IsCompatible(localBenchPaths, remoteBenchPaths, out subMsg)) - { - message = string.Format("Bench: {0}", subMsg); - return false; - } - - if (!IsCompatible(localOutputPaths, remoteOutputPaths, out subMsg)) - { - message = string.Format("Output: {0}", subMsg); - return false; - } - - if (!IsCompatible(localMetersPaths, remoteMetersPaths, out subMsg)) - { - message = string.Format("Sensors: {0}", subMsg); - return false; - } - - if (!IsCompatible(localTransitions, remoteTransitions, out subMsg)) - { - message = string.Format("Transitions: {0}", subMsg); - return false; - } - - message = string.Empty; - return true; - } - - /// - /// - /// - /// FeedingPath, BenchPath, OutputPath, MetersPath or TransitionSequence - /// Local list of paths or transitions - /// Remote list of paths or transitions - /// Message specifying a cause of incompatibility - /// true when lists are compatible, otherwise false - private static bool IsCompatible(IList localList, IList remoteList, out string message) - { - message = "Local list is empty"; - if ((localList == null) || (localList.Count == 0) || !(localList[0] is IHasName)) return false; - - message = "Remote list is empty"; - if ((remoteList == null) || (remoteList.Count == 0) || !(remoteList[0] is IHasName)) return false; - - /// - /// Each path or transition on a remote list must exist on a local list - /// - foreach (var rItem in remoteList) - { - bool exists = false; - foreach (var lItem in localList) - { - if ((rItem as IHasName).Name == (lItem as IHasName).Name) - { - exists = true; - break; - } - } - - if (!exists) - { - message = string.Format("Remote item {0} does not exist on a local list", (rItem as IHasName).Name); - return false; - } - } - - message = string.Empty; - return true; - } - - - /// - /// Start the state machine - /// - public static void Start() - { - 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(); - } - - /// - /// Loads all paths and transitions from the DB. - /// Updates StatMachine.feedingPaths ... StatMachine.meterPaths, StatMachine.TransitionSequences - /// - public static void LoadPathsAndTransitions(ISession session) - { - feedingPaths = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); - benchPaths = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); - outputPaths = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); - metersPaths = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); - TransitionSequences = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); - TransitionSteps = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); -#if HEAT_METERS - heatMetersPaths = session.QueryOver().OrderBy(x => x.ItemNr).Asc.List(); -#endif - } - - /// - /// Loads selected procedure from the DB. - /// Updates StateMachine.Procedure and StateMachine.Tests - /// - public static bool LoadProcedure(ISession session, string procedureName, bool isRemote, IList autoTests = null) - { - Procedure = null; - - IList selectedProcs = session.QueryOver() - .Where(x => (x.ProcedureState == Common.ProcedureState.Active)) - .And(x => (x.Name == procedureName)) - .List(); - if (selectedProcs.Count == 1) - { - IsRemoteProcedure = isRemote; - Procedure = selectedProcs[0]; - TestInstances = selectedProcs[0].UpdateTestInstances(LoopStartNames, LoopEndNames, autoTests); - return true; - } - else - { - return false; - } - } - - public static void LoadProcedureParams(Procedure procedure) - { - foreach (var cmpnt in components) - { - cmpnt.Cfg.LoadProcedureParamsFromDB(procedure); - } - } - - public static void LoadTestParams(Test test) - { - foreach (var cmpnt in components) - { - cmpnt.Cfg.LoadTestParamsFromDB(test); - } - } - - /// - /// Called from the sequence to update paths based on the selected test - /// - /// Selected test - /// - /// - /// - /// - /// Transition sequence entity - /// Transition sequence entity - /// Error message in case of incorrect configuration - /// true when loaded configuration is correct (all four paths are defined !=null, etc.) - public static bool GetPaths(Test test, - bool heatMetersPathRequired, - out FeedingPath pfeed, - out BenchPath pben, - out OutputPath pout, - out MetersPath pmtrs, - out HeatMetersPath phmtrs, - out TransitionSequence transitionBefore, - out TransitionSequence transitionBetween, - out TransitionSequence transitionAfter, - out string errorMsg) - { - ITestMethod tm = TbfComponents.FindComponent(test.Method) as ITestMethod; - bool isHydroTest = (tm != null) ? tm.DoTransitions() : false; - - pfeed = null; - pben = null; - pout = null; - phmtrs = null; - transitionBefore = null; - transitionBetween = null; - transitionAfter = null; - - foreach (var path in feedingPaths) - { - if (test.FeedingPath == path.Name) { pfeed = new FeedingPath(path, components); break; } - } - - foreach (var path in benchPaths) - { - if (test.BenchPath == path.Name) { pben = new BenchPath(path, components); break; } - } - - foreach (var path in outputPaths) - { - if (test.OutputPath == path.Name) { pout = new OutputPath(path, components); break; } - } - - pmtrs = GetMetersPath(test); - - if (isHydroTest && (pfeed == null)) errorMsg = Strings.Cannot_load_feeding_path; - else if (isHydroTest && (pben == null)) errorMsg = Strings.Cannot_load_bench_path; - else if (isHydroTest && (pout == null)) errorMsg = Strings.Cannot_load_output_path; - else if (pmtrs == null) errorMsg = Strings.Cannot_load_sensor_path; - else errorMsg = string.Empty; - if ((isHydroTest && (pfeed == null || pben == null || pout == null)) || (pmtrs == null)) - { - log.ErrorFormat("GetPaths({0},...) returns false, wrong configuration", test.Name); - return false; - } - -#if HEAT_METERS - foreach (var path in heatMetersPaths) - { - if (test.HeatMetersPath == path.Name) { phmtrs = new HeatMetersPath(path, components); break; } - } -#endif - if (heatMetersPathRequired && phmtrs == null) - { - log.ErrorFormat("GetPaths({0},...) returns false, missing heat meters sensors", test.Name); - errorMsg = "Cannot load heat meters sensors"; - return false; - } - - foreach (var tr in TransitionSequences) - { - if (tr.Name == test.TransBefore) transitionBefore = tr; - if (tr.Name == test.TransBetween) transitionBetween = tr; - if (tr.Name == test.TransAfter) transitionAfter = tr; - } - - if (isHydroTest && pout.Scale == null) - { - log.ErrorFormat("GetPaths({0},...) returns false, missing scales in output path {1}", test.Name, test.OutputPath); - errorMsg = string.Format("No balance specified in path {0}", test.OutputPath); - return false; - } - - if (Config.Formulas.RealDensity() < 500.0f || Config.Formulas.RealDensity() > 2000.0f) - { - log.ErrorFormat("GetPaths({0},...) returns false, density was not specified", test.Name); - errorMsg = string.Format("Density was not specified"); - return false; - } - - log.WarnFormat("GetPaths({0},...) returns true, paths loaded OK, isHydroTest={1}", test.Name, isHydroTest); - errorMsg = string.Empty; - return true; - } - - - /// - /// Updates paths based on the selected test - /// - public static MetersPath GetMetersPath(Test test) - { - MetersPath pmtrs = null; - foreach (var path in metersPaths) - { - if (test.MetersPath == path.Name) { pmtrs = new MetersPath(path, components); break; } - } - if (pmtrs != null) - { - int count = Math.Min(TBF.Data.WMsCount, pmtrs.RegisterReaders.Length); - for (int i = 0; i < count; i++) - { - if ((pmtrs.RegisterReaders[i] != null) && - (pmtrs.RegisterReaders[i].Cfg.DebugLevel == DebugMode.DetectedOff)) - { - pmtrs.RegisterReaders[i] = null; - } - } - } - return pmtrs; - } - - - /* - * This is and example sequence of RunDeviceBefore() / RunOperations() / RunDeviceAfter() calls - * as they are executed during normal run from the progran start to the end. - * - foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in StateMachine.Worker() - State.Create(...).AddOperation(...).AddOperation(...).EnterState() . . in the sequence in Execute(...) - - foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() - WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() - foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() - IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() - - foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() - WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() - foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() - IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() - - State.Create(...).AddOperation(...).AddOperation(...).EnterState() . . in the sequence in Execute(...) - - foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() - WaitNextTick() (may throw QuitStateMachineException) . . . . . . . . in WaitRunDevsRunOps() - foreach (var device in devices) device.RunDeviceBefore(); . . . . . . in WaitRunDevsRunOps() - IList events = State.RunOperations(); . . . . . . . . . . . . . in WaitRunDevsRunOps() - - foreach (var device in devices) device.RunDeviceAfter(); . . . . . . . in WaitRunDevsRunOps() - WaitNextTick() (assume QuitStateMachineException thrown) . . . . . . in WaitRunDevsRunOps() - State.StopOperations(); . . . . . . . . . . . . . . . . . . . . . . . in StateMachine.Worker() catch() - foreach (var device in devices) device.StopDevice(); . . . . . . . . . in StateMachine.Worker() catch() - */ - - /// - /// Worker thread: calls Start(), Run() and Stop() methods of operations. - /// It uses 'currentState', 'nextState' and 'quitStateMachine' static fields. - /// - static void Worker() - { - MachineState = MachineState.Running; - startDateTime = DateTime.Now; - 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(); - - SequenceBase.ReferenceFlowmetersCount = SequenceBase.FlowMeters.Count; - SequenceBase.CalibratedLtrPerRefPulse = new double[SequenceBase.ReferenceFlowmetersCount]; - foreach (var flowmtr in SequenceBase.FlowMeters) - { - int ix = flowmtr.Idx1; - if (ix > 0 && ix <= SequenceBase.ReferenceFlowmetersCount) - { - SequenceBase.CalibratedLtrPerRefPulse[ix - 1] = flowmtr.NominalFlow / 7200.0; - } - } - - /// - /// 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 - } - - - /// - /// 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(bool lastTime = false) - { - Thread.Sleep(100); /// Insert 1/10 sec.delay between RunOperations() and RunDeviceAfter() - - for (int i = devices.Count - 1; i >= 0; i-- ) - { - devices[i].RunDeviceAfter(); - } - - WaitNextTick(); - - if (lastTime) - { - /// - /// Executed when the state machine is being stopped - /// - State.StopOperations(); - return null; - } - - foreach (var device in devices) - { - device.RunDeviceBefore(); - } - - 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 - } - - - /// - /// Wait time period - synchronize - /// - /// true when interrupted by 'quitStateMachine', otherwise false - public static void WaitNextTick() - { - int currentTimeSecFromClock = Convert.ToInt32(Math.Round((DateTime.Now - startDateTime).TotalSeconds - 0.2)); - - currentTimeSec = Math.Max(currentTimeSec, currentTimeSecFromClock) + Period; - - DateTime nextTickDateTime = startDateTime + TimeSpan.FromSeconds(currentTimeSec); - - while (DateTime.Now < nextTickDateTime) - { - Thread.Sleep(100); - } - } - } -} diff --git a/TBF/Rig/Sequences/ProcessData.cs b/TBF/Rig/Sequences/ProcessData.cs index a93fd6dc9..749b30019 100644 --- a/TBF/Rig/Sequences/ProcessData.cs +++ b/TBF/Rig/Sequences/ProcessData.cs @@ -30,6 +30,13 @@ namespace TBF.Rig.Sequences public static int LinesCount { get { return TBF.Data.WMsCount / TBF.Data.LineSize; } } public static int LineSize { get { return TBF.Data.LineSize; } } public static int CompoundWMsCount { get { return TBF.Data.CompoundWMsCount; } } + /// + public static Unit VolumeUnit { get { return BenchInfo != null ? BenchInfo.VolumeUnit : Unit.l; } } + public static Unit FlowUnit { get { return BenchInfo != null ? BenchInfo.FlowUnit : Unit.m3ph; } } + public static Unit MassUnit { get { return BenchInfo != null ? BenchInfo.MassUnit : Unit.kg; } } + public static Unit TempUnit { get { return BenchInfo != null ? BenchInfo.TempUnit : Unit.C; } } + public static Unit PressUnit { get { return BenchInfo != null ? BenchInfo.PressUnit : Unit.bar; } } + public static Unit LengthUnit { get { return BenchInfo != null ? BenchInfo.LengthUnit : Unit.mm; } } /// /// Procedure related state variables