using DTS.Common.Interface.DASFactory; using DTS.Common.Interface.DataRecorders; using DTS.Common.Interface.StatusAndProgressBar; using DTS.Common.Utilities.Logging; using Stateless; using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using DTS.Common.Classes.DSP; namespace DTS.DASLib.Service.StateMachine { public class StateMachineBootstrap { private StateMachine _stateMachine; private readonly IDASFactory _dasFactory; public StateMachineBootstrap(IDASFactory dasFactory = null) { //initialize logger _logger = new TextLogger(@"Logs\StateMachine.log", OnLoggerException, MAX_LOG_FILE_SIZE); _logger.LogStartMessage = GetLogStartMessage(); APILogger.StateWriter = LogStuff; _dasFactory = dasFactory; _stateMachine = new StateMachine(States.Instance.Prepare); States.SetDASFactory(dasFactory); Configure(); APILogger.StateLog("State machine started"); } private void DisplayCurrentState() { Console.WriteLine($"Current state is {_stateMachine.State.ToString()}"); } /// /// turns off excitation for units in configure state /// /// /// /// /// public void TurnOffExcitation( ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction ) { var param = States.Instance.ConfigureStart.Status.ConfigureParameters; param.SkipTurnOnPower = true; var status = States.Instance.ConfigureStart.Status.ConfigureStatus; //if we are running, wait till complete to do go to low power status.DoneEvent.WaitOne(); //now make sure we aren't running ... param.TurnOffExcitation = true; status.CompleteAction = () => { APILogger.StateLog($"Complete"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iState) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog($"StatusAction: {statusEnum.ToString()}"); StatusAction?.Invoke(iState); }; status.StatusExAction = (int iState, object[] objParams) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iState, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.TurnOffExcitation.ToString()}"); _stateMachine.FireAsync(Trigger.TurnOffExcitation); } /// /// turns on excitation for units in configure state /// /// /// /// /// /// public void PrepareForDiagnostics( ErrorCallback ErrorRequiringActionAction, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction ) { var param = States.Instance.ConfigureStart.Status.ConfigureParameters; param.ErrorRequiringActionAction = ErrorRequiringActionAction; param.SetConfiguration = false; param.SkipTurnOnPower = false; param.PrepareForDiagnostics = true; var status = States.Instance.ConfigureStart.Status.ConfigureStatus; status.CompleteAction = () => { APILogger.StateLog($"Complete"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iState) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog($"StatusAction: {statusEnum.ToString()}"); StatusAction?.Invoke(iState); }; status.StatusExAction = (int iState, object[] objParams) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iState, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.ApplyConfiguration.ToString()}"); _stateMachine.FireAsync(Trigger.ApplyConfiguration); } /// /// updates the config for units in configure state /// optionally turns on excitation /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public void UpdateConfig( bool ResetEventLines, bool PrepareForDiagnostics, bool ConfigureDigitalOutputs, bool DoStrictCheck, bool DummyConfig, bool EventConfig, double[] maxAAF, bool TurnOffAAFRealtime, bool SkipTurnOnPower, IDASCommunication[] UnitsToConfigure, IReadOnlyDictionary SampleRateLookup, IReadOnlyDictionary AAFRateLookup, ErrorCallback ErrorRequiringActionAction, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction, DSPFilterType dspFilterType ) { var param = States.Instance.ConfigureStart.Status.ConfigureParameters; param.ResetHardwareEventLines = ResetEventLines; param.PrepareForDiagnostics = PrepareForDiagnostics; param.UnitsToConfigure = UnitsToConfigure; param.ConfigureDigitalOutputs = ConfigureDigitalOutputs; param.ErrorRequiringActionAction = ErrorRequiringActionAction; param.DoStrictCheck = DoStrictCheck; param.DummyConfig = DummyConfig; param.EventConfig = EventConfig; param.TurnOffAAFRealtime = TurnOffAAFRealtime; param.MaxAAF = maxAAF; param.SampleRateLookup = SampleRateLookup; param.AAFRateLookup = AAFRateLookup; param.SkipTurnOnPower = SkipTurnOnPower; param.DSPFilterType = dspFilterType; var status = States.Instance.ConfigureStart.Status.ConfigureStatus; status.CompleteAction = () => { APILogger.StateLog($"Complete"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iState) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog($"StatusAction: {statusEnum.ToString()}"); StatusAction?.Invoke(iState); }; status.StatusExAction = (int iState, object[] objParams) => { var statusEnum = (ConfigureStatusInformation.StatusValues)iState; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iState, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.ApplyConfiguration.ToString()}"); _stateMachine.FireAsync(Trigger.ApplyConfiguration); } /// /// turns an array of generic parameters into a single string for logging /// /// /// /// private string ParamsToString(string prepend, object[] objParams) { var sb = new StringBuilder(); sb.Append(prepend); foreach (var obj in objParams) { sb.Append(", "); switch (obj) { case Common.Utils.Entry entry: sb.Append(entry.IPAddress); break; case IDASCommunication das: sb.Append(das.SerialNumber); break; case IDASHardware hardware: sb.Append(hardware.SerialNumber); break; default: sb.Append(obj.ToString()); break; } } return sb.ToString(); } /// /// max size (bytes?) for state machine log /// private const int MAX_LOG_FILE_SIZE = 4194304; /// /// the state machine logger itself /// private static TextLogger _logger; /// /// any additional work needed to done to log a message /// /// private void LogStuff(string message) { try { _logger?.LogMessage(message); } catch (Exception) { } } /// /// the prepend to a new state machine log /// /// private string GetLogStartMessage() { return string.Format($"Application: StateMachine{Environment.NewLine}OS: {Environment.OSVersion}{Environment.NewLine}MachineName: {Environment.MachineName}{Environment.NewLine}Environment: {Environment.Version}{Environment.NewLine}=================================================================={Environment.NewLine}"); } /// /// what to do if there's an exception while logging /// /// private static void OnLoggerException(Exception ex) { System.Diagnostics.Trace.WriteLine(ex.ToString()); } /// /// pings, connects, and checks out hardware (firmware/version/status/channels, etc) /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public void PingAndConnectAndCheckHardware( string[] Addresses, Tuple[] AddressRanges, bool GoToDownload, string[] KnownSLICEIPAddresses, string[] KnownTDASIPAddresses, bool ProceedWhenDone, bool ReadIds, bool RequireAllDASFound, bool RunAutoSense, bool UseUDPDiscovery, string[] RequiredSerials, HardwareDiscoveryParameters.IsCalDateExpiredDelegate CalDateExpiredQuery, IDASHardware[] ExpectedHardware, HardwareDiscoveryParameters.FirmwareExpectedVersionDelegate UnitExpectedFirmwareQuery, HardwareDiscoveryParameters.UnitExpectedMaxMemoryDelegate UnitExpectedMaxMemoryQuery, HardwareDiscoveryParameters.UnitIsInDbDelegate UnitIsInDbQuery, HardwareDiscoveryParameters.UpdateMaxMemoryDelegate UpdateMaxMemoryAction, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction) { var param = GetPingAndConnectParameters(); param.Addresses = Addresses; param.AddressRanges = AddressRanges; param.Connect = true; param.GoToDownload = GoToDownload; param.KnownSLICEIPAddresses = KnownSLICEIPAddresses; param.KnownTDASIPAddresses = KnownTDASIPAddresses; param.ProceedWhenDone = ProceedWhenDone; param.ReadIds = ReadIds; param.RequireAllDASFound = RequireAllDASFound; param.RunAutoSense = RunAutoSense; param.UseMulticastDiscover = UseUDPDiscovery; param.RequeryDevice = null; param.RequiredSerials = RequiredSerials; param.DoHardwareChecks = true; param.CalDateExpiredQuery = CalDateExpiredQuery; param.ExpectedHardware = ExpectedHardware; param.UnitExpectedFirmwareQuery = UnitExpectedFirmwareQuery; param.UnitExpectedMaxMemoryQuery = UnitExpectedMaxMemoryQuery; param.UnitIsInDbQuery = UnitIsInDbQuery; param.UpdateMaxMemoryAction = UpdateMaxMemoryAction; var status = GetPingAndConnectStatus(); status.CompleteAction = () => { APILogger.StateLog("Finished"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iStatus) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog($"Status: {statusEnum.ToString()}"); StatusAction?.Invoke(iStatus); }; status.StatusExAction = (int iStatus, object[] objParams) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iStatus, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.PingAndConnect.ToString()}"); _stateMachine.FireAsync(Trigger.PingAndConnect); } /// /// just pings and connects to hardware /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public void PingAndConnect( string[] Addresses, Tuple[] AddressRanges, bool GoToDownload, string[] KnownSLICEIPAddresses, string[] KnownTDASIPAddresses, bool ProceedWhenDone, bool ReadIds, bool RequireAllDASFound, bool RunAutoSense, bool UseUDPDiscovery, string[] RequiredSerials, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction ) { var param = GetPingAndConnectParameters(); param.Addresses = Addresses; param.AddressRanges = AddressRanges; param.Connect = true; param.GoToDownload = GoToDownload; param.KnownSLICEIPAddresses = KnownSLICEIPAddresses; param.KnownTDASIPAddresses = KnownTDASIPAddresses; param.ProceedWhenDone = ProceedWhenDone; param.ReadIds = ReadIds; param.RequireAllDASFound = RequireAllDASFound; param.RunAutoSense = RunAutoSense; param.UseMulticastDiscover = UseUDPDiscovery; param.RequeryDevice = null; param.RequiredSerials = RequiredSerials; param.DoHardwareChecks = false; var status = GetPingAndConnectStatus(); status.CompleteAction = () => { APILogger.StateLog("Finished"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iStatus) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog($"Status: {statusEnum.ToString()}"); StatusAction?.Invoke(iStatus); }; status.StatusExAction = (int iStatus, object[] objParams) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iStatus, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.PingAndConnect.ToString()}"); _stateMachine.FireAsync(Trigger.PingAndConnect); } /// /// requires one specific already connected device /// used by hardware discovery tile when a device is reconfigured /// /// /// /// /// /// public void RequeryDevice( IDASCommunication device, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction) { var param = GetPingAndConnectParameters(); param.RequeryDevice = device; param.ReadIds = false; var status = GetPingAndConnectStatus(); status.CompleteAction = () => { APILogger.StateLog("Finished"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); param.RequeryDevice = null; }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iStatus) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog($"{statusEnum.ToString()}"); StatusAction?.Invoke(iStatus); }; status.StatusExAction = (int iStatus, object[] objParams) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iStatus, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.RequeryDevice.ToString()}"); _stateMachine.FireAsync(Trigger.RequeryDevice); } public void StopRealtime() { GetRealtimeStatus().StopRealtime(); } public bool IsInRealtime { get { return GetRealtimeStatus().IsInRealtime; } } public void StartRealtime(List ldas, List moduleIndicies, bool useSingleSampleMode, double realtimeSampleRate, int realtimeDelayBetweenPolls, bool allowMultipleSampleRealtime, byte realtimeSampleRateAAFilterRatio, bool sliceTurnOffAAFRealtime, Action SetRealtimeSampleRateAAF, Action CompleteAction, Dictionary idasToActiveChannels, ServiceBase.Callback StartRealtimeCallback ) { var param = GetRealtimeParameters(); var status = GetRealtimeStatus(); param.UnitsToStartRealtime = ldas; param.ModuleIndices = moduleIndicies; param.UseSingleSampleMode = useSingleSampleMode; param.RealtimeSampleRate = realtimeSampleRate; param.RealtimeDelayBetweenPollsInMilliSecond = realtimeDelayBetweenPolls; param.AllowMultipleSampleRealtime = allowMultipleSampleRealtime; param.IdasToActiveChannels = idasToActiveChannels; param.RealtimeSampleRateAAFilterRatio = realtimeSampleRateAAFilterRatio; param.SliceTurnOffAAFRealtime = sliceTurnOffAAFRealtime; status.CompleteAction = () => { _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.SetRealtimeSampleRateAAF = SetRealtimeSampleRateAAF; status.StartRealtimeCallback = StartRealtimeCallback; _stateMachine.FireAsync(Trigger.StartRealtime); } /// /// pings but does not connect /// /// whether UDP multicast discovery should be used /// specific ips that should be pinged /// ranges of ips that should be pinged (aaa.bbb.ccc.xxx : aa.bb.cc.yyy) /// action to take on completion /// action to be taken on progress /// action to take on status change /// action to take on status change with extended info public void Ping( bool UseUDPDiscovery, string[] ipAddresses, Tuple[] ipRanges, ActionCompleteDelegate CompleteAction, SetProgressValueDelegate ProgressAction, StatusIntDelegate StatusAction, StatusExIntDelegate StatusExAction ) { var param = GetPingAndConnectParameters(); var status = GetPingAndConnectStatus(); param.Addresses = ipAddresses; param.AddressRanges = ipRanges; param.GoToDownload = false; param.ProceedWhenDone = false; param.RequireAllDASFound = false; param.GoToDownload = false; param.Connect = false; param.UseMulticastDiscover = UseUDPDiscovery; param.RequeryDevice = null; status.CompleteAction = () => { APILogger.StateLog($"Finished"); _stateMachine.Fire(Trigger.Finish); CompleteAction?.Invoke(); }; status.ProgressAction = (double d) => { APILogger.StateLog($"Progress: {d}"); ProgressAction?.Invoke(d); }; status.StatusAction = (int iStatus) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog($"{statusEnum.ToString()}"); StatusAction?.Invoke(iStatus); }; status.StatusExAction = (int iStatus, object[] objParams) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; APILogger.StateLog(ParamsToString($"StatusEx: {statusEnum.ToString()}", objParams)); StatusExAction?.Invoke(iStatus, objParams); }; APILogger.StateLog($"CurrentState: {_stateMachine.State.ToString()}"); APILogger.StateLog($"Params: {param.ToString()}"); APILogger.StateLog($"Trigger: {Trigger.PingAndConnect.ToString()}"); _stateMachine.FireAsync(Trigger.PingAndConnect); } private void PingAndConnect(bool bProceedWhenDone, bool useMulticast, Tuple ipRanges, bool connect) { var pingParam = GetPingAndConnectParameters(); pingParam.ProceedWhenDone = bProceedWhenDone; pingParam.UseMulticastDiscover = useMulticast; pingParam.AddressRanges = new[] { ipRanges }; pingParam.Connect = connect; pingParam.RequeryDevice = null; var status = GetPingAndConnectStatus(); status.CompleteAction = () => { _stateMachine.Fire(Trigger.Finish); }; status.ProgressAction = (double d) => { Console.WriteLine($"{d}%"); }; status.StatusAction = (int iStatus) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; Console.WriteLine($"{statusEnum.ToString()}"); }; status.StatusExAction = (int iStatus, object[] param) => { var statusEnum = (HardwareDiscoveryStatusInfo.StatusValues)iStatus; switch (statusEnum) { case HardwareDiscoveryStatusInfo.StatusValues.DiscoveredDevice: var device = (IDiscoveredDevice)param[0]; Console.WriteLine($"Discovered {device.Serial}"); break; case HardwareDiscoveryStatusInfo.StatusValues.PingStatus: var entry = (Common.Utils.Entry)param[0]; var pingStatus = (Common.Utils.PingProgressStates)param[1]; var roundTrip = (long)param[2]; Console.WriteLine($"Ping: {entry.IPAddress}, {pingStatus.ToString()}, {roundTrip}"); break; case HardwareDiscoveryStatusInfo.StatusValues.Connecting: Console.WriteLine($"Connecting: {param[0]}"); break; case HardwareDiscoveryStatusInfo.StatusValues.Connected: Console.WriteLine($"Connected: {param[0]}"); break; } }; _stateMachine.FireAsync(Trigger.PingAndConnect); } private ConfigureStatusInformation GetConfigureStatus() { return States.Instance.Configure.Status.ConfigureStatus; } private ConfigureStatusParameters GetConfigureParameters() { return States.Instance.Configure.Status.ConfigureParameters; } private DiagnoseParameters GetDiagnoseParameters() { return States.Instance.Diagnose.Status.DiagnoseParams; } private HardwareDiscoveryParameters GetPingAndConnectParameters() { return States.Instance.HardwareDiscovery.Status.HardwareDiscoveryParams; } private HardwareDiscoveryStatusInfo GetPingAndConnectStatus() { return States.Instance.HardwareDiscovery.Status.HardwareDiscoveryStatusInfo; } private RealtimeParameters GetRealtimeParameters() { return States.Instance.Realtime.Status.RealtimeParams; } private RealtimeStatusInformation GetRealtimeStatus() { return States.Instance.Realtime.Status.RealtimeStatus; } /// /// resets the state machine to the start /// public void Reset() { _stateMachine.Fire(Trigger.Reset); //all the states share the same status reference right now States.Instance.HardwareDiscovery.Status.Reset(); } /// /// Configure the state machine /// private void Configure() { States.SetDASFactory(_dasFactory); //--------------------PREPARE------------------ _stateMachine.Configure(States.Instance.Prepare) .OnEntry(States.Instance.Prepare.OnEntry) .OnExit(States.Instance.Prepare.OnExit) .PermitReentry(Trigger.Reset) .Permit(Trigger.PingAndConnect, States.Instance.HardwareDiscoveryStart); //--------------------HardwareDiscovery------------------ _stateMachine.Configure(States.Instance.HardwareDiscoveryStart) .OnEntry(States.Instance.HardwareDiscoveryStart.OnEntry) .SubstateOf(States.Instance.HardwareDiscovery) .Permit(Trigger.Cancel, States.Instance.HardwareDiscovery) .PermitDynamicIf(Trigger.Finish, States.Instance.HardwareDiscoveryStart.StateSelector) .Permit(Trigger.Reset, States.Instance.Prepare); _stateMachine.Configure(States.Instance.HardwareDiscovery) .OnEntry(States.Instance.HardwareDiscovery.OnEntry) .OnExit(States.Instance.HardwareDiscovery.OnExit) .Permit(Trigger.PingAndConnect, States.Instance.HardwareDiscoveryStart) .Permit(Trigger.RequeryDevice, States.Instance.HardwareDiscoveryStart) .Permit(Trigger.ApplyConfiguration, States.Instance.ConfigureStart) .Permit(Trigger.Reset, States.Instance.Prepare); //--------------------Configure------------------ _stateMachine.Configure(States.Instance.Configure) .OnEntry(States.Instance.Configure.OnEntry) .OnExit(States.Instance.Configure.OnExit) //trigger resolve channels can be sent by application (or application could just use apply configuration itself) //auto is work done by the application .PermitReentry(Trigger.ResolveChannelsAuto) //trigger resolve channels can be sent by application, this is after work done by the user .PermitReentry(Trigger.ResolveChannelsManual) .Permit(Trigger.ApplyConfiguration, States.Instance.ConfigureStart) .Permit(Trigger.TurnOffExcitation, States.Instance.ConfigureStart) .Permit(Trigger.Reset, States.Instance.Prepare); _stateMachine.Configure(States.Instance.ConfigureStart) .SubstateOf(States.Instance.Configure) .OnEntry(States.Instance.ConfigureStart.OnEntry) .OnExit(States.Instance.ConfigureStart.OnExit) .Permit(Trigger.Cancel, States.Instance.Configure) .Permit(Trigger.Reset, States.Instance.Prepare) .Permit(Trigger.Finish, States.Instance.Configure); //--------------------Diagnose------------------ _stateMachine.Configure(States.Instance.Diagnose) .OnEntry(States.Instance.Diagnose.OnEntry) .OnExit(States.Instance.Diagnose.OnExit) .PermitDynamicIf(Trigger.StartRealtime, States.Instance.Diagnose.StateSelector) .Permit(Trigger.Reset, States.Instance.Prepare); //--------------------Realtime------------------ _stateMachine.Configure(States.Instance.RealtimeStart) .SubstateOf(States.Instance.Realtime) .OnEntry(States.Instance.RealtimeStart.OnEntry) .PermitDynamicIf(Trigger.Finish, States.Instance.RealtimeStart.StateSelector) .Permit(Trigger.Reset, States.Instance.Prepare); _stateMachine.Configure(States.Instance.Realtime) .OnEntry(States.Instance.Realtime.OnEntry) .Permit(Trigger.Arm, States.Instance.Arming) .Permit(Trigger.Reset, States.Instance.Prepare); //--------------------Download------------------ //_stateMachine.Configure(States.Instance.Download) // .OnEntry(States.Instance.Download.OnEntry) // .Permit(Trigger.Download, States.Instance.DownloadStart) // .Permit(Trigger.Reset, States.Instance.Prepare); //_stateMachine.Configure(States.Instance.DownloadStart) // .SubstateOf(States.Instance.Download) // .OnEntry(States.Instance.DownloadStart.OnEntry) // .OnExit(States.Instance.DownloadStart.OnExit) // .Permit(Trigger.Cancel, States.Instance.Download) // .Permit(Trigger.Reset, States.Instance.Prepare) // .Permit(Trigger.Finish, States.Instance.Download); GenerateStateMachineGraph(); } private void GenerateStateMachineGraph() { //Output this value to a file and use a DOT graph renderer tool to create a visual representation of the state machine "dot -T pdf -o DAS.pdf DAS.dot" string graph = Stateless.Graph.UmlDotGraph.Format(_stateMachine.GetInfo()); graph = graph.Replace("DTS.DASLib.Service.StateMachine.", ""); } public void Start() { DisplayCurrentState(); _stateMachine.Fire(Trigger.Reset); SimulatePingAndConnectWithCancel(); Reset(); SimulatePingAndConnectComplete(); Reset(); BasicInfoToDiagnostics(); Reset(); BasicInfoToRealtime(); Reset(); } private void SimulatePingAndConnectComplete() { GetConfigureStatus().StatusAction = (int i) => { var status = (ConfigureStatusInformation.StatusValues)i; Console.WriteLine($"{status.ToString()}"); }; GetConfigureStatus().ProgressAction = (double d) => { Console.WriteLine($"{d}%"); }; DisplayCurrentState(); PingAndConnect(true, true, new Tuple("192.168.1.95", "192.168.1.97"), true); GetPingAndConnectStatus().DoneEvent.WaitOne(); System.Threading.Thread.Sleep(100); DisplayCurrentState(); } private void SimulatePingAndConnectWithCancel() { GetConfigureStatus().StatusAction = (int i) => { var status = (ConfigureStatusInformation.StatusValues)i; Console.WriteLine($"{status.ToString()}"); }; GetConfigureStatus().ProgressAction = (double d) => { Console.WriteLine($"{d}%"); }; DisplayCurrentState(); //Fire the trigger PingAndConnect(false, true, new Tuple("192.168.1.95", "192.168.1.97"), true); DisplayCurrentState(); //allow ping thread to work before canceling System.Threading.Thread.Sleep(2000); _stateMachine.FireAsync(Trigger.Cancel); DisplayCurrentState(); GetPingAndConnectStatus().Cancel(); DisplayCurrentState(); } private void BasicInfoToDiagnostics() { GetConfigureStatus().StatusAction = (int i) => { var status = (ConfigureStatusInformation.StatusValues)i; Console.WriteLine($"{status.ToString()}"); }; GetConfigureStatus().ProgressAction = (double d) => { Console.WriteLine($"{d}%"); }; GetConfigureStatus().StatusExAction = (int status, object[] param) => { var state = (ConfigureStatusInformation.StatusValues)status; Console.Write($"{state.ToString()} "); foreach (var o in param) { if (o is IDASCommunication idas) { Console.Write($"{idas.SerialNumber} "); } if (o is Exception ex) { Console.Write($"{ex.Message}"); } if (o is string s) { Console.Write(s); } } Console.WriteLine(); }; GetPingAndConnectParameters().ReadIds = true; GetPingAndConnectParameters().RequireAllDASFound = false; DisplayCurrentState(); //prepare PingAndConnect(true, true, new Tuple("192.168.1.95", "192.168.1.97"), true); DisplayCurrentState(); //HardwareDiscoveryStart GetPingAndConnectStatus().DoneEvent.WaitOne(); System.Threading.Thread.Sleep(100); DisplayCurrentState(); //Configure ResolveChannelsAuto(); DisplayCurrentState(); //configure ResolveChannelsManual(); DisplayCurrentState(); //configure ApplyConfiguration(); DisplayCurrentState(); //ConfigureStart GetConfigureStatus().DoneEvent.WaitOne(); System.Threading.Thread.Sleep(100); DisplayCurrentState(); //Diagnos } private void BasicInfoToRealtime() { GetConfigureStatus().StatusAction = (int i) => { var status = (ConfigureStatusInformation.StatusValues)i; Console.WriteLine($"{status.ToString()}"); }; GetConfigureStatus().ProgressAction = (double d) => { Console.WriteLine($"{d}%"); }; GetConfigureStatus().StatusExAction = (int status, object[] param) => { var state = (ConfigureStatusInformation.StatusValues)status; Console.Write($"{state.ToString()} "); foreach (var o in param) { if (o is IDASCommunication idas) { Console.Write($"{idas.SerialNumber} "); } if (o is Exception ex) { Console.Write($"{ex.Message}"); } if (o is string s) { Console.Write(s); } } Console.WriteLine(); }; GetPingAndConnectParameters().ReadIds = true; GetPingAndConnectParameters().RequireAllDASFound = false; DisplayCurrentState(); //prepare PingAndConnect(true, true, new Tuple("192.168.1.95", "192.168.1.97"), true); DisplayCurrentState(); //HardwareDiscoveryStart GetPingAndConnectStatus().DoneEvent.WaitOne(); System.Threading.Thread.Sleep(100); DisplayCurrentState(); //Configure ResolveChannelsAuto(); DisplayCurrentState(); //configure ResolveChannelsManual(); DisplayCurrentState(); //configure ApplyConfiguration(); DisplayCurrentState(); //ConfigureStart GetConfigureStatus().DoneEvent.WaitOne(); System.Threading.Thread.Sleep(100); DisplayCurrentState(); //Diagnos //Realtime StartAndStopRealtime(); DisplayCurrentState(); } private void StartAndStopRealtime() { var diagParam = GetDiagnoseParameters(); diagParam.ProceedToRealtimeWhenDone = true; diagParam.AllUnitsPassedDiagnostic = false; var param = GetRealtimeParameters(); var status = GetRealtimeStatus(); var pingAndConnectStatus = GetPingAndConnectStatus(); param.UnitsToStartRealtime = pingAndConnectStatus.UnitsConnected.ToList(); var indices = new List(); indices.Add(0); param.ModuleIndices = indices; param.UseSingleSampleMode = false; param.RealtimeSampleRate = 1000; param.RealtimeDelayBetweenPollsInMilliSecond = 4; param.AllowMultipleSampleRealtime = true; param.RealtimeSampleRateAAFilterRatio = 1; param.SliceTurnOffAAFRealtime = true; var b = new byte[1]; b[0] = 0; var dict = new Dictionary(); dict.Add(pingAndConnectStatus.UnitsConnected[0], b); param.IdasToActiveChannels = dict; status.CompleteAction = () => { Console.WriteLine("Realtime started"); }; status.SetRealtimeSampleRateAAF += (p, q) => { Console.WriteLine("Set RealtimeSampleRateAAF {0},{1}", p, q); }; status.StartRealtimeCallback += (data) => { if (data.Status == ServiceBase.CallbackData.CallbackStatus.AllFinished) { Console.WriteLine("Finished receiving data"); } if (data.Status == ServiceBase.CallbackData.CallbackStatus.NewData) { Console.WriteLine("Receiving new data {0}", data.Data[0].SampleNumber.ToString()); } }; _stateMachine.FireAsync(Trigger.StartRealtime); //5 seconds get the data then stop the real time System.Threading.Thread.Sleep(5000); StopRealtime(); Console.WriteLine("Stopped Realtime"); } private void ResolveChannelsManual() { } private void ResolveChannelsAuto() { } private void ApplyConfiguration() { GetConfigureStatus().CompleteAction = () => { _stateMachine.Fire(Trigger.Finish); }; GetConfigureParameters().ErrorRequiringActionAction = (string errorString, string msg) => DialogResult.OK; GetConfigureParameters().ConfigureDigitalOutputs = true; GetConfigureParameters().DoStrictCheck = true; GetConfigureParameters().DummyConfig = false; GetConfigureParameters().EventConfig = true; GetConfigureParameters().MaxAAF = new[] { 10000D, 100000D, 100000D }; GetConfigureParameters().UnitsToConfigure = GetPingAndConnectStatus().UnitsWithConfiguration; _stateMachine.FireAsync(Trigger.ApplyConfiguration); } } }