2015-04-15 18:32:56 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Copyright (c) 2013-2015 Sensus Metering Systems
|
|
|
|
|
|
///
|
|
|
|
|
|
using System;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
using log4net;
|
|
|
|
|
|
using NHibernate;
|
2015-12-04 16:17:20 +00:00
|
|
|
|
using Config.Entities;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
using TBF.BenchControl.Generic;
|
|
|
|
|
|
using TBF.BenchControl.GenericDevices;
|
|
|
|
|
|
using TBF.BenchControl.Sequences;
|
2016-12-12 16:25:12 +00:00
|
|
|
|
using Dirichlet.Numerics;
|
2017-05-03 20:17:20 +00:00
|
|
|
|
using TBF.Resources;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
namespace TBF.BenchControl
|
|
|
|
|
|
{
|
|
|
|
|
|
public class QuitStateMachineException : Exception
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// This class controls real test bench behavior.
|
|
|
|
|
|
/// It is based on a state machine
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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<IComponent> components; /// list of all components
|
|
|
|
|
|
static IList<IDevice> devices; /// list of devices
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Bench paths
|
2015-12-04 16:17:20 +00:00
|
|
|
|
static IList<Config.Entities.FeedingPath> feedingPaths;
|
|
|
|
|
|
static IList<Config.Entities.BenchPath> benchPaths;
|
|
|
|
|
|
static IList<Config.Entities.OutputPath> outputPaths;
|
|
|
|
|
|
static IList<Config.Entities.MetersPath> metersPaths;
|
2016-06-28 16:04:52 +00:00
|
|
|
|
static IList<Config.Entities.HeatMetersPath> heatMetersPaths;
|
|
|
|
|
|
public static IList<Config.Entities.TransitionSequence> TransitionSequences;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
/// Public components
|
|
|
|
|
|
public static Elde.ControlBoardDev ControlBoard;
|
|
|
|
|
|
public static GenericDevices.IAmbient Ambient;
|
2017-03-28 21:47:32 +00:00
|
|
|
|
public static GenericDevices.IScale Scale1;
|
|
|
|
|
|
public static GenericDevices.IScale Scale2;
|
|
|
|
|
|
public static GenericDevices.IScale Scale3;
|
2017-03-28 10:38:47 +00:00
|
|
|
|
public static GenericDevices.IValve DrainValve1;
|
|
|
|
|
|
public static GenericDevices.IValve DrainValve2;
|
|
|
|
|
|
public static GenericDevices.IValve DrainValve3;
|
2015-06-29 09:26:08 +00:00
|
|
|
|
public static IList<IValve> MasterValves; /// list of directly controlled valves
|
|
|
|
|
|
public static IList<IValve> CoupledValves; /// list of coupled valves
|
|
|
|
|
|
public static IList<Elde.ValveEx.Valve> ExtendedValves; /// list of extended valves
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
2016-04-07 13:37:49 +00:00
|
|
|
|
|
|
|
|
|
|
/// Time and synchronization
|
2017-02-14 12:25:43 +00:00
|
|
|
|
#if TURA_IPERL
|
2015-08-19 11:00:00 +00:00
|
|
|
|
public const int Period = 2; /// State machine period in sec.
|
2016-04-07 13:37:49 +00:00
|
|
|
|
#else
|
|
|
|
|
|
public const int Period = 1; /// State machine period in sec.
|
2015-08-19 11:00:00 +00:00
|
|
|
|
#endif
|
2015-09-17 16:14:49 +00:00
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
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; } }
|
|
|
|
|
|
|
|
|
|
|
|
/// Worker thread and database session
|
|
|
|
|
|
static Thread workerThread;
|
|
|
|
|
|
public static ISession WtSession;
|
|
|
|
|
|
|
|
|
|
|
|
static IList<State> states; /// list of states
|
|
|
|
|
|
|
2016-03-02 19:02:30 +00:00
|
|
|
|
public static DateTime CycleStartTimeStamp;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
public static IList<IValve> DefaultValvesOpen
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return GenericDevices.ValveBase.Merge(
|
|
|
|
|
|
Utils.ValvesOpen((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null),
|
2017-03-28 21:47:32 +00:00
|
|
|
|
Utils.ValvesOpen((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null),
|
|
|
|
|
|
Utils.ValvesOpen((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static IList<IValve> DefaultValvesClose
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
return GenericDevices.ValveBase.Merge(
|
|
|
|
|
|
Utils.ValvesClose((feedingPaths != null && feedingPaths.Count > 0) ? feedingPaths[0] : null),
|
2017-03-28 21:47:32 +00:00
|
|
|
|
Utils.ValvesClose((benchPaths != null && benchPaths.Count > 0) ? benchPaths[0] : null),
|
|
|
|
|
|
Utils.ValvesClose((outputPaths != null && outputPaths.Count > 0) ? outputPaths[0] : null)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Loaded by LoadProcedure() or IOperation LoadProcedureOp(...)
|
|
|
|
|
|
/// </summary>
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static Procedure Procedure; /// Procedure
|
|
|
|
|
|
public static IList<Test> Tests; /// Tests
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Hardware devices connected to the PC controlling the bench.
|
|
|
|
|
|
public static IList<IComponent> Components { get { return components; } }
|
|
|
|
|
|
public static IList<IDevice> Devices { get { return devices; } }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// DateTime of time instance when the state machine worker thread starts
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static DateTime StartDateTime { get { return startDateTime; } }
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Current state name
|
|
|
|
|
|
/// </summary>
|
2014-08-01 06:36:17 +00:00
|
|
|
|
public static int Time { get { return currentTimeSec; } }
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Constructor
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
static StateMachine()
|
|
|
|
|
|
{
|
|
|
|
|
|
devices = new List<IDevice>();
|
|
|
|
|
|
states = new List<State>();
|
|
|
|
|
|
|
|
|
|
|
|
currentTimeSec = 0;
|
|
|
|
|
|
quitStateMachine = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a device to the state machine.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">Device</param>
|
|
|
|
|
|
public static void AddDevice(IDevice device)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (device != null && !devices.Contains(device)) devices.Add(device);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Add a state to the state machine.
|
|
|
|
|
|
/// In this way a sequence can be created programtically.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">State</param>
|
|
|
|
|
|
public static void AddState(State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (state != null && !states.Contains(state)) states.Add(state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Remove the state from the state machine.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="obj">State</param>
|
|
|
|
|
|
public static void RemoveState(State state)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (state != null && state != State.CurrentState && states.Contains(state)) states.Remove(state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Get a state from a label
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="label"></param>
|
|
|
|
|
|
/// <returns>The matching state or null</returns>
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 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().
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="mode">Mode of operation</param>
|
|
|
|
|
|
/// <param name="benchData">A copy of bench data used by the state machine</param>
|
|
|
|
|
|
/// <param name="label">Identifies the initial state</param>
|
|
|
|
|
|
#if DN100
|
|
|
|
|
|
public static void InitializeBoardEtc(ControlCom2VB.ControlCom2panel ctrlBrdComponent)
|
2017-01-24 14:05:30 +00:00
|
|
|
|
#elif MUNICH || FUZHOU150
|
2014-07-28 07:54:35 +00:00
|
|
|
|
public static void InitializeBoardEtc(ControlComponent3Munich.UserControl1 ctrlBrdComponent)
|
2014-09-02 16:10:16 +00:00
|
|
|
|
#elif FUZHOU300
|
2014-09-05 12:17:12 +00:00
|
|
|
|
public static void InitializeBoardEtc(ControlComponent3F300.UserControl1 ctrlBrdComponent)
|
2017-05-11 13:37:48 +00:00
|
|
|
|
#elif PT200IL || PUCHONG_PT200 || GENESIS || BERLIN || SLM_150 || PETERBURG_200
|
2017-01-24 14:05:30 +00:00
|
|
|
|
public static void InitializeBoardEtc(ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent)
|
2015-09-17 16:14:49 +00:00
|
|
|
|
#else /// all newer benches
|
2015-05-05 15:15:37 +00:00
|
|
|
|
public static void InitializeBoardEtc(ControlComponent_Torino2015.UserControl1 ctrlBrdComponent)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
#endif
|
2016-12-14 10:09:23 +00:00
|
|
|
|
{
|
2014-07-28 07:54:35 +00:00
|
|
|
|
/// Load the list of components (entities) from the database.
|
|
|
|
|
|
/// Then create the components (derived from IComponent).
|
2017-03-16 20:53:12 +00:00
|
|
|
|
components = BenchControl.TbfComponents.LoadComponentsFromDB(Config.FluentCommon.CreateSession(Users.Entities.DBKind.Config));
|
2014-07-28 07:54:35 +00:00
|
|
|
|
MasterValves = GenericDevices.ValveBase.MasterValves(components);
|
|
|
|
|
|
CoupledValves = GenericDevices.ValveBase.CoupledValves(components);
|
2015-06-29 09:26:08 +00:00
|
|
|
|
ExtendedValves = GenericDevices.ValveBase.ExtendedValves(components);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
/// Find all balances (to initialize tank capacities in the control board)
|
|
|
|
|
|
/// Find the control board
|
2017-03-28 21:47:32 +00:00
|
|
|
|
IList<IScale> balances = new List<IScale>();
|
2014-09-06 15:34:26 +00:00
|
|
|
|
SequenceBase.FlowMeters = new List<IFlowMeter>();
|
2014-07-28 07:54:35 +00:00
|
|
|
|
SequenceBase.RegulValves = new List<IRegulValve>();
|
2014-09-08 11:16:31 +00:00
|
|
|
|
SequenceBase.PumpsWithFM = new List<IPumpFM>();
|
2014-07-28 07:54:35 +00:00
|
|
|
|
SequenceBase.WaterMeters = new List<IWaterMeter>();
|
|
|
|
|
|
SequenceBase.Cameras = new List<ICamera>();
|
2016-12-12 16:25:12 +00:00
|
|
|
|
UInt128 valvesToInvert = 0;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
foreach (var cmpnt in components)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmpnt is Elde.ControlBoardDev) ControlBoard = cmpnt as Elde.ControlBoardDev;
|
2016-01-08 18:18:45 +00:00
|
|
|
|
if (cmpnt is IBenchInfo) ProcessData.BenchInfo = cmpnt as IBenchInfo;
|
2014-09-06 15:34:26 +00:00
|
|
|
|
if (cmpnt is IFlowMeter) SequenceBase.FlowMeters.Add(cmpnt as IFlowMeter);
|
2015-02-03 09:53:02 +00:00
|
|
|
|
if ((cmpnt is IRegulValve) && !(cmpnt is BenchControl.Elde.RegulValveTandem.RegulValveTandem))
|
|
|
|
|
|
{
|
|
|
|
|
|
SequenceBase.RegulValves.Add(cmpnt as IRegulValve);
|
|
|
|
|
|
}
|
2014-09-08 11:16:31 +00:00
|
|
|
|
if (cmpnt is IPumpFM) SequenceBase.PumpsWithFM.Add(cmpnt as IPumpFM);
|
|
|
|
|
|
if (cmpnt is IWaterMeter) SequenceBase.WaterMeters.Add(cmpnt as IWaterMeter);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
if (cmpnt is ICamera) SequenceBase.Cameras.Add(cmpnt as ICamera);
|
|
|
|
|
|
if (cmpnt is GenericDevices.IAmbient) Ambient = cmpnt as GenericDevices.IAmbient;
|
2017-03-28 21:47:32 +00:00
|
|
|
|
if (cmpnt is IScale)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
2017-03-28 21:47:32 +00:00
|
|
|
|
IScale scale = cmpnt as IScale;
|
|
|
|
|
|
balances.Add(scale);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
2017-03-28 21:47:32 +00:00
|
|
|
|
if (scale.ScaleNr == 0) Scale1 = scale;
|
|
|
|
|
|
else if (scale.ScaleNr == 1) Scale2 = scale;
|
|
|
|
|
|
else if (scale.ScaleNr == 2) Scale3 = scale;
|
2014-08-12 12:52:42 +00:00
|
|
|
|
}
|
2014-09-06 11:29:04 +00:00
|
|
|
|
|
|
|
|
|
|
Elde.Valve.Valve eldeValve = (cmpnt as Elde.Valve.Valve);
|
|
|
|
|
|
if ((eldeValve != null) && eldeValve.Inverted) valvesToInvert |= eldeValve.Mask;
|
2015-01-02 22:42:01 +00:00
|
|
|
|
|
|
|
|
|
|
cmpnt.StartChangeHandler(); /// Start handling parameter change events
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Create an array with tank capacities
|
2016-10-07 12:06:54 +00:00
|
|
|
|
double[] tankCapacities = new double[balances.Count];
|
2014-07-28 07:54:35 +00:00
|
|
|
|
for (int i = 0; i < tankCapacities.Length; i++) tankCapacities[i] = balances[i].Capacity;
|
|
|
|
|
|
|
|
|
|
|
|
/// Pre-initialize the control board (= buffer the arguments ctrlBrdComponent, tankCapacities)
|
2016-02-14 18:02:07 +00:00
|
|
|
|
if (ControlBoard != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ControlBoard.InitializeComponent(ctrlBrdComponent, valvesToInvert, tankCapacities);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("Control board component is missing");
|
|
|
|
|
|
}
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-16 12:34:40 +00:00
|
|
|
|
|
|
|
|
|
|
public static string CurrentlyInitializedDeviceName;
|
|
|
|
|
|
///
|
2015-08-24 14:04:31 +00:00
|
|
|
|
public static string InitializeDevices()
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
2017-01-16 12:34:40 +00:00
|
|
|
|
CurrentlyInitializedDeviceName = "-";
|
|
|
|
|
|
|
|
|
|
|
|
bool anyComponentIsInSimulMode = false;
|
2015-08-24 14:04:31 +00:00
|
|
|
|
StringBuilder inSimulMode = new StringBuilder();
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
/// Add all devices to the state machine and initialize them
|
|
|
|
|
|
foreach (var cmpnt in components)
|
|
|
|
|
|
{
|
2015-12-04 16:17:20 +00:00
|
|
|
|
if (cmpnt.DebugLevel == DebugMode.Simulate)
|
2015-08-24 14:04:31 +00:00
|
|
|
|
{
|
|
|
|
|
|
inSimulMode.AppendFormat("{0}{1}", anyComponentIsInSimulMode ? ", " : "", cmpnt.Name);
|
|
|
|
|
|
anyComponentIsInSimulMode = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-16 12:34:40 +00:00
|
|
|
|
IDevice device = cmpnt as IDevice;
|
|
|
|
|
|
if (device != null)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
2017-01-16 12:34:40 +00:00
|
|
|
|
CurrentlyInitializedDeviceName = device.Name;
|
|
|
|
|
|
device.Initialize();
|
|
|
|
|
|
AddDevice(device); /// Only components that were initialized are added
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-01-16 12:34:40 +00:00
|
|
|
|
|
|
|
|
|
|
CurrentlyInitializedDeviceName = "---";
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
2017-03-28 10:38:47 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// (1) Propagate debug levels from parents to children when necessary
|
|
|
|
|
|
/// (2) Set drain valves DrainValve1, DrainValve2 and DrainValve3
|
|
|
|
|
|
///
|
2014-07-28 07:54:35 +00:00
|
|
|
|
foreach (var cmpnt in components)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cmpnt.Cfg is IChildComponentCfg && !string.IsNullOrEmpty(cmpnt.Cfg.ParentName) &&
|
2015-12-04 16:17:20 +00:00
|
|
|
|
(cmpnt.Cfg.DebugLevel == DebugMode.Inherit || cmpnt.Cfg.DebugLevel == DebugMode.AutoDetect))
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
foreach (var par in components)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (par.Cfg.Name.Equals(cmpnt.Cfg.ParentName)) { cmpnt.Cfg.DebugLevel = par.Cfg.DebugLevel; break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-03-28 10:38:47 +00:00
|
|
|
|
|
2017-03-28 21:47:32 +00:00
|
|
|
|
if (cmpnt is IScale)
|
2017-03-28 10:38:47 +00:00
|
|
|
|
{
|
2017-03-28 21:47:32 +00:00
|
|
|
|
IScale balance = cmpnt as IScale;
|
2017-03-28 10:38:47 +00:00
|
|
|
|
|
2017-03-28 21:47:32 +00:00
|
|
|
|
if (balance.ScaleNr == 0)
|
2017-03-28 10:38:47 +00:00
|
|
|
|
{
|
|
|
|
|
|
DrainValve1 = balance.DrainValve;
|
|
|
|
|
|
log.WarnFormat("InitializeBoardEtc() ... Scale1={0} Draining valve1={1}",
|
|
|
|
|
|
balance.Name, (DrainValve1 != null) ? DrainValve1.Name : "---");
|
|
|
|
|
|
}
|
2017-03-28 21:47:32 +00:00
|
|
|
|
else if (balance.ScaleNr == 1)
|
2017-03-28 10:38:47 +00:00
|
|
|
|
{
|
|
|
|
|
|
DrainValve2 = balance.DrainValve;
|
|
|
|
|
|
log.WarnFormat("InitializeBoardEtc() ... Scale2={0} Draining valve2={1}",
|
|
|
|
|
|
balance.Name, (DrainValve2 != null) ? DrainValve2.Name : "---");
|
|
|
|
|
|
}
|
2017-03-28 21:47:32 +00:00
|
|
|
|
else if (balance.ScaleNr == 2)
|
2017-03-28 10:38:47 +00:00
|
|
|
|
{
|
|
|
|
|
|
DrainValve3 = balance.DrainValve;
|
|
|
|
|
|
log.WarnFormat("InitializeBoardEtc() ... Scale3={0} Draining valve3={1}",
|
|
|
|
|
|
balance.Name, (DrainValve3 != null) ? DrainValve3.Name : "---");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
2015-08-24 14:04:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (anyComponentIsInSimulMode)
|
|
|
|
|
|
return inSimulMode.ToString();
|
|
|
|
|
|
else
|
|
|
|
|
|
return null;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-01-06 12:05:27 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Stop devices that were started by InitializeDevices().
|
|
|
|
|
|
/// Works correctly also after exeption from InitializeDevices() as only ...
|
|
|
|
|
|
/// ... correctly started devices were added in 'devices' list.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void StopDevices()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var dev in devices) dev.StopDevice();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Start the state machine
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (stateMachineRunning) return;
|
|
|
|
|
|
|
|
|
|
|
|
workerThread = new Thread(Worker);
|
|
|
|
|
|
workerThread.CurrentCulture = Thread.CurrentThread.CurrentCulture;
|
|
|
|
|
|
workerThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
|
|
|
|
|
|
workerThread.Start();
|
|
|
|
|
|
stateMachineRunning = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void LoadProcedure(bool loadPathsOnly)
|
|
|
|
|
|
{
|
2017-03-16 20:53:12 +00:00
|
|
|
|
ISession session = Config.FluentCommon.CreateSession(Users.Entities.DBKind.Config);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
WtSession = session;
|
|
|
|
|
|
|
2016-12-02 11:52:30 +00:00
|
|
|
|
feedingPaths = session.QueryOver<Config.Entities.FeedingPath>().OrderBy(x => x.ItemNr).Asc.List();
|
|
|
|
|
|
benchPaths = session.QueryOver<Config.Entities.BenchPath>().OrderBy(x => x.ItemNr).Asc.List();
|
|
|
|
|
|
outputPaths = session.QueryOver<Config.Entities.OutputPath>().OrderBy(x => x.ItemNr).Asc.List();
|
|
|
|
|
|
metersPaths = session.QueryOver<Config.Entities.MetersPath>().OrderBy(x => x.ItemNr).Asc.List();
|
|
|
|
|
|
TransitionSequences = session.QueryOver<TransitionSequence>().OrderBy(x => x.ItemNr).Asc.List();
|
2017-02-14 12:25:43 +00:00
|
|
|
|
#if HEAT_METERS
|
2016-12-02 11:52:30 +00:00
|
|
|
|
heatMetersPaths = session.QueryOver<Config.Entities.HeatMetersPath>().OrderBy(x => x.ItemNr).Asc.List();
|
2016-06-28 16:04:52 +00:00
|
|
|
|
#endif
|
2014-08-12 12:52:42 +00:00
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
if (loadPathsOnly) return;
|
|
|
|
|
|
|
2016-12-02 11:52:30 +00:00
|
|
|
|
IList<Procedure> selectedProcs = session.QueryOver<Procedure>()
|
|
|
|
|
|
.Where(x => (x.ProcedureState == ProcedureState.Active))
|
|
|
|
|
|
.And(x => (x.Name == TBF.UiBridge.Bridge.SelectedProcedureName))
|
|
|
|
|
|
.List();
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
if (selectedProcs.Count != 1) return;
|
|
|
|
|
|
|
|
|
|
|
|
Procedure = selectedProcs[0];
|
|
|
|
|
|
Tests = selectedProcs[0].Tests;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static void LoadProcedureParams(Procedure procedure)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
foreach (var cmpnt in components)
|
|
|
|
|
|
{
|
2014-12-31 12:46:33 +00:00
|
|
|
|
cmpnt.Cfg.UpdateProcedureParams(procedure);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static void LoadTestParams(Test test)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
foreach (var cmpnt in components)
|
|
|
|
|
|
{
|
2014-12-31 12:46:33 +00:00
|
|
|
|
cmpnt.Cfg.UpdateTestParams(test);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Processes the selection done by the bench control panel in the main sequence.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="selection">Selection.Q1, .Q2, .Q3 or .Test</param>
|
|
|
|
|
|
/// <returns>The selected test or null</returns>
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static Config.Entities.Test GetTest(Sequences.MainSeq.Selection selection)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
if ((selection == Sequences.MainSeq.Selection.Q1) && (Tests.Count >= 1))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Tests[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
else if ((selection == Sequences.MainSeq.Selection.Q2) && (Tests.Count >= 2))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Tests[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
else if ((selection == Sequences.MainSeq.Selection.Q3) && (Tests.Count >= 3))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Tests[2];
|
|
|
|
|
|
}
|
2016-04-11 07:39:02 +00:00
|
|
|
|
else if (selection == Sequences.MainSeq.Selection.Test || selection == Sequences.MainSeq.Selection.RestOfCycle)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
2014-12-11 08:04:06 +00:00
|
|
|
|
foreach (var test in Tests)
|
|
|
|
|
|
{
|
2015-12-01 21:03:53 +00:00
|
|
|
|
if (Utils.TestTitle(test, 1).Equals(UiBridge.Bridge.SelectedTestName)) return test;
|
2014-12-11 08:04:06 +00:00
|
|
|
|
}
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Called from the sequence to update paths based on the selected test
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="test">Selected test</param>
|
|
|
|
|
|
/// <param name="pfeed"></param>
|
|
|
|
|
|
/// <param name="pben"></param>
|
|
|
|
|
|
/// <param name="pout"></param>
|
|
|
|
|
|
/// <param name="pmtrs"></param>
|
2015-06-25 02:42:28 +00:00
|
|
|
|
/// <param name="transitionBefore">Transition sequence entity</param>
|
|
|
|
|
|
/// <param name="transitionAfter">Transition sequence entity</param>
|
|
|
|
|
|
/// <param name="errorMsg">Error message in case of incorrect configuration</param>
|
|
|
|
|
|
/// <returns>true when loaded configuration is correct (all four paths are defined !=null, etc.)</returns>
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static bool GetPaths(Test test,
|
2016-07-07 07:52:54 +00:00
|
|
|
|
bool heatMetersPathRequired,
|
2015-05-20 14:18:54 +00:00
|
|
|
|
out FeedingPath pfeed,
|
|
|
|
|
|
out BenchPath pben,
|
|
|
|
|
|
out OutputPath pout,
|
|
|
|
|
|
out MetersPath pmtrs,
|
2016-06-28 16:04:52 +00:00
|
|
|
|
out HeatMetersPath phmtrs,
|
|
|
|
|
|
out TransitionSequence transitionBefore,
|
2015-12-04 16:17:20 +00:00
|
|
|
|
out TransitionSequence transitionAfter,
|
2015-05-20 14:18:54 +00:00
|
|
|
|
out string errorMsg)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
pfeed = null;
|
|
|
|
|
|
pben = null;
|
|
|
|
|
|
pout = null;
|
2016-06-28 16:04:52 +00:00
|
|
|
|
phmtrs = null;
|
2015-05-22 08:29:56 +00:00
|
|
|
|
transitionBefore = null;
|
|
|
|
|
|
transitionAfter = null;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
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; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-09-04 11:49:04 +00:00
|
|
|
|
pmtrs = GetMetersPath(test);
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
2017-05-03 20:17:20 +00:00
|
|
|
|
if (pfeed == null) errorMsg = Strings.Cannot_load_feeding_path;
|
|
|
|
|
|
else if (pben == null) errorMsg = Strings.Cannot_load_bench_path;
|
|
|
|
|
|
else if (pout == null) errorMsg = Strings.Cannot_load_output_path;
|
|
|
|
|
|
else if (pmtrs == null) errorMsg = Strings.Cannot_load_sensor_path;
|
|
|
|
|
|
else errorMsg = string.Empty;
|
2016-06-28 16:04:52 +00:00
|
|
|
|
if ((pfeed == null) || (pben == null) || (pout == null) || (pmtrs == null))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2014-07-28 07:54:35 +00:00
|
|
|
|
|
2017-02-14 12:25:43 +00:00
|
|
|
|
#if HEAT_METERS
|
2016-06-28 16:04:52 +00:00
|
|
|
|
foreach (var path in heatMetersPaths)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (test.HeatMetersPath == path.Name) { phmtrs = new HeatMetersPath(path, components); break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
2016-07-07 07:52:54 +00:00
|
|
|
|
if (heatMetersPathRequired && phmtrs == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMsg = "Cannot load heat meters sensors";
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2016-06-28 16:04:52 +00:00
|
|
|
|
|
|
|
|
|
|
foreach (var tr in TransitionSequences)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (tr.Name == test.RelTransBefore) transitionBefore = tr;
|
|
|
|
|
|
if (tr.Name == test.TransitionAfter) transitionAfter = tr;
|
|
|
|
|
|
}
|
2015-05-20 14:18:54 +00:00
|
|
|
|
|
2017-03-28 21:47:32 +00:00
|
|
|
|
if (pout.Scale == null)
|
2015-05-20 14:18:54 +00:00
|
|
|
|
{
|
|
|
|
|
|
errorMsg = string.Format("No balance specified in path {0}", test.OutputPath);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (Program.LocalSettings.RealDensity < 500.0f || Program.LocalSettings.RealDensity > 2000.0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
errorMsg = string.Format("Density was not specified");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
errorMsg = string.Empty;
|
|
|
|
|
|
return true;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2015-09-04 11:49:04 +00:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Updates paths based on the selected test
|
|
|
|
|
|
/// </summary>
|
2015-12-04 16:17:20 +00:00
|
|
|
|
public static MetersPath GetMetersPath(Test test)
|
2015-09-04 11:49:04 +00:00
|
|
|
|
{
|
|
|
|
|
|
MetersPath pmtrs = null;
|
|
|
|
|
|
foreach (var path in metersPaths)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (test.MetersPath == path.Name) { pmtrs = new MetersPath(path, components); break; }
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pmtrs != null)
|
|
|
|
|
|
{
|
2015-12-04 16:17:20 +00:00
|
|
|
|
int count = Math.Min(Config.Data.WMsCount, pmtrs.RegisterReaders.Length);
|
2015-09-04 11:49:04 +00:00
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((pmtrs.RegisterReaders[i] != null) &&
|
2015-12-04 16:17:20 +00:00
|
|
|
|
(pmtrs.RegisterReaders[i].Cfg.DebugLevel == DebugMode.DetectedOff))
|
2015-09-04 11:49:04 +00:00
|
|
|
|
{
|
|
|
|
|
|
pmtrs.RegisterReaders[i] = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return pmtrs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Stops the state machine (and the worker thread)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
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.
|
|
|
|
|
|
*
|
|
|
|
|
|
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<Event> 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<Event> 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<Event> 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()
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Worker thread: calls Start(), Run() and Stop() methods of operations.
|
|
|
|
|
|
/// It uses 'currentState', 'nextState' and 'quitStateMachine' static fields.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
static void Worker()
|
|
|
|
|
|
{
|
|
|
|
|
|
startDateTime = DateTime.Now;
|
2015-12-02 17:03:37 +00:00
|
|
|
|
CycleStartTimeStamp = startDateTime; /// To prevent it is undefined
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
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
|
|
|
|
|
|
{
|
2014-09-06 16:30:13 +00:00
|
|
|
|
SequenceBase.ReferenceFlowmetersCount = SequenceBase.FlowMeters.Count;
|
2016-02-10 18:24:10 +00:00
|
|
|
|
SequenceBase.CalibratedLtrPerRefPulse = new float[SequenceBase.ReferenceFlowmetersCount];
|
2014-09-06 15:34:26 +00:00
|
|
|
|
foreach (var flowmtr in SequenceBase.FlowMeters)
|
|
|
|
|
|
{
|
2014-09-10 10:05:49 +00:00
|
|
|
|
int ix = flowmtr.Idx1;
|
2014-09-06 16:30:13 +00:00
|
|
|
|
if (ix > 0 && ix <= SequenceBase.ReferenceFlowmetersCount)
|
|
|
|
|
|
{
|
2016-02-10 18:24:10 +00:00
|
|
|
|
SequenceBase.CalibratedLtrPerRefPulse[ix - 1] = flowmtr.NominalFlow / 7200.0f;
|
2014-09-06 16:30:13 +00:00
|
|
|
|
}
|
2014-09-06 15:34:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
(new Sequences.MainSeq()).Execute(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (QuitStateMachineException)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Do stuff that is repeated in the state execution loops most often
|
|
|
|
|
|
/// </summary>
|
2017-04-03 13:15:31 +00:00
|
|
|
|
/// <returns>List of Event-s returned from the state operations, null == quit</returns>
|
2014-07-28 07:54:35 +00:00
|
|
|
|
public static IList<Event> WaitRunDevsRunOps()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var device in devices) device.RunDeviceAfter();
|
2017-04-03 13:15:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (WaitNextTick())
|
|
|
|
|
|
{
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Executed when the state machine is stopped
|
|
|
|
|
|
///
|
|
|
|
|
|
foreach (var device in devices) device.RunDeviceBefore();
|
|
|
|
|
|
State.StopOperations();
|
|
|
|
|
|
foreach (var device in devices) device.StopDevice();
|
|
|
|
|
|
stateMachineRunning = false;
|
|
|
|
|
|
|
|
|
|
|
|
throw new QuitStateMachineException();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
foreach (var device in devices) device.RunDeviceBefore();
|
2017-04-03 13:15:31 +00:00
|
|
|
|
|
2014-07-28 07:54:35 +00:00
|
|
|
|
IList<Event> events = State.RunOperations();
|
|
|
|
|
|
return events;
|
2017-04-03 13:15:31 +00:00
|
|
|
|
///
|
2014-07-28 07:54:35 +00:00
|
|
|
|
/// This is followed by a state change in the sequence
|
2017-04-03 13:15:31 +00:00
|
|
|
|
///
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Wait time period - synchronize
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>true when interrupted by 'quitStateMachine', otherwise false</returns>
|
2017-04-03 13:15:31 +00:00
|
|
|
|
public static bool WaitNextTick()
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
currentTimeSec += Period;
|
|
|
|
|
|
|
|
|
|
|
|
TimeSpan timeFromStart = TimeSpan.FromSeconds(currentTimeSec);
|
|
|
|
|
|
DateTime nextLoopDateTime = startDateTime + timeFromStart;
|
|
|
|
|
|
while (DateTime.Now < nextLoopDateTime)
|
|
|
|
|
|
{
|
2017-04-03 13:15:31 +00:00
|
|
|
|
Thread.Sleep(100);
|
|
|
|
|
|
|
|
|
|
|
|
if (quitStateMachine)
|
2014-07-28 07:54:35 +00:00
|
|
|
|
{
|
|
|
|
|
|
wlog.Info("quitStateMachine == true ... going to stop the StateMachine()");
|
2017-04-03 13:15:31 +00:00
|
|
|
|
return true;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wlog.DebugFormat(" currentTime = {0}s", currentTimeSec);
|
2017-04-03 13:15:31 +00:00
|
|
|
|
return false;
|
2014-07-28 07:54:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|