Files
DP44/DataPRO/IService/StateMachine/StateMachineBootstrap.cs

1074 lines
46 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
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<IDASState, Trigger> _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<IDASState, Trigger>(States.Instance.Prepare);
States.SetDASFactory(dasFactory);
Configure();
APILogger.StateLog("State machine started");
}
private void DisplayCurrentState()
{
Console.WriteLine($"Current state is {_stateMachine.State.ToString()}");
}
/// <summary>
/// turns off excitation for units in configure state
/// </summary>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
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);
}
/// <summary>
/// turns on excitation for units in configure state
/// </summary>
/// <param name="ErrorRequiringActionAction"></param>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
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);
}
/// <summary>
/// updates the config for units in configure state
/// optionally turns on excitation
/// </summary>
/// <param name="ResetEventLines"></param>
/// <param name="PrepareForDiagnostics"></param>
/// <param name="ConfigureDigitalOutputs"></param>
/// <param name="DoStrictCheck"></param>
/// <param name="DummyConfig"></param>
/// <param name="EventConfig"></param>
/// <param name="maxAAF"></param>
/// <param name="TurnOffAAFRealtime"></param>
/// <param name="SkipTurnOnPower"></param>
/// <param name="UnitsToConfigure"></param>
/// <param name="SampleRateLookup"></param>
/// <param name="AAFRateLookup"></param>
/// <param name="ErrorRequiringActionAction"></param>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
public void UpdateConfig(
bool ResetEventLines,
bool PrepareForDiagnostics,
bool ConfigureDigitalOutputs,
bool DoStrictCheck,
bool DummyConfig,
bool EventConfig,
double[] maxAAF,
bool TurnOffAAFRealtime,
bool SkipTurnOnPower,
IDASCommunication[] UnitsToConfigure,
IReadOnlyDictionary<string, double> SampleRateLookup,
IReadOnlyDictionary<string, float> 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);
}
/// <summary>
/// turns an array of generic parameters into a single string for logging
/// </summary>
/// <param name="prepend"></param>
/// <param name="objParams"></param>
/// <returns></returns>
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();
}
/// <summary>
/// max size (bytes?) for state machine log
/// </summary>
private const int MAX_LOG_FILE_SIZE = 4194304;
/// <summary>
/// the state machine logger itself
/// </summary>
private static TextLogger _logger;
/// <summary>
/// any additional work needed to done to log a message
/// </summary>
/// <param name="message"></param>
private void LogStuff(string message)
{
try
{
_logger?.LogMessage(message);
}
catch (Exception)
{
}
}
/// <summary>
/// the prepend to a new state machine log
/// </summary>
/// <returns></returns>
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}");
}
/// <summary>
/// what to do if there's an exception while logging
/// </summary>
/// <param name="ex"></param>
private static void OnLoggerException(Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.ToString());
}
/// <summary>
/// pings, connects, and checks out hardware (firmware/version/status/channels, etc)
/// </summary>
/// <param name="Addresses"></param>
/// <param name="AddressRanges"></param>
/// <param name="GoToDownload"></param>
/// <param name="KnownSLICEIPAddresses"></param>
/// <param name="KnownTDASIPAddresses"></param>
/// <param name="ProceedWhenDone"></param>
/// <param name="ReadIds"></param>
/// <param name="RequireAllDASFound"></param>
/// <param name="RunAutoSense"></param>
/// <param name="UseUDPDiscovery"></param>
/// <param name="RequiredSerials"></param>
/// <param name="CalDateExpiredQuery"></param>
/// <param name="ExpectedHardware"></param>
/// <param name="UnitExpectedFirmwareQuery"></param>
/// <param name="UnitExpectedMaxMemoryQuery"></param>
/// <param name="UnitIsInDbQuery"></param>
/// <param name="UpdateMaxMemoryAction"></param>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
public void PingAndConnectAndCheckHardware(
string[] Addresses,
Tuple<string, string>[] 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);
}
/// <summary>
/// just pings and connects to hardware
/// </summary>
/// <param name="Addresses"></param>
/// <param name="AddressRanges"></param>
/// <param name="GoToDownload"></param>
/// <param name="KnownSLICEIPAddresses"></param>
/// <param name="KnownTDASIPAddresses"></param>
/// <param name="ProceedWhenDone"></param>
/// <param name="ReadIds"></param>
/// <param name="RequireAllDASFound"></param>
/// <param name="RunAutoSense"></param>
/// <param name="UseUDPDiscovery"></param>
/// <param name="RequiredSerials"></param>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
public void PingAndConnect(
string[] Addresses,
Tuple<string, string>[] 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);
}
/// <summary>
/// requires one specific already connected device
/// used by hardware discovery tile when a device is reconfigured
/// </summary>
/// <param name="device"></param>
/// <param name="CompleteAction"></param>
/// <param name="ProgressAction"></param>
/// <param name="StatusAction"></param>
/// <param name="StatusExAction"></param>
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<IDASCommunication> ldas, List<int> moduleIndicies, bool useSingleSampleMode,
double realtimeSampleRate, int realtimeDelayBetweenPolls, bool allowMultipleSampleRealtime, byte realtimeSampleRateAAFilterRatio, bool sliceTurnOffAAFRealtime,
Action<double, double> SetRealtimeSampleRateAAF, Action CompleteAction,
Dictionary<IDASCommunication, byte[]> 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);
}
/// <summary>
/// pings but does not connect
/// </summary>
/// <param name="UseUDPDiscovery">whether UDP multicast discovery should be used</param>
/// <param name="ipAddresses">specific ips that should be pinged</param>
/// <param name="ipRanges">ranges of ips that should be pinged (aaa.bbb.ccc.xxx : aa.bb.cc.yyy)</param>
/// <param name="CompleteAction">action to take on completion</param>
/// <param name="ProgressAction">action to be taken on progress</param>
/// <param name="StatusAction">action to take on status change</param>
/// <param name="StatusExAction">action to take on status change with extended info</param>
public void Ping(
bool UseUDPDiscovery,
string[] ipAddresses,
Tuple<string, string>[] 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<string, string> 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;
}
/// <summary>
/// resets the state machine to the start
/// </summary>
public void Reset()
{
_stateMachine.Fire(Trigger.Reset);
//all the states share the same status reference right now
States.Instance.HardwareDiscovery.Status.Reset();
}
/// <summary>
/// Configure the state machine
/// </summary>
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<string, string>("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<string, string>("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<string, string>("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<string, string>("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<int>();
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<IDASCommunication, byte[]>();
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);
}
}
}