2624 lines
108 KiB
C#
2624 lines
108 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Xml.Serialization;
|
|
using System.IO;
|
|
using DTS.Common;
|
|
using DTS.Common.DASResource;
|
|
using DTS.Common.Enums;
|
|
using DTS.Common.Interface.DASFactory;
|
|
using DTS.DASLib.Command.Ribeye;
|
|
using DTS.Common.Utilities.Logging;
|
|
using DTS.Common.Enums.Sensors;
|
|
using DTS.Common.Classes.Connection;
|
|
using DTS.Common.Interface.Connection;
|
|
using DTS.Common.Interface.DASFactory.Diagnostics;
|
|
using DTS.DASLib.Service.Classes.Diagnostics;
|
|
using DTS.Common.Enums.DASFactory;
|
|
using DTS.Common.Interface.DASFactory.ARM;
|
|
using DTS.Common.Interface.DASFactory.Download;
|
|
using DTS.Common.Interface.DASFactory.Config;
|
|
using DTS.Common.ICommunication;
|
|
using DTS.Common.Interface.StatusAndProgressBar;
|
|
using DTS.Common.Enums.Hardware;
|
|
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
|
|
using System.IO.Ports;
|
|
using DTS.Common.Classes.DSP;
|
|
|
|
namespace DTS.DASLib.Service
|
|
{
|
|
/// <summary>
|
|
/// The Ribeye class implements the required services for a Ribeye device
|
|
/// </summary>
|
|
/// <typeparam>Type of connection (e.g. Ethernet)</typeparam>
|
|
public partial class Ribeye<T> : Communication<T>,
|
|
IDASCommunication,
|
|
IConfigurationActions,
|
|
IDiagnosticsActions,
|
|
IRealTimeActions,
|
|
IArmActions,
|
|
IDownloadActions
|
|
where T : IConnection, new()
|
|
{
|
|
|
|
public ExcitationStatus ExcitationStatus { get; set; } = ExcitationStatus.Unknown;
|
|
/// <summary>
|
|
/// <inheritdoc cref="IConfiguration"/>
|
|
/// </summary>
|
|
public string TestDirectory { get; set; }
|
|
public IOptimizationValues OptimizationValues { get; set; }
|
|
/// <summary>
|
|
/// returns true if the unit is capable of reading arm status
|
|
/// 17800 Trigger status is "waiting" but PPRO has indeed triggered
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
bool IDASCommunication.GetCanCheckArmStatus() { return true; }
|
|
void IDASCommunication.SetIsStreamingSupported(bool supported = false)
|
|
{
|
|
IsStreamingSupported = false;
|
|
}
|
|
void IDASCommunication.ReadFirstUseDate()
|
|
{
|
|
IsFirstUseDateSupported = false;
|
|
FirstUseDate = null;
|
|
}
|
|
/// <summary>
|
|
/// indicates date of first use
|
|
/// null indicates the hardware has not been used since calibration
|
|
/// only valid when IsFirstUseDateSupported is true
|
|
/// 15524 DAS "First Use Date"
|
|
/// </summary>
|
|
public DateTime? FirstUseDate { get; set; } = null;
|
|
/// <summary>
|
|
/// returns whether the hardware supports first use or not
|
|
/// for hardware to support first use the hardware must support
|
|
/// storage for user attributes in firmware and also have been
|
|
/// calibrated by software support hardware first use
|
|
/// 15524 DAS "First Use Date"
|
|
/// </summary>
|
|
public bool IsFirstUseDateSupported { get; set; } = false;
|
|
/// <summary>
|
|
/// returns whether or not the hardware and firmware support streaming
|
|
/// </summary>
|
|
public bool IsStreamingSupported { get; set; } = false;
|
|
|
|
public bool ConnectionCheck()
|
|
{
|
|
try
|
|
{
|
|
var querySerialNumber = new QuerySerialNumber(this);
|
|
querySerialNumber.SyncExecute();
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log(ex);
|
|
}
|
|
return false;
|
|
}
|
|
public HardwareTypes GetHardwareType() => HardwareTypes.Ribeye;
|
|
public int[] GetStackChannelConfigTypes() => new int[] { 0 };
|
|
|
|
public int RecordId { get; set; } = HardwareConstants.INVALID_IDASCOMMUNICATION_RECORD_ID;
|
|
void IDiagnosticsActions.ClearTriggerOut(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
void IConfigurationActions.SetFirstUseDate(DateTime firstUseDate, ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Error("Not supported");
|
|
}
|
|
void IDiagnosticsActions.ClearLatches(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// clears any das trigger lines (N/A to ribeye)
|
|
/// </summary>
|
|
void IDiagnosticsActions.ClearDASTriggerLine(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
bool IConfiguration.SupportsAutoDetect => false;
|
|
void IConfigurationActions.AutoDetect(bool QueryConfiguration, ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// queries for any connected devices
|
|
/// currently Ribeye can not discover devices
|
|
/// </summary>
|
|
public void QueryConnectedDevices() { }
|
|
public string MACAddress { get; set; }
|
|
public string[] DownstreamMACAddresses { get; set; }
|
|
public bool IsEthernetDistributor() { return false; }
|
|
public bool IsSlice6Distributor() { return false; }
|
|
public bool IsBattery() { return false; }
|
|
public bool IsTSRAIR() { return false; }
|
|
public bool IsSlice6Air() { return false; }
|
|
public bool IsSlice6AirTc() { return false; }
|
|
public bool IsScheduleEventCountSupported() { return false; }
|
|
public double[] GetNominalRanges(SensorConstants.BridgeType bridge)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
public int MaxModules
|
|
{
|
|
get => 1;
|
|
set {; }
|
|
}
|
|
/// <summary>
|
|
/// phase shift information not known for ribeye, so assume 0 for now
|
|
/// </summary>
|
|
/// <param name="ModuleIndex"></param>
|
|
/// <param name="ActualSampleRate"></param>
|
|
/// <param name="HardwareAAF"></param>
|
|
/// <returns></returns>
|
|
public ulong GetPhaseShiftSamples(uint ModuleIndex, double ActualSampleRate, uint HardwareAAF, ulong originalT0) { return 0; }
|
|
/// <summary>
|
|
/// initiates background flash erase for units that support it
|
|
/// will return immediately after flash erase begins
|
|
/// </summary>
|
|
/// <param name="callbck"></param>
|
|
/// <param name="userData"></param>
|
|
void IArmActions.BeginBackgroundFlashErase(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// returns whether unit is capable of flash erase
|
|
/// </summary>
|
|
bool IArmActions.SupportsBackgroundFlashErase => false;
|
|
/// <summary>
|
|
/// returns whether unit has started background flash erase
|
|
/// </summary>
|
|
bool IArmActions.BackgroundFlashEraseStarted => false;
|
|
DateTime? IArmActions.BackgroundFlashEraseStartTime => null;
|
|
int IConfiguration.GetDASDisplayOrder() { return -1; }
|
|
int[] IConfiguration.GetChannelDisplayOrder() { return new int[] { -1 }; }
|
|
void IConfiguration.SetDASDisplayOrder(int order) { throw new NotSupportedException("Not supported for Ribeye"); }
|
|
void IConfiguration.SetChannelDisplayOrder(int[] order) { throw new NotSupportedException("Not supported for Ribeye"); }
|
|
|
|
public bool RequireDiagnosticRateMatchSampleRate() { return false; }
|
|
public DateTime SystemBaseTime => DateTime.MinValue;
|
|
public bool SupportsTimeSynchronization => false;
|
|
public bool RangeBandwidthLimited => false;
|
|
|
|
void IArmActions.ReadyForArming(ServiceCallback callback, object userData, Guid eventGuid, int armNowTimeout, bool testingMode,
|
|
int maxNumberEvents, bool DummyArm, bool SysMode)
|
|
{
|
|
var info = new RibeyeArmNowPacket(callback, userData, armNowTimeout);
|
|
|
|
LaunchAsyncWorker("Ribeye.ReadyArming", new WaitCallback(AsyncReadyArming), info);
|
|
}
|
|
|
|
private void AsyncReadyArming(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeArmNowPacket;
|
|
info.Success();
|
|
return;
|
|
}
|
|
public bool CheckAAF(float rate) { return true; }
|
|
long IDASCommunication.MaxMemory() { return long.MaxValue; }
|
|
//don't know the actual max rate, but hopefully it doesn't run by itself and is controlled by the
|
|
//max rate of other hardware
|
|
uint IDASCommunication.MaxSampleRate(int numberOfConfiguredChannels) { return uint.MaxValue; }
|
|
uint IDASCommunication.MinSampleRate() { return uint.MinValue; }
|
|
public uint MaxAAFilterRate() { return uint.MaxValue; }
|
|
public float InputLowVoltage { get; set; }
|
|
public float InputMediumVoltage { get; set; }
|
|
public float InputHighVoltage { get; set; }
|
|
public float BatteryLowVoltage { get; set; }
|
|
public float BatteryMediumVoltage { get; set; }
|
|
public float BatteryHighVoltage { get; set; }
|
|
public double MinimumValidInputVoltage { get; set; }
|
|
public double MaximumValidInputVoltage { get; set; }
|
|
public double MinimumValidBatteryVoltage { get; set; }
|
|
public double MaximumValidBatteryVoltage { get; set; }
|
|
public bool AutoArmed { get => false; set { } }
|
|
|
|
/// <summary>
|
|
/// the UDP settings to broadcast auto arm status to on auto arm boot
|
|
/// 17583 Monitor Test UI
|
|
/// </summary>
|
|
public string AutoArmUDPSetting { get; set; } = "239.1.2.3:8504";
|
|
/// <summary>
|
|
/// Auto Arm a single DAS now
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
/// <param name="eventGuid">A unique GUID that this event will be tagged
|
|
/// with</param>
|
|
void IArmActions.AutoArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
|
|
armNowTimeout, bool testingMode, uint diagnosticsDelayMs, int maxNumberEvents, bool repeatEnable, bool preserveDiagnostics)
|
|
{
|
|
throw new NotSupportedException("AutoArmNow not supported for Ribeye");
|
|
}
|
|
|
|
private Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> Ribeye_MinimumProtocols = new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
|
|
|
public override void InitMinProto()
|
|
{
|
|
// Ribeye Protocol Limitations
|
|
MinimumProtocols = Ribeye_MinimumProtocols;
|
|
}
|
|
|
|
private const float RibeyeSampleRate = 10000.0F;
|
|
private const string RIBEYE_CONFIGURATION_FILE = "ribeye.xml";
|
|
#region Configuration
|
|
|
|
/// <summary>
|
|
/// ConfigData contains all configuration information about the Ribeye
|
|
/// </summary>
|
|
public IConfigurationData ConfigData { get; set; }
|
|
|
|
/// <summary>
|
|
/// Verify that the ConfigData property is correctly constructed
|
|
/// </summary>
|
|
/// <param name="DoStrictCheck">Set to true if your're arming</param>
|
|
void IConfigurationActions.VerifyConfig(bool DoStrictCheck)
|
|
{
|
|
VerifyConfig(DoStrictCheck, null);
|
|
}
|
|
|
|
void IConfigurationActions.StoreTestSetupXML(ServiceCallback callback, object userData, string testSetupXML)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
void IConfigurationActions.ResetHardwareLines(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
void IConfigurationActions.CheckAAFilterRate(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
void IConfigurationActions.VerifyConfig(bool DoStrictCheck, ErrorCallback failedChallengeFunc)
|
|
{
|
|
VerifyConfig(DoStrictCheck, failedChallengeFunc);
|
|
}
|
|
void VerifyConfig(bool DoStrictCheck, ErrorCallback failedChallengeFunc)
|
|
{
|
|
// look thru all the config data and make sure it's fit to be used
|
|
// our caller have already checked for null, but...
|
|
if (ConfigData == null)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData is null"
|
|
throw new ArgumentException(Strings.Slice_VerifyConfig_Err1);
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(ConfigData.Description))
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Description is null"
|
|
//throw new ArgumentException(Strings.Slice_VerifyConfig_Err2);
|
|
ConfigData.Description = "";
|
|
}
|
|
|
|
if (DoStrictCheck && string.IsNullOrEmpty(ConfigData.TestID))
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.TestID is null"
|
|
throw new ArgumentException(Strings.Slice_VerifyConfig_Err3);
|
|
//ConfigData.TestID = "Default Test ID";
|
|
}
|
|
|
|
// we don't care about EID's here
|
|
|
|
if (ConfigData.Modules == null || ConfigData.Modules.Length == 0 || ConfigData.Modules.Length > DASInfo.Modules.Length)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Modules is null, empty or too long"
|
|
throw new ArgumentException(Strings.Slice_VerifyConfig_Err4);
|
|
}
|
|
|
|
for (int moduleIdx = 0; moduleIdx < ConfigData.Modules.Length; moduleIdx++)
|
|
{
|
|
var module = ConfigData.Modules[moduleIdx];
|
|
|
|
if (module.ModuleArrayIndex != moduleIdx)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].ModuleNumber doesn't mach index"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err5, moduleIdx));
|
|
}
|
|
|
|
if (module.RecordingMode != DFConstantsAndEnums.RecordingMode.CircularBuffer &&
|
|
module.RecordingMode != DFConstantsAndEnums.RecordingMode.RecorderMode)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Mode has incorrect value"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err7, moduleIdx));
|
|
}
|
|
|
|
if (module.SampleRateHz != RibeyeSampleRate)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].SampleRateHz must be below {1}"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err8, moduleIdx, RibeyeSampleRate));
|
|
}
|
|
|
|
if ((uint)((module.PreTriggerSeconds + module.PostTriggerSeconds) * module.SampleRateHz) > DASInfo.Modules[moduleIdx].MaxRecordingSamples)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}] total number of samples must be below {1}"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err9, moduleIdx, DASInfo.Modules[moduleIdx].MaxRecordingSamples));
|
|
}
|
|
|
|
if (module.Channels == null || module.Channels.Length == 0 || module.Channels.Length > DASInfo.Modules[moduleIdx].NumberOfChannels)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels is null, empty or too long"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err10, moduleIdx));
|
|
}
|
|
|
|
for (int channelIdx = 0; channelIdx < module.Channels.Length; channelIdx++)
|
|
{
|
|
var channel = (DASChannel)module.Channels[channelIdx];
|
|
|
|
if (channel.ConfigurationMode == DFConstantsAndEnums.ConfigMode.Disabled)
|
|
continue;
|
|
|
|
if (channel.OwningModule != module)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].OwningModule doesn't mach owner"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err11, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (channel.ModuleChannelNumber != channelIdx)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].ChannelNumber doesn't mach index"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err12, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (channel.DiagnosticsMode) { throw new ArgumentException("no Diagnostics Mode support for Ribeye"); }
|
|
|
|
if (channel.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal &&
|
|
channel.ConfigurationMode != DFConstantsAndEnums.ConfigMode.DummyArm &&
|
|
channel.ConfigurationMode != DFConstantsAndEnums.ConfigMode.Disabled)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].mode has incorrect value"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err13, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (!(channel is AnalogInputDASChannel))
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}] is not an analog input channel"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err14, moduleIdx, channelIdx));
|
|
}
|
|
|
|
var analog = channel as AnalogInputDASChannel;
|
|
if (analog.TypeOfBridge != SensorConstants.BridgeType.FullBridge)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].Bridge has incorrect value"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err15, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (analog.ShuntIsEnabled)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].BridgeResistanceOhms is outside the allowed range({2}-{3})"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err16, moduleIdx, channelIdx, 0, 0));
|
|
}
|
|
|
|
if (analog.VoltageInsertionCheckEnabled)
|
|
{
|
|
throw new NotSupportedException("No voltage insertion supported for Ribeye");
|
|
}
|
|
|
|
if (analog.IsProportionalToExcitation)
|
|
{
|
|
throw new ArgumentException(string.Format(Strings.Ribeye_VerifyConfig_ProportionalNotSupported, moduleIdx * 3 + channelIdx));
|
|
}
|
|
|
|
if (analog.BypassAAFilter)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}], bypassing AA filter is not supported"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err17, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (analog.DesiredRangeWithHeadroomEU < 0)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].DesiredRange must be positive"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err18, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (DoStrictCheck && string.IsNullOrEmpty(analog.EngineeringUnits))
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].EngineeringUnits can't be null or empty"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err19, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (analog.Excitation != ExcitationVoltageOptions.ExcitationVoltageOption.Volt5)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].Excitation only 5 volts is supported"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err20, moduleIdx, channelIdx));
|
|
}
|
|
|
|
|
|
if (analog.ZeroMethod != ZeroMethodType.AverageOverTime &&
|
|
analog.ZeroMethod != ZeroMethodType.UsePreEventDiagnosticsZero)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}].ZeroMethod has invalid value"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err22, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (DoStrictCheck && analog.ZeroMethod == ZeroMethodType.AverageOverTime)
|
|
{
|
|
if (analog.ZeroAverageStartSeconds >= analog.ZeroAverageStopSeconds)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}] zero average start must be less than zero average stop"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err23, moduleIdx, channelIdx));
|
|
}
|
|
|
|
if (analog.ZeroAverageStopSeconds > module.PostTriggerSeconds)
|
|
{
|
|
// "Slice.VerifyConfig: ConfigData.Module[{0}].Channels[{1}] zero average stop must be less than post-trigger"
|
|
throw new ArgumentException(string.Format(Strings.Slice_VerifyConfig_Err25, moduleIdx, channelIdx));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply the data in the ConfigData property to the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IConfigurationActions.CheckSafetyState(bool bArmed, ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.CheckSafetyState", new WaitCallback(AsyncCheckSafetyState), info);
|
|
}
|
|
|
|
void IConfigurationActions.QueryTestSetup(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// Apply the data in the ConfigData property to the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IConfigurationActions.Configure(ServiceCallback callback, object userData, bool EventConfig, bool DummyConfig, double [] maxAAF, bool configureDigitalOutputs, uint crc, bool turnOffAAFRealtime,
|
|
IStreamingFilterProfile dspFilterType, bool discardDiagnostics, Dictionary<IDASCommunication, ushort> timeChannelIds, Dictionary<IDASCommunication, ushort> dataChannelIds,
|
|
Dictionary<IDASCommunication, UDPStreamProfile> streamProfiles, Dictionary<IDASCommunication, int> streamADCPerPacket, Dictionary<IDASCommunication, ushort> irigTDPIntervals,
|
|
Dictionary<IDASCommunication, string> addresses, Dictionary<IDASCommunication, uint[]> tmnsConfigs,
|
|
Dictionary<IDASCommunication, uint> baudRates, Dictionary<IDASCommunication, uint> dataBits, Dictionary<IDASCommunication, StopBits> stopBits,
|
|
Dictionary<IDASCommunication, Parity> parities, Dictionary<IDASCommunication, Handshake> flowControls, Dictionary<IDASCommunication, UartDataFormat> dataFormats,
|
|
Dictionary<IDASCommunication, ushort> tmatsIntervals
|
|
)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.DiscardDiagnostics = discardDiagnostics;
|
|
LaunchAsyncWorker("Ribeye.Configure", new WaitCallback(AsyncConfigure), info);
|
|
}
|
|
|
|
void IConfigurationActions.ApplyLevelTriggers(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.ApplyLevelTriggers", AsyncApplyLevelTriggers, info);
|
|
}
|
|
|
|
private void AsyncApplyLevelTriggers(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
info.Success();
|
|
}
|
|
private const string KEY_TESTID = "TestID";
|
|
private const string KEY_TEST_DESCRIPTION = "TestDescription";
|
|
private const string KEY_TEST_GUID = "TestGUID";
|
|
private const string KEY_FAULT_FLAGS = "FaultFlags";
|
|
private const string KEY_SAMPLE_RATE = "SampleRate";
|
|
private const string KEY_RECORDING_MODE = "RecordingMode";
|
|
private const string KEY_PRETRIGGER_SECONDS = "PretriggerSeconds";
|
|
private const string KEY_POSTTRIGGER_SECONDS = "PosttriggerSeconds";
|
|
private const string KEY_CONFIGDATA = "ConfigData";
|
|
|
|
private void AsyncConfigure(object configAsyncInfo)
|
|
{
|
|
var info = configAsyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
var Configuration = new Utility.XmlDictionary(); ;
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
Configuration.Dictionary[KEY_TESTID] = ConfigData.TestID;
|
|
Configuration.Dictionary[KEY_TEST_DESCRIPTION] = ConfigData.Description;
|
|
Configuration.Dictionary[KEY_SAMPLE_RATE] = ConfigData.Modules.FirstOrDefault().SampleRateHz;
|
|
Configuration.Dictionary[KEY_RECORDING_MODE] = ConfigData.Modules.FirstOrDefault().RecordingMode;
|
|
Configuration.Dictionary[KEY_PRETRIGGER_SECONDS] = ConfigData.Modules.FirstOrDefault().PreTriggerSeconds;
|
|
Configuration.Dictionary[KEY_POSTTRIGGER_SECONDS] = ConfigData.Modules.FirstOrDefault().PostTriggerSeconds;
|
|
Configuration.Dictionary[KEY_CONFIGDATA] = ConfigurationData.Serialize((ConfigurationData)ConfigData);
|
|
|
|
using (var writer = new StreamWriter(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
serializer.Serialize(writer, Configuration);
|
|
writer.Close();
|
|
}
|
|
|
|
ConfigurationData.SetConfiguration(this, File.ReadAllText(RIBEYE_CONFIGURATION_FILE), ConfigurationData.DIAGNOSTIC_FILESTORE);
|
|
ConfigureHasBeenRun = true;
|
|
if (info.DiscardDiagnostics) { DiagnosticsHasBeenRun = false; }
|
|
info.Success();
|
|
}
|
|
|
|
private void AsyncCheckSafetyState(object configAsyncInfo)
|
|
{
|
|
// ribeye doesn't have safety switch info, so might as well return right away.
|
|
var info = configAsyncInfo as RibeyeServiceAsyncInfo;
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// Retrieve configuration from DAS and store it in the ConfigData property
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IConfigurationActions.QueryConfiguration(ServiceCallback callback, object userData, uint crc, string strConfig, bool bReadIds, bool bDeviceScaleFactors,
|
|
bool differentModuleCountsAreOK)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.QueryConfiguration", new WaitCallback(AsyncQueryConfiguration), info);
|
|
}
|
|
|
|
void IConfigurationActions.UpdateConfigurationFromFile(ServiceCallback callback, object userData,
|
|
string filePath)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.UpdateConfigurationFromFile", new WaitCallback(AsyncUpdateConfigurationFromFile),
|
|
info);
|
|
}
|
|
|
|
private void AsyncUpdateConfigurationFromFile(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
info.Error("Not supported yet");
|
|
return;
|
|
}
|
|
|
|
private void AsyncQueryConfiguration(object configAsyncInfo)
|
|
{
|
|
var info = configAsyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
try
|
|
{
|
|
var Configuration = new Utility.XmlDictionary(); ;
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_CONFIGDATA))
|
|
{
|
|
ConfigData = ConfigurationData.DeserializeFromString((string)Configuration.Dictionary[KEY_CONFIGDATA]);
|
|
}
|
|
else
|
|
{
|
|
ConfigData = MakeDefaultConfigFromInfo();
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_TESTID))
|
|
{
|
|
ConfigData.TestID = Configuration.Dictionary[KEY_TESTID] as string;
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_TEST_DESCRIPTION))
|
|
{
|
|
ConfigData.Description = Configuration.Dictionary[KEY_TEST_DESCRIPTION] as string;
|
|
}
|
|
else
|
|
{
|
|
ConfigData.Description = "";
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_SAMPLE_RATE))
|
|
{
|
|
ConfigData.Modules.FirstOrDefault().SampleRateHz = (uint)Configuration.Dictionary[KEY_SAMPLE_RATE];
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_PRETRIGGER_SECONDS))
|
|
{
|
|
ConfigData.Modules.FirstOrDefault().PreTriggerSeconds = (double)Configuration.Dictionary[KEY_PRETRIGGER_SECONDS];
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_POSTTRIGGER_SECONDS))
|
|
{
|
|
ConfigData.Modules.FirstOrDefault().PostTriggerSeconds = (double)Configuration.Dictionary[KEY_POSTTRIGGER_SECONDS];
|
|
}
|
|
// get scale factors
|
|
try
|
|
{
|
|
var scaleFactors = GetScaleFactors();
|
|
|
|
// set the OwningDAS and OwningModule since it was skipped during serialization
|
|
foreach (var iDASModule in ConfigData.Modules)
|
|
{
|
|
var module = (DASModule)iDASModule;
|
|
module.OwningDAS = this;
|
|
foreach (var iDASchannel in module.Channels)
|
|
{
|
|
var channel = (DASChannel)iDASchannel;
|
|
channel.OwningModule = module;
|
|
|
|
// pick up the scalefactor for this channel
|
|
if (channel is AnalogInputDASChannel analog)
|
|
{
|
|
var dasChannelNumber = DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(module.ModuleArrayIndex, analog.ModuleChannelNumber);
|
|
analog.ScalefactorMilliVoltsPerADC = scaleFactors[dasChannelNumber];
|
|
analog.IDs = RetriveEIDs(dasChannelNumber);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// we don't need no stinking scale factors
|
|
}
|
|
|
|
// get sensor ID's
|
|
if (ConfigData.Modules != null)
|
|
{
|
|
foreach (var iDASModule in ConfigData.Modules)
|
|
{
|
|
var module = (DASModule)iDASModule;
|
|
module.OwningDAS = this; // in case bailed out above
|
|
foreach (var iDASChannel in module.Channels)
|
|
{
|
|
var channel = (DASChannel)iDASChannel;
|
|
channel.OwningModule = module; // in case bailed out above
|
|
var dasChannelNumber = DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(module.ModuleArrayIndex, channel.ModuleChannelNumber);
|
|
channel.IDs = RetriveEIDs(dasChannelNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
private DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
|
|
{
|
|
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
|
|
if (infoModule.TypeOfModule != DFConstantsAndEnums.ModuleType.RibeyeLED)
|
|
{
|
|
throw new Exception("Ribeye.MakeConfigModuleFromInfoModule: Unsupported slice type " + infoModule.TypeOfModule.ToString());
|
|
}
|
|
configModule.Channels = new AnalogInputDASChannel[infoModule.NumberOfChannels];
|
|
for (var channelIdx = 0; channelIdx < infoModule.NumberOfChannels; channelIdx++)
|
|
{
|
|
configModule.Channels[channelIdx] = new AnalogInputDASChannel(configModule, channelIdx);
|
|
}
|
|
|
|
return configModule;
|
|
}
|
|
|
|
private ConfigurationData MakeDefaultConfigFromInfo()
|
|
{
|
|
var conf = new ConfigurationData();
|
|
if (DASInfo != null && DASInfo.Modules != null && DASInfo.Modules.Length > 0)
|
|
{
|
|
conf.Modules = new DASModule[DASInfo.Modules.Length];
|
|
for (var moduleIdx = 0; moduleIdx < DASInfo.Modules.Length; moduleIdx++)
|
|
{
|
|
conf.Modules[moduleIdx] = MakeConfigModuleFromInfoModule((InfoResult.Module)DASInfo.Modules[moduleIdx]);
|
|
}
|
|
}
|
|
return conf;
|
|
}
|
|
|
|
void IConfigurationActions.Reboot(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve the EID's and store it in the ConfigData property
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IConfigurationActions.UpdateIDs(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.UpdateIDs", new WaitCallback(AsyncUpdateIDs), info);
|
|
}
|
|
|
|
void IConfigurationActions.UpdateId(ServiceCallback callback, object userData, DASModule module, DASChannel channel)
|
|
{
|
|
var info = new UpdateIdsInfo(callback, userData, module, channel);
|
|
LaunchAsyncWorker("Ribeye.UpdateId", new WaitCallback(AsyncUpdateId), info);
|
|
}
|
|
private class UpdateIdsInfo : RibeyeServiceAsyncInfo
|
|
{
|
|
public DASModule Module { get; set; }
|
|
public DASChannel Channel { get; set; }
|
|
public UpdateIdsInfo(ServiceCallback callback, object userData, DASModule module, DASChannel channel)
|
|
: base(callback, userData)
|
|
{
|
|
Module = module;
|
|
Channel = channel;
|
|
}
|
|
}
|
|
|
|
private void AsyncUpdateIDs(object configAsyncInfo)
|
|
{
|
|
var info = configAsyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
if (ConfigData == null)
|
|
{
|
|
info.Error("DAS doesn't have any ConfigData");
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
// get sensor ID's
|
|
if (ConfigData.Modules != null)
|
|
{
|
|
foreach (var module in ConfigData.Modules)
|
|
{
|
|
foreach (var channel in module.Channels)
|
|
{
|
|
var dasChannelNumber = DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(module.ModuleArrayIndex, channel.ModuleChannelNumber);
|
|
channel.IDs = RetriveEIDs(dasChannelNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
private void AsyncUpdateId(object configAsyncInfo)
|
|
{
|
|
var info = configAsyncInfo as UpdateIdsInfo;
|
|
|
|
try
|
|
{
|
|
// get sensor ID's
|
|
|
|
var dasChannelNumber = DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(info.Module.ModuleArrayIndex, info.Channel.ModuleChannelNumber);
|
|
info.Channel.IDs = RetriveEIDs(dasChannelNumber);
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
private float[] GetScaleFactors()
|
|
{
|
|
var LEDQuery = new QueryNumberOfLEDs(this);
|
|
LEDQuery.SyncExecute();
|
|
|
|
var ScaleFactors = new float[LEDQuery.NumberOfLEDs * 3];
|
|
|
|
for (var Index = 0; Index < ScaleFactors.Length; Index++)
|
|
{
|
|
ScaleFactors[Index] = (float)(1.0 / 100.0);
|
|
}
|
|
return ScaleFactors;
|
|
}
|
|
|
|
private EID[] RetriveEIDs(byte DASChannelNumber)
|
|
{
|
|
if (RunTestVariables.BypassEIDRead) { return new EID[0]; }
|
|
var idList = new List<EID>();
|
|
uint LEDNumber = (uint)DASChannelNumber / 3;
|
|
uint AxisNumber = (uint)DASChannelNumber % 3;
|
|
|
|
var EID = "E" + SerialNumber + LEDNumber.ToString("00") + AxisNumber.ToString("0");
|
|
idList.Add(new EID(EID));
|
|
return idList.ToArray();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Diagnostics
|
|
|
|
// our public diagnostics member
|
|
/// <summary>
|
|
/// ChannelDiagnostics is used to indicate which diagnostics are requested
|
|
/// </summary>
|
|
public IDiagnosticActions[] ChannelDiagnostics { get; set; }
|
|
|
|
public IArmCheckActions ArmCheckActions { get; set; }
|
|
|
|
public IArmCheckResults ArmCheckResults { get; set; }
|
|
|
|
/// <summary>
|
|
/// ChannelDiagnosticsResults contains the results of a diagnostics service.
|
|
/// </summary>
|
|
public IDiagnosticResult[] ChannelDiagnosticsResults { get; set; }
|
|
|
|
public void SetChannelDiagnosticActions(IDiagnosticActions[] actions, bool setInDb = true)
|
|
{
|
|
DiagnosticsActions.SetChannelDiagnosticActions(this, actions, setInDb);
|
|
}
|
|
public void ClearChannelDiagnosticsResults(bool bClearDb = true)
|
|
{
|
|
DiagnosticsResultActions.ClearChannelDiagnosticsResults(this, bClearDb);
|
|
}
|
|
|
|
public void SetChannelDiagnosticsResults(IDiagnosticResult[] results, bool setInDb)
|
|
{
|
|
DiagnosticsResultActions.SetChannelDiagnosticsResults(this, results, setInDb);
|
|
}
|
|
|
|
public IModuleDiagnosticsResult[] ModuleDiagnosticsResults { get; set; }
|
|
|
|
/// <summary>
|
|
/// BaseInput contains information about diagnostics for the module.
|
|
/// </summary>
|
|
public IBaseInputValues BaseInput { get; set; }
|
|
|
|
#region Clock Sync
|
|
public IDictionary<InputClockSource, bool> DASClockSyncStatus { get; set; } = null;
|
|
public bool ClockSyncInUTC { get; set; } = false;
|
|
public ClockSyncProfile DASClockSyncProfile { get; set; }
|
|
public byte PTPDomainID { get; set; }
|
|
#endregion
|
|
|
|
void IDiagnosticsActions.GetBridgeMeasurement(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.GetBridgeMeasurement", new WaitCallback(AsyncDiagnosAndGetResults), info);
|
|
}
|
|
|
|
void IDiagnosticsActions.MeasureTransferSpeed(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
#region Voltage Check
|
|
public void PerformVoltageCheck(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.PerformVoltageCheck", new WaitCallback(AsyncPerformVoltageCheck), info);
|
|
}
|
|
private void AsyncPerformVoltageCheck(object o)
|
|
{
|
|
RibeyeServiceAsyncInfo info = o as RibeyeServiceAsyncInfo;
|
|
info.Success();
|
|
}
|
|
public void PerformVoltageCheckTAOnly(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.PerformVoltageCheckTAOnly", new WaitCallback(AsyncPerformVoltageCheckTAOnly), info);
|
|
}
|
|
private void AsyncPerformVoltageCheckTAOnly(object o)
|
|
{
|
|
RibeyeServiceAsyncInfo info = o as RibeyeServiceAsyncInfo;
|
|
info.Success();
|
|
}
|
|
void IDiagnosticsActions.PerformArmChecks(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.PerformArmChecks", new WaitCallback(AsyncPerformArmChecks), info);
|
|
}
|
|
void IDiagnosticsActions.SaveTiltSensorDataPre(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.SaveTiltSensorDataPre", new WaitCallback(AsyncSaveTiltSensorDataPre), info);
|
|
}
|
|
void IDiagnosticsActions.SaveTemperaturesPre(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.SaveTemperaturesPre", new WaitCallback(AsyncSaveTemperaturesPre), info);
|
|
}
|
|
#endregion Voltage Check
|
|
|
|
private void AsyncPerformArmChecks(object o)
|
|
{
|
|
if (!(o is RibeyeServiceAsyncInfo info)) { return; }
|
|
info.Success();
|
|
}
|
|
|
|
private void AsyncSaveTiltSensorDataPre(object o)
|
|
{
|
|
if (!(o is RibeyeServiceAsyncInfo info)) { return; }
|
|
info.Success();
|
|
}
|
|
|
|
private void AsyncSaveTemperaturesPre(object o)
|
|
{
|
|
if (!(o is RibeyeServiceAsyncInfo info)) { return; }
|
|
info.Success();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
|
|
/// result in ChannelDiagnosticsResults
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
/// <param name="DiagnosticsAAFilterFrequencyHz">The AA filter frequency for diagnostics. Not used by Ribeye</param>
|
|
/// <param name="DiagnosticsSampleRateHz">The sample rate for diagnostics. Not used by Ribeye</param>
|
|
void IDiagnosticsActions.PrepareForDiagnostics(UInt32 DiagnosticsSampleRateHz,
|
|
float DiagnosticsAAFilterFrequencyHz,
|
|
PrePostResults WhichResult,
|
|
ServiceCallback callback,
|
|
object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.PrepareForDiagnostics", new WaitCallback(AsyncPrepareForDiagnostics), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of PrepareForDiagnostics
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncPrepareForDiagnostics(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
// we're done
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
// like most tv shows, we have been canceled
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
|
|
/// result in ChannelDiagnosticsResults
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
/// <param name="DiagnosticsAAFilterFrequencyHz">The AA filter rate for
|
|
/// diagnostics. Not used by Ribeye</param>
|
|
/// <param name="DiagnosticsSampleRateHz">The sample rate for diagnostics. Not
|
|
/// used by Ribeye</param>
|
|
void IDiagnosticsActions.PrepareForBridgeResistanceMeasurement(UInt32 DiagnosticsSampleRateHz,
|
|
float DiagnosticsAAFilterFrequencyHz,
|
|
ServiceCallback callback,
|
|
object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.PrepareForBridgeResistanceMeasurement", new WaitCallback(AsyncPrepareForBridgeResistanceMeasurement), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of PrepareForBridgeResistanceMeasurement
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncPrepareForBridgeResistanceMeasurement(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
try
|
|
{
|
|
// we're done
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
// like most tv shows, we have been canceled
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
public void SetStatusIndicator(DiagnosticsStatusIndicatorState state, ServiceCallback callback, object userData)
|
|
{
|
|
}
|
|
|
|
public void TurnOffT0Lights(ServiceCallback callback, object userData)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
|
|
/// result in ChannelDiagnosticsResults
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDiagnosticsActions.DiagnosAndGetResults(int EventNumber,
|
|
PrePostResults WhichResult,
|
|
ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.DiagnosAndGetResults", new WaitCallback(AsyncDiagnosAndGetResults), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of DiagnosAndGetResults
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncDiagnosAndGetResults(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
try
|
|
{
|
|
// prepare the result array
|
|
var results = new DiagnosticsResult[ChannelDiagnostics.Length];
|
|
for (var idx = 0; idx < ChannelDiagnostics.Length; idx++)
|
|
{
|
|
results[idx] = new DiagnosticsResult();
|
|
results[idx].DASChannelNumber = ChannelDiagnostics[idx].DASChannelNumber;
|
|
results[idx].EventNumber = DFConstantsAndEnums.EVENT_NUMBER_PRETEST_DIAG; // it's not really an event
|
|
}
|
|
|
|
|
|
// There's only one diagnostic, the current positions
|
|
var Query = new QueryCurrentPositions(this);
|
|
Query.SyncExecute();
|
|
|
|
var ScaleFactors = GetScaleFactors();
|
|
|
|
for (var idx = 0; idx < ChannelDiagnostics.Length; idx++)
|
|
{
|
|
results[idx].ExpectedExcitationMilliVolts = 5000;
|
|
results[idx].MeasuredOffsetMilliVolts = Query.Positions[ChannelDiagnostics[idx].DASChannelNumber];
|
|
|
|
// This is not the real scale factor. But it will make the diagnostics happy. It's OK
|
|
// do to this because the real scale factor is queried elsewhere for use with download
|
|
var ModuleIndex = ChannelDiagnostics[idx].DASChannelNumber / ConfigData.Modules[0].NumberOfChannels();
|
|
var ChannelIndex = ChannelDiagnostics[idx].DASChannelNumber % 3;
|
|
AnalogInputDASChannel channel = ConfigData.Modules[ModuleIndex].Channels[ChannelIndex] as AnalogInputDASChannel;
|
|
if (null == channel)
|
|
{
|
|
results[idx].ScalefactorMilliVoltsPerADC = ScaleFactors[ChannelDiagnostics[idx].DASChannelNumber];
|
|
}
|
|
else
|
|
{
|
|
results[idx].ScalefactorMilliVoltsPerADC = channel.SensorCapacityEU / Constants.ADC_MIDPOINT;
|
|
// Need to update this value for consistency
|
|
channel.ScalefactorMilliVoltsPerADC = results[idx].ScalefactorMilliVoltsPerADC;
|
|
channel.NoiseAsPercentOfFullScale = null != results[idx].NoisePercentFullScale ? (double)results[idx].NoisePercentFullScale : 0D;
|
|
}
|
|
results[idx].FinalOffsetADC = (short)(results[idx].MeasuredOffsetMilliVolts / results[idx].ScalefactorMilliVoltsPerADC);
|
|
if (channel.RemoveOffset)
|
|
{
|
|
var ADC = (double)results[idx].MeasuredOffsetMilliVolts / results[idx].ScalefactorMilliVoltsPerADC;
|
|
var devPercent = 100D * ADC / short.MaxValue;
|
|
results[idx].AutoZeroPercentDeviation = devPercent;
|
|
}
|
|
else { results[idx].AutoZeroPercentDeviation = null; }
|
|
}
|
|
|
|
SetChannelDiagnosticsResults(results, true);
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
// like most tv shows, we have been canceled
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve the results from the implicit pre and post event diagnostics
|
|
/// </summary>
|
|
/// <param name="EventNumber">Which event number to Retrieve from</param>
|
|
/// <param name="WhichResult">The pre or post test results?</param>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDiagnosticsActions.GetEventDiagnosticsResults(int EventNumber,
|
|
PrePostResults WhichResult,
|
|
ServiceCallback callback,
|
|
object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.GetEventDiagnosticsResults", new WaitCallback(AsyncGetEventDiagnosticsResults), info);
|
|
}
|
|
|
|
private void AsyncGetEventDiagnosticsResults(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
DiagnosticsResult[] resultArray = null;
|
|
|
|
var scaleFactors = GetScaleFactors();
|
|
|
|
resultArray = new DiagnosticsResult[scaleFactors.Length];
|
|
for (int idx = 0; idx < scaleFactors.Length; idx++)
|
|
{
|
|
resultArray[idx] = new DiagnosticsResult();
|
|
resultArray[idx].DASChannelNumber = idx;
|
|
resultArray[idx].EventNumber = 1;
|
|
resultArray[idx].ScalefactorMilliVoltsPerADC = scaleFactors[idx];
|
|
}
|
|
|
|
SetChannelDiagnosticsResults(resultArray, true);
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
#region Realtime
|
|
/// <summary>
|
|
/// indicates whether the DAS supports streaming
|
|
/// 10572 implement SW side for single command streaming realtime
|
|
/// </summary>
|
|
public bool SupportsIndividualChannelRealtimeStreaming => false;
|
|
public bool SupportsHardwareInputCheck() { return false; }
|
|
public bool ControlsDAQ() { return true; }
|
|
public bool SupportsAutoArm() { return false; }
|
|
public bool SupportsLevelTrigger() { return false; }
|
|
public bool SupportsMultipleEvents() { return false; }
|
|
public bool SupportsMultipleConfigurations() { return false; }
|
|
public bool SupportsRealtime() { return false; }
|
|
public bool SupportsStartInversion() => HardwareConstants.SupportsStartInversion(GetHardwareType(), ProtocolVersion);
|
|
public bool SupportsTriggerInversion() => HardwareConstants.SupportsTriggerInversion(GetHardwareType(), ProtocolVersion);
|
|
public bool InvertTrigger
|
|
{
|
|
get => false;
|
|
set { if (value) { throw new NotSupportedException("Ribeye doesn't support trigger inversion"); } }
|
|
}
|
|
public bool InvertStart
|
|
{
|
|
get => false;
|
|
set { if (value) { throw new NotSupportedException("Ribeye doesn't support start inversion"); } }
|
|
}
|
|
|
|
public bool IgnoreShortedStart
|
|
{
|
|
get => false;
|
|
set { if (value) { throw new NotSupportedException("Ribeye doesn't support ignore shorted start"); } }
|
|
}
|
|
public bool IgnoreShortedTrigger
|
|
{
|
|
get => false;
|
|
set { if (value) { throw new NotSupportedException("Ribeye doesn't support ignore shorted trigger"); } }
|
|
}
|
|
|
|
public bool SupportsMultipleSampleRealtime() { return false; }
|
|
|
|
/// <summary>
|
|
/// A list of channels to use with the Realtime service.
|
|
/// </summary>
|
|
public List<int> RealtimeDASChannels { get; set; }
|
|
public List<double> TiltAxisData { get; set; }
|
|
|
|
EventWaitHandle QuitRealtime;
|
|
|
|
private class RealTimeAsyncPacket
|
|
{
|
|
public RibeyeServiceAsyncInfo Info { get; set; }
|
|
public System.Threading.Timer Timer { get; set; }
|
|
public int SamplesPerSecond { get; set; }
|
|
public int MillisecBetweenSamples { get; set; }
|
|
public bool AllowMultipleSampleRealtime { get; set; }
|
|
}
|
|
|
|
void IRealTimeActions.RealTime(int samplesPerSecond,
|
|
int millisecBetweenSamples,
|
|
ServiceCallback callback,
|
|
object userData,
|
|
bool allowMultipleSampleRealtime,
|
|
int moduleIndex,
|
|
ManualResetEvent stopEvent,
|
|
byte[] channels,
|
|
double aaf,
|
|
int minCAllbackUpdateTimeMs,
|
|
bool UseUDPStreaming,
|
|
string hostIPAddress)
|
|
{
|
|
var packet = new RealTimeAsyncPacket();
|
|
packet.Info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
packet.SamplesPerSecond = samplesPerSecond;
|
|
packet.MillisecBetweenSamples = millisecBetweenSamples;
|
|
packet.AllowMultipleSampleRealtime = allowMultipleSampleRealtime;
|
|
QuitRealtime = new EventWaitHandle(false, EventResetMode.ManualReset);
|
|
|
|
LaunchAsyncWorker("Ribeye.RealTime", new WaitCallback(AsyncRealTime), packet);
|
|
}
|
|
|
|
void IRealTimeActions.RealTimePolling(ServiceCallback callback,
|
|
object userData,
|
|
ManualResetEvent stopEvent,
|
|
byte[] channels
|
|
)
|
|
{
|
|
var packet = new RealTimeAsyncPacket();
|
|
packet.Info.Success();
|
|
}
|
|
|
|
void IRealTimeActions.RealTimeTiltPolling(ServiceCallback callback, object userData, ManualResetEvent stopEvent)
|
|
{
|
|
var packet = new RealTimeAsyncPacket();
|
|
packet.Info.Success();
|
|
}
|
|
|
|
private void AsyncRealTime(object asyncInfo)
|
|
{
|
|
var packet = (RealTimeAsyncPacket)asyncInfo;
|
|
|
|
packet.Info.Success();
|
|
}
|
|
|
|
void IRealTimeActions.ExitRealTimeMode(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.ExitRealTimeMode", new WaitCallback(AsyncExitRealTimeMode), info);
|
|
}
|
|
|
|
private void AsyncExitRealTimeMode(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
QuitRealtime.Set();
|
|
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false;// FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
public string UDPStreamAddress { get; }
|
|
void IRealTimeActions.SetUDPStreamProfile(ServiceCallback callback, object userData, UDPStreamProfile streamProfile, string udpAddress, ushort timeChannelId, ushort dataChannelId, uint[] tmnsConfig, ushort irigTimeDataPacketIntervalMs)
|
|
{
|
|
var packet = new RealTimeAsyncPacket();
|
|
packet.Info.Success();
|
|
}
|
|
void IRealTimeActions.GetUDPStreamProfile(ServiceCallback callback, object userData)
|
|
{
|
|
var packet = new RealTimeAsyncPacket();
|
|
packet.Info.Success();
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region Arming
|
|
|
|
/// <summary>
|
|
/// The arm status information
|
|
/// </summary>
|
|
public IArmStatusData DASArmStatus { get; set; }
|
|
|
|
public bool GetIsInArm()
|
|
{
|
|
if (null == DASArmStatus) { return false; }
|
|
return DASArmStatus.IsArmed;
|
|
}
|
|
public bool GetIsInRealtime()
|
|
{
|
|
if (null == DASArmStatus) { return false; }
|
|
return DASArmStatus.IsInRealtime;
|
|
}
|
|
/// <summary>
|
|
/// returns true if the unit is known to be streaming
|
|
/// does not query the hardware, just returns a flag if it has been set
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool GetIsStreaming()
|
|
{
|
|
return false;
|
|
}
|
|
public void SetDASArmStatus(IArmStatusData status, bool bSetInDb)
|
|
{
|
|
ArmStatus.SetArmStatus(this, status, bSetInDb);
|
|
}
|
|
|
|
public void SetInArm(bool WriteToDb)
|
|
{
|
|
if (null == DASArmStatus)
|
|
{
|
|
var armStatus = new ArmStatus()
|
|
{
|
|
IsArmed = true
|
|
};
|
|
ArmStatus.SetArmStatus(this, armStatus, WriteToDb);
|
|
}
|
|
else
|
|
{
|
|
DASArmStatus.IsArmed = true;
|
|
if (WriteToDb)
|
|
{
|
|
SetDASArmStatus();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetInRealtime(bool WriteToDb, bool ExitRealtimeIfPossible)
|
|
{
|
|
if (null == DASArmStatus)
|
|
{
|
|
var armStatus = new ArmStatus()
|
|
{
|
|
IsInRealtime = true
|
|
};
|
|
ArmStatus.SetArmStatus(this, armStatus, WriteToDb);
|
|
}
|
|
else
|
|
{
|
|
DASArmStatus.IsInRealtime = true;
|
|
if (WriteToDb)
|
|
{
|
|
SetDASArmStatus();
|
|
}
|
|
}
|
|
}
|
|
public void SetDASArmStatus()
|
|
{
|
|
ArmStatus.SetArmStatus(this, DASArmStatus, true);
|
|
}
|
|
public DFConstantsAndEnums.CommandStatus AutoArmStatus { get; set; } = DFConstantsAndEnums.CommandStatus.StatusNoError;
|
|
|
|
public FlashEraseStatus DASFlashEraseStatus { get; set; }
|
|
|
|
void IArmActions.BeginFlashErase(ServiceCallback callback, object userData, bool DummyArm)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
void IArmActions.QueryFlashEraseStatus(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
var eraseStatus = new FlashEraseStatus();
|
|
|
|
eraseStatus.PercentComplete = 100.0f;
|
|
eraseStatus.LastError = DFConstantsAndEnums.CommandStatus.StatusNoError;
|
|
|
|
DASFlashEraseStatus = eraseStatus;
|
|
|
|
info.Success();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Arm a single DAS now
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
/// <param name="eventGuid">A unique GUID that this event will be tagged
|
|
/// with</param>
|
|
void IArmActions.ArmNow(ServiceCallback callback, object userData,
|
|
Guid eventGuid, int armNowTimeout, bool testingMode, int maxNumberEvents, bool SysMode)
|
|
{
|
|
var info = new RibeyeArmNowPacket(callback, userData, armNowTimeout);
|
|
|
|
LaunchAsyncWorker("Ribeye.ArmNow", new WaitCallback(AsyncArmNow), info);
|
|
|
|
var Configuration = new Utility.XmlDictionary(); ;
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
Configuration.Dictionary[KEY_TEST_GUID] = eventGuid;
|
|
using (var writer = new StreamWriter(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
serializer.Serialize(writer, Configuration);
|
|
writer.Close();
|
|
}
|
|
}
|
|
|
|
void IArmActions.PrepareForArmNow(ServiceCallback callback, object userData,
|
|
Guid eventGuid, int armNowTimeout, bool testingMode, int maxNumberEvents, bool SysMode)
|
|
{
|
|
var info = new RibeyeArmNowPacket(callback, userData, armNowTimeout);
|
|
|
|
LaunchAsyncWorker("Ribeye.PrepareForArmNow", new WaitCallback(AsyncPrepareForArmNow), info);
|
|
|
|
var Configuration = new Utility.XmlDictionary(); ;
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
Configuration.Dictionary[KEY_TEST_GUID] = eventGuid;
|
|
using (var writer = new StreamWriter(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
serializer.Serialize(writer, Configuration);
|
|
writer.Close();
|
|
}
|
|
}
|
|
void IArmActions.ReArm(ServiceCallback callback, object userData, bool autoArm, bool arm, bool repeatEnable)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Error("NotSupported");
|
|
}
|
|
void IArmActions.PreparedArmNow(ServiceCallback callback, object userData,
|
|
Guid eventGuid, int armNowTimeout, bool testingMode, int maxNumberEvents, bool SysMode)
|
|
{
|
|
var info = new RibeyeArmNowPacket(callback, userData, armNowTimeout);
|
|
|
|
LaunchAsyncWorker("Ribeye.PreparedArmNow", new WaitCallback(AsyncPreparedArmNow), info);
|
|
|
|
var Configuration = new Utility.XmlDictionary(); ;
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
Configuration.Dictionary[KEY_TEST_GUID] = eventGuid;
|
|
using (var writer = new StreamWriter(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
serializer.Serialize(writer, Configuration);
|
|
writer.Close();
|
|
}
|
|
}
|
|
|
|
private void AsyncArmNow(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeArmNowPacket;
|
|
|
|
try
|
|
{
|
|
var Prepare = new PrepareForDataCollection(this, 60000);
|
|
Prepare.SyncExecute();
|
|
|
|
// After we've reset the event list, our (the DAS) EventInfo property is now invalid
|
|
SetEventInfo(null);
|
|
|
|
var ArmNow = new Arm(this, info.ArmNowTimeout);
|
|
|
|
// Ribeye has different logic than we do. Map theirs to ours
|
|
|
|
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer)
|
|
{
|
|
ArmNow.TStopMS = 0;
|
|
ArmNow.TPostMS = (uint)(1000.0 * ConfigData.Modules[0].PostTriggerSeconds);
|
|
}
|
|
else
|
|
{
|
|
ArmNow.TStopMS = (uint)(1000.0 * (ConfigData.Modules[0].PostTriggerSeconds + ConfigData.Modules[0].PreTriggerSeconds));
|
|
ArmNow.TPostMS = (uint)(1000.0 * ConfigData.Modules[0].PostTriggerSeconds);
|
|
}
|
|
|
|
ArmNow.SyncExecute();
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
private void AsyncPrepareForArmNow(object asyncInfo)
|
|
{
|
|
var info = (RibeyeArmNowPacket)asyncInfo;
|
|
|
|
try
|
|
{
|
|
var Prepare = new PrepareForDataCollection(this, 60000);
|
|
Prepare.SyncExecute();
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
private void AsyncPreparedArmNow(object asyncInfo)
|
|
{
|
|
var info = (RibeyeArmNowPacket)asyncInfo;
|
|
|
|
try
|
|
{
|
|
// After we've reset the event list, our (the DAS) EventInfo property is now invalid
|
|
SetEventInfo(null);
|
|
|
|
var ArmNow = new Arm(this, info.ArmNowTimeout);
|
|
|
|
// Ribeye has different logic than we do. Map theirs to ours
|
|
|
|
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer)
|
|
{
|
|
ArmNow.TStopMS = 0;
|
|
ArmNow.TPostMS = (uint)(1000.0 * ConfigData.Modules[0].PostTriggerSeconds);
|
|
}
|
|
else
|
|
{
|
|
ArmNow.TStopMS = (uint)(1000.0 * (ConfigData.Modules[0].PostTriggerSeconds + ConfigData.Modules[0].PreTriggerSeconds));
|
|
ArmNow.TPostMS = (uint)(1000.0 * ConfigData.Modules[0].PostTriggerSeconds);
|
|
}
|
|
|
|
ArmNow.SyncExecute();
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Arm multiple chained DAS now
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.EnableFaultChecking(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.EnableFaultChecking", new WaitCallback(AsyncEnableFaultChecking), info);
|
|
}
|
|
|
|
void IArmActions.CheckAlreadyLevelTriggered(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
LaunchAsyncWorker("Ribeye.CheckAlreadyLevelTriggered", new WaitCallback(AsyncCheckAlreadyLevelTriggered), info);
|
|
|
|
}
|
|
private void AsyncCheckAlreadyLevelTriggered(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
try
|
|
{
|
|
foreach (var m in ConfigData.Modules)
|
|
{
|
|
foreach (var ch in m.Channels)
|
|
{
|
|
if (ch is AnalogInputDASChannel)
|
|
{
|
|
(ch as AnalogInputDASChannel).AlreadyLevelTriggered = false;
|
|
}
|
|
}
|
|
}
|
|
info.Success();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
private void AsyncEnableFaultChecking(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// DisAutoArm the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.DisAutoArm(ServiceCallback callback, object userData)
|
|
{
|
|
throw new NotSupportedException("DisAutoArm not supported for Ribeye");
|
|
}
|
|
/// <summary>
|
|
/// Disarm the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.Disarm(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.EnableDisarm", new WaitCallback(AsyncDisarm), info);
|
|
}
|
|
|
|
private void AsyncDisarm(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
var DisarmCommand = new Disarm(this);
|
|
DisarmCommand.SyncExecute();
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
void IArmActions.GetExtendedFaultIds(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.GetExtendedFaultIds", new WaitCallback(RibeyeAsyncGetExtendedFaultIds), info);
|
|
}
|
|
|
|
private void RibeyeAsyncGetExtendedFaultIds(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
info.Success();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve the current arm status from the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.GetArmStatus(ServiceCallback callback, object userData, uint inputVoltageCutoff, int maxTimeout)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.GetArmStatus", new WaitCallback(RibeyeAsyncGetArmStatus), info);
|
|
}
|
|
|
|
private void RibeyeAsyncGetArmStatus(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
var armStatus = new ArmStatus();
|
|
var Status = new QueryArmAndTriggerStatus(this);
|
|
Status.IO_Timeout = 3000;
|
|
try
|
|
{
|
|
Status.SyncExecute();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Flush(500);
|
|
Status = new QueryArmAndTriggerStatus(this);
|
|
Status.IO_Timeout = 3000;
|
|
Status.SyncExecute();
|
|
}
|
|
armStatus.IsArmed = Status.IsArmed;
|
|
armStatus.IsFaulted = false;
|
|
armStatus.IsRecording = Status.IsRecording;
|
|
armStatus.IsTriggered = Status.IsTriggered;
|
|
armStatus.IsInRealtime = false;
|
|
armStatus.IsRearming = false;
|
|
|
|
// !!!! Do something better!!!!!
|
|
armStatus.TotalSamples = 300000;
|
|
armStatus.CurrentSample = 0;
|
|
armStatus.SampleRate = (uint)RibeyeSampleRate;
|
|
armStatus.TimeRemainingSeconds = 30;
|
|
|
|
armStatus.EventNumber = 0;
|
|
armStatus.RecordingMode = 0;
|
|
|
|
SetDASArmStatus(armStatus, true);
|
|
|
|
Thread.Sleep(50);
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve the current arm status from the DAS
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.GetAutoArmStatus(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.GetAutoArmStatus", new WaitCallback(RibeyeAsyncGetAutoArmStatus), info);
|
|
}
|
|
|
|
private void RibeyeAsyncGetAutoArmStatus(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
AutoArmStatus = DFConstantsAndEnums.CommandStatus.StatusUnimplemented;
|
|
info.Success();
|
|
}
|
|
/// <summary>
|
|
/// Set the DAS to low power mode
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.EnterLowPowerMode(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.LowPowerMode", new WaitCallback(RibeyeAsyncLowPowerMode), info);
|
|
}
|
|
|
|
private void RibeyeAsyncLowPowerMode(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
DiagnosticsHasBeenRun = false;
|
|
try
|
|
{
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tells the DAS to start record
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.StartRecord(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.StartRecord", new WaitCallback(RibeyeAsyncStartRecord), info);
|
|
}
|
|
|
|
private void RibeyeAsyncStartRecord(object asyncInfo)
|
|
{
|
|
// ribeye doesn't have software start. Trigger is the next best thing.
|
|
RibeyeAsyncTrigger(asyncInfo);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends trigger signal to HW
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IArmActions.Trigger(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.Trigger", new WaitCallback(RibeyeAsyncTrigger), info);
|
|
}
|
|
|
|
private void RibeyeAsyncTrigger(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
Trigger Trigger = new Trigger(this);
|
|
Trigger.SyncExecute();
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Trigger check
|
|
|
|
// our public trigger check member
|
|
public ITriggerCheckResult TriggerResult { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region Downloading
|
|
void IDownloadActions.SetEventInfo(int eventIndex,
|
|
string id,
|
|
Guid guid,
|
|
ulong totalSamples,
|
|
ulong[] triggerSamples,
|
|
ulong startRecordSample,
|
|
UInt32 eventHasDownloaded,
|
|
ServiceCallback callback,
|
|
object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Error("Setting event info not supported on Ribeye");
|
|
}
|
|
private class RibeyeDownloadState : RibeyeServiceAsyncInfo
|
|
{
|
|
public IDownloadRequest Request;
|
|
public ulong SamplesDownloaded; // how many samples have we downloaded so far
|
|
|
|
public DownloadTestData DownloadCommand;
|
|
|
|
public RibeyeDownloadState(ServiceCallback cb, object cbObj, IDownloadRequest _Request)
|
|
: base(cb, cbObj)
|
|
{
|
|
Request = _Request;
|
|
SamplesDownloaded = 0;
|
|
DownloadCommand = null;
|
|
}
|
|
}
|
|
|
|
public IDownloadRequest WhatToDownload { get; set; }
|
|
|
|
public void SetWhatToDownload(IDownloadRequest request, bool bSetInDb = true)
|
|
{
|
|
DownloadRequest.SetWhatToDownload(this, request, bSetInDb);
|
|
}
|
|
public IDownloadReport EventInfo { get; set; }
|
|
|
|
public void SetEventInfo(IDownloadReport eventInfo, bool bSetInDb = true)
|
|
{
|
|
DownloadReport.SetEventInfo(this, eventInfo, bSetInDb);
|
|
}
|
|
public bool[] EventDownloadedStatus { get; set; }
|
|
|
|
public void SetEventDownloadStatus(bool[] status, bool storeInDb = true)
|
|
{
|
|
DownloadReport.SetEventDownloadStatus(this, status, storeInDb);
|
|
}
|
|
|
|
public void SetEventGuids(Guid[] guids, bool storeInDb = true)
|
|
{
|
|
DownloadReport.SetEventGuids(this, guids, storeInDb);
|
|
}
|
|
public Guid[] EventGuids { get; set; }
|
|
public ushort[] FaultFlags { get; set; }
|
|
|
|
public void SetEventFaultFlags(ushort[] flags, bool storeInDb = true)
|
|
{
|
|
DownloadReport.SetEventFaultFlags(this, flags, storeInDb);
|
|
}
|
|
|
|
public byte[] ArmAttempts { get; set; }
|
|
|
|
uint[] IDownload.ExtendedFaultFlags1 { get; set; }
|
|
uint[] IDownload.ExtendedFaultFlags2 { get; set; }
|
|
uint[] IDownload.ExtendedFaultFlags3 { get; set; }
|
|
uint[] IDownload.ExtendedFaultFlags4 { get; set; }
|
|
void IDownload.SetExtendedFaultFlags(uint[][] flags)
|
|
{
|
|
DownloadExtendedFaultFunctions.SetExtendedFaultFlags(flags, this);
|
|
}
|
|
|
|
public void SetEventArmAttemps(byte[] armAttempts, bool storeInDb = true)
|
|
{
|
|
DownloadReport.SetEventArmAttempts(this, armAttempts, storeInDb);
|
|
}
|
|
/// <summary>
|
|
/// Download the data specified in the WhatToDownload property
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDownloadActions.Download(ServiceCallback callback, object userData)
|
|
{
|
|
var state = new RibeyeDownloadState(callback, userData, WhatToDownload);
|
|
LaunchAsyncWorker("Ribeye.Download", new WaitCallback(Download), state);
|
|
}
|
|
|
|
private void Download(object asyncInfo)
|
|
{
|
|
var state = asyncInfo as RibeyeDownloadState;
|
|
|
|
try
|
|
{
|
|
var NumberOfChannels = EventInfo.Events[WhatToDownload.EventNumber].Modules.Sum(module => module.NumberOfChannels());
|
|
|
|
// these two are per channel of course
|
|
var TotalNumberOfSamples = WhatToDownload.EndSample - WhatToDownload.StartSample + 1;
|
|
|
|
// allocate array to return to user
|
|
var Data = new short[NumberOfChannels][];
|
|
for (var idx = 0; idx < NumberOfChannels; idx++)
|
|
{
|
|
Data[idx] = new short[TotalNumberOfSamples];
|
|
}
|
|
|
|
const uint DownloadChunkMS = 100;
|
|
for (uint CurrentMS = 0; CurrentMS < TotalNumberOfSamples / RibeyeSampleRate * 1000.0; CurrentMS += DownloadChunkMS)
|
|
{
|
|
const int MaximumRetries = 10;
|
|
var Sucess = false;
|
|
var Download = new DownloadTestData(this);
|
|
|
|
for (var CurrentRetryCount = 0; CurrentRetryCount < MaximumRetries && false == Sucess; CurrentRetryCount++)
|
|
{
|
|
|
|
Download = new DownloadTestData(this);
|
|
Download.IO_Timeout = 5000;
|
|
var StartTimeMS = (int)(WhatToDownload.StartSample / RibeyeSampleRate * 1000D + CurrentMS - EventInfo.Events[0].Modules[0].PreTriggerSeconds * 1000D);
|
|
Download.StartTimeMS = StartTimeMS;
|
|
Download.StopTimeMS = (int)Math.Min(StartTimeMS + DownloadChunkMS, (WhatToDownload.EndSample * 1000D / RibeyeSampleRate - EventInfo.Events[0].Modules[0].PreTriggerSeconds * 1000.0));
|
|
try
|
|
{
|
|
Download.SyncExecute();
|
|
Sucess = true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
APILogger.LogString("Ribeye download timed out. Retrying");
|
|
Flush(500);
|
|
}
|
|
}
|
|
|
|
// OK, we have our data block
|
|
var newData = new short[NumberOfChannels][];
|
|
for (var channelIdx = 0; channelIdx < NumberOfChannels; channelIdx++)
|
|
{
|
|
Download.GetChannelData(channelIdx, out newData[channelIdx]);
|
|
}
|
|
state.SamplesDownloaded = (ulong)(CurrentMS * RibeyeSampleRate / 1000);
|
|
state.NewData(newData, state.SamplesDownloaded, ulong.MinValue, ulong.MinValue);
|
|
var ratio = Math.Min(1D, state.SamplesDownloaded / (double)(state.Request.EndSample - state.Request.StartSample + 1));
|
|
state.Progress((int)(ratio * 100D));
|
|
}
|
|
state.Progress(100);
|
|
// send data to user
|
|
state.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
state.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
state.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve info about available events to download
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDownloadActions.QueryDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
if (eventIndex > 0) { info.Error("only single event support - RibEye"); }
|
|
else { LaunchAsyncWorker("Ribeye.QueryDownload", new WaitCallback(RibeyeAsyncQueryDownload), info); }
|
|
}
|
|
|
|
private void RibeyeAsyncQueryDownload(object asyncInfo)
|
|
{
|
|
var info = asyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
var Configuration = new Utility.XmlDictionary();
|
|
var serializer = new XmlSerializer(Configuration.GetType());
|
|
|
|
if (File.Exists(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
try
|
|
{
|
|
using (var sr = new StreamReader(RIBEYE_CONFIGURATION_FILE))
|
|
{
|
|
Configuration = (Utility.XmlDictionary)serializer.Deserialize(sr);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
uint EventCount = 1;
|
|
|
|
var dlReport = new DownloadReport();
|
|
|
|
// we'll also freshen up the cached event GUIDs
|
|
var eventGuids = new Guid[EventCount];
|
|
var faultFlags = new ushort[EventCount];
|
|
try
|
|
{
|
|
dlReport.Events = new DownloadReport.EventInfo[EventCount];
|
|
for (var eventIdx = 0; eventIdx < EventCount; eventIdx++)
|
|
{
|
|
// the object to store it all in
|
|
var eventInfo = new DownloadReport.EventInfo();
|
|
|
|
// get the event level values
|
|
if (Configuration.Dictionary.ContainsKey(KEY_TEST_DESCRIPTION))
|
|
{
|
|
eventInfo.Description = Configuration.Dictionary[KEY_TEST_DESCRIPTION] as string;
|
|
}
|
|
else
|
|
{
|
|
eventInfo.Description = "";
|
|
}
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_TESTID))
|
|
{
|
|
eventInfo.TestID = Configuration.Dictionary[KEY_TESTID] as string;
|
|
}
|
|
|
|
eventInfo.EventNumber = eventIdx;
|
|
|
|
if (Configuration.Dictionary.ContainsKey(KEY_TEST_GUID))
|
|
{
|
|
eventInfo.TestGUID = (Guid)Configuration.Dictionary[KEY_TEST_GUID];
|
|
eventInfo.FaultFlags = (UInt16)Configuration.Dictionary[KEY_FAULT_FLAGS];
|
|
eventInfo.ClearFaults();
|
|
}
|
|
|
|
eventGuids[eventIdx] = eventInfo.TestGUID;
|
|
faultFlags[eventIdx] = 0;
|
|
eventInfo.HasBeenDownloaded = false;
|
|
|
|
var LEDs = new QueryNumberOfLEDs(this);
|
|
LEDs.SyncExecute();
|
|
var Data = new QueryDataAvailable(this);
|
|
Data.SyncExecute();
|
|
|
|
eventInfo.Modules = new DASModule[LEDs.NumberOfLEDs];
|
|
var numberOfSamples = Data.TotalMS / 1000.0 * RibeyeSampleRate;
|
|
var triggerSampleNumber = Data.PreTriggerMS / 1000.0 * RibeyeSampleRate;
|
|
|
|
//this appears to be not be used, so I commented it out to reduce compiler warnings
|
|
// 6/10/2010 - dtm
|
|
//var eventStartRecordSampleNumber = 0;
|
|
|
|
var eventStartTime = DateTime.Now;
|
|
for (var moduleIdx = 0; moduleIdx < eventInfo.Modules.Length; moduleIdx++)
|
|
{
|
|
var module = new DASModule(moduleIdx, this);
|
|
|
|
// now update the module with dynamic data
|
|
module.NumberOfSamples = (ulong)(Data.TotalMS / 1000.0 * RibeyeSampleRate);
|
|
module.TriggerSampleNumbers = new UInt64[1]; // only one so far
|
|
module.TriggerSampleNumbers[0] = (ulong)(Data.PreTriggerMS / 1000.0 * RibeyeSampleRate);
|
|
var phaseshift = GetPhaseShiftSamples(Convert.ToUInt32(module.ModuleArrayIndex),
|
|
Convert.ToDouble(ConfigData.Modules[moduleIdx].SampleRateHz),
|
|
Convert.ToUInt32(ConfigData.Modules[moduleIdx].AAFilterRateHz),
|
|
module.TriggerSampleNumbers[0]);
|
|
module.TriggerSampleNumbers[0] += phaseshift;
|
|
module.StartRecordSampleNumber = 0;
|
|
module.PreTriggerSeconds = Data.PreTriggerMS / 1000.0;
|
|
module.PostTriggerSeconds = (Data.PreTriggerMS + Data.PostTriggerMS) / 1000.0;
|
|
module.Channels = new DASChannel[3];
|
|
module.AAFilterRateHz = ConfigData.Modules[moduleIdx].AAFilterRateHz;
|
|
module.SampleRateHz = ConfigData.Modules[moduleIdx].SampleRateHz;
|
|
module.Channels = (DASChannel[])ConfigData.Modules[moduleIdx].Channels.Clone();
|
|
|
|
// update the channel info
|
|
|
|
for (uint channelIdx = 0; channelIdx < module.Channels.Length; channelIdx++)
|
|
{
|
|
module.Channels[channelIdx].EventStartTime = eventStartTime;
|
|
}
|
|
|
|
// store it in the object
|
|
eventInfo.Modules[moduleIdx] = module;
|
|
}
|
|
|
|
// store it in the object
|
|
dlReport.Events[eventIdx] = eventInfo;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
SetEventGuids(eventGuids);
|
|
SetEventFaultFlags(faultFlags);
|
|
}
|
|
|
|
// now assigned the data to the public property
|
|
SetEventInfo(dlReport);
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
void CopyDownloadChannelDataFromConfigData(AnalogInputDASChannel SourceChannel, ref AnalogInputDASChannel DestinationChannel)
|
|
{
|
|
if (null == SourceChannel)
|
|
{
|
|
throw new ArgumentException("The internal representation of a source channel was expected to be an AnalogInputDASChannel, but it was null");
|
|
}
|
|
|
|
if (null == DestinationChannel)
|
|
{
|
|
throw new ArgumentException("The internal representation of a destination channel was expected to be an AnalogInputDASChannel, but it was null");
|
|
}
|
|
|
|
DestinationChannel.BridgeResistanceOhms = SourceChannel.BridgeResistanceOhms;
|
|
DestinationChannel.ZeroPoint = SourceChannel.ZeroPoint;
|
|
DestinationChannel.BypassAAFilter = SourceChannel.BypassAAFilter;
|
|
DestinationChannel.ConfigurationMode = SourceChannel.ConfigurationMode;
|
|
DestinationChannel.DiagnosticsMode = SourceChannel.DiagnosticsMode;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Figure out if events have been downloaded
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDownloadActions.QueryDownloadedStatus(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.QueryDownloadedStatus", new WaitCallback(AsyncQueryDownloadedStatus), info);
|
|
}
|
|
|
|
private void AsyncQueryDownloadedStatus(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
int EventCount = 1;
|
|
|
|
var eventDownloadedStatus = new bool[EventCount];
|
|
for (var eventIdx = 0; eventIdx < EventCount; eventIdx++)
|
|
{
|
|
eventDownloadedStatus[eventIdx] = true;
|
|
}
|
|
// now assigned the data to the public property
|
|
SetEventDownloadStatus(eventDownloadedStatus);
|
|
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Update the recorded trigger sample numbers in HW
|
|
/// </summary>
|
|
/// <param name="callback">The function to call with information</param>
|
|
/// <param name="userData">Whatever you want to pass along</param>
|
|
void IDownloadActions.SetTriggerSampleNumbers(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.SetTriggerSampleNumbers", new WaitCallback(AsyncSetTriggerSampleNumbers), info);
|
|
}
|
|
|
|
private void AsyncSetTriggerSampleNumbers(object asyncInfo)
|
|
{
|
|
var info = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
try
|
|
{
|
|
info.Success();
|
|
}
|
|
catch (CanceledException)
|
|
{
|
|
info.Cancel();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
info.Error(ex.Message, ex);
|
|
}
|
|
}
|
|
|
|
void IDownloadActions.SetDownloaded(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
info.Success();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Information
|
|
|
|
/// <summary>
|
|
/// well, something interesting going on here
|
|
/// there are multiple definitions for DASInfo property in the inherited interfaces
|
|
/// the other one is Communication_DASInfo from ICommunication
|
|
/// but since that's a different type, I'm presuming this property was intended to hide that one
|
|
/// 6/29/10 - dtm
|
|
/// </summary>
|
|
public new IInfoResult DASInfo { get; set; }
|
|
|
|
public void SetDASInfo(IInfoResult dasInfo, bool bSetInDb = true)
|
|
{
|
|
InfoResult.SetDASInfo(this, dasInfo, bSetInDb);
|
|
}
|
|
public void SetDASInfo() { InfoResult.SetDASInfo(this); }
|
|
#endregion
|
|
|
|
#region Misc
|
|
|
|
/// <summary>
|
|
/// Provides a string representation of this object.
|
|
/// </summary>
|
|
/// <returns>a string representing this object</returns>
|
|
public override string ToString()
|
|
{
|
|
var sn = SerialNumber;
|
|
if (!string.IsNullOrEmpty(sn))
|
|
return sn;
|
|
return "Unknown DAS";
|
|
}
|
|
|
|
/// <summary>
|
|
/// The number of channels that have been configured. For a Ribeye all channels are always configured
|
|
/// </summary>
|
|
/// <returns>The number of channels configured</returns>
|
|
public int NumberOfConfiguredChannels()
|
|
{
|
|
if (ConfigData == null)
|
|
return 0;
|
|
return ConfigData.NumberOfConfiguredChannels();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The number of channels in this ribeye
|
|
/// </summary>
|
|
/// <returns>The number of channels in this ribeye</returns>
|
|
public int NumberOfChannels()
|
|
{
|
|
if (ConfigData == null)
|
|
return 0;
|
|
return ConfigData.NumberOfChannels();
|
|
}
|
|
|
|
/// <summary>
|
|
/// CompareTo delegate for sorting, etc.
|
|
/// </summary>
|
|
/// <param name="das">The das to compare with this das</param>
|
|
/// <returns></returns>
|
|
public int CompareTo(IDASCommunication das)
|
|
{
|
|
if (das == null || string.IsNullOrEmpty(das.SerialNumber) || string.IsNullOrEmpty(SerialNumber))
|
|
return 0;
|
|
return SerialNumber.CompareTo(das.SerialNumber);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tracks if diagnostics have been run
|
|
/// </summary>
|
|
public bool DiagnosticsHasBeenRun { get; set; }
|
|
public bool ConfigureHasBeenRun { get; set; } = false;
|
|
|
|
private class RibeyeArmNowPacket : RibeyeServiceAsyncInfo
|
|
{
|
|
public int ArmNowTimeout { get; set; }
|
|
public RibeyeArmNowPacket(ServiceCallback callback, object userData, int armNowTimeout)
|
|
: base(callback, userData)
|
|
{
|
|
ArmNowTimeout = armNowTimeout;
|
|
}
|
|
}
|
|
private class RibeyeServiceAsyncInfo
|
|
{
|
|
public ServiceCallback Callback { get; set; }
|
|
public object UserData { get; set; }
|
|
public object FunctionData { get; set; }
|
|
public bool DiscardDiagnostics { get; set; } = true;
|
|
public RibeyeServiceAsyncInfo(ServiceCallback _callback, object _userData)
|
|
{
|
|
Callback = _callback;
|
|
UserData = _userData;
|
|
}
|
|
|
|
public void Error(string msg, Exception ex)
|
|
{
|
|
try
|
|
{
|
|
var cbData = new ServiceCallbackData();
|
|
cbData.Status = ServiceCallbackData.CallbackStatus.Failure;
|
|
cbData.ErrorMessage = msg;
|
|
cbData.ErrorException = ex;
|
|
cbData.UserData = UserData;
|
|
Callback(cbData);
|
|
}
|
|
catch (Exception eex)
|
|
{
|
|
APILogger.Log("MessageBox", Strings.RibeyeAsyncInfoError, eex);
|
|
}
|
|
}
|
|
|
|
public void Error(string msg)
|
|
{
|
|
Error(msg, null);
|
|
}
|
|
|
|
public void Progress(int value)
|
|
{
|
|
try
|
|
{
|
|
var progressData = new ServiceCallbackData();
|
|
progressData.Status = ServiceCallbackData.CallbackStatus.ProgressReport;
|
|
progressData.ProgressValue = value;
|
|
progressData.UserData = UserData;
|
|
Callback(progressData);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("MessageBox", Strings.RibeyeAsyncInfoProgressError, ex);
|
|
}
|
|
}
|
|
|
|
public void NewData(short[][] data, ulong samplenumber, ulong timeStamp, ulong sequenceNumber)
|
|
{
|
|
try
|
|
{
|
|
var progressData = new ServiceCallbackData();
|
|
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
|
progressData.ProgressValue = 0;
|
|
progressData.UserData = UserData;
|
|
progressData.AddSampleData(data, samplenumber, timeStamp, sequenceNumber);
|
|
Callback(progressData);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("MessageBox", Strings.RibeyeAsyncInfoNewDataError, ex);
|
|
}
|
|
}
|
|
|
|
public void Success()
|
|
{
|
|
try
|
|
{
|
|
var success = new ServiceCallbackData();
|
|
success.Status = ServiceCallbackData.CallbackStatus.Success;
|
|
success.UserData = UserData;
|
|
Callback(success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("MessageBox", Strings.RibeyeAsyncInfoSuccessError, ex);
|
|
}
|
|
}
|
|
|
|
public void Cancel()
|
|
{
|
|
try
|
|
{
|
|
var cancelReport = new ServiceCallbackData();
|
|
cancelReport.Status = ServiceCallbackData.CallbackStatus.Canceled;
|
|
cancelReport.ProgressValue = 0;
|
|
cancelReport.UserData = UserData;
|
|
Callback(cancelReport);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
APILogger.Log("MessageBox", Strings.RibeyeAsyncInfoCancelError, ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LaunchAsyncWorker(string Invoker, WaitCallback cb, object asyncInfo)
|
|
{
|
|
if (!Connected)
|
|
{
|
|
// "{0}: Not currently connected"
|
|
throw new NotConnectedException(string.Format(Strings.Slice_LaunchAsyncWorker_Err1, Invoker));
|
|
}
|
|
|
|
if (!ThreadPool.QueueUserWorkItem(cb, asyncInfo))
|
|
{
|
|
// "{0}: Unable to enqueue function"
|
|
throw new Exception(string.Format(Strings.Slice_LaunchAsyncWorker_Err2, Invoker));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
void IDiagnosticsActions.SquibFireCheckArm(double delay, double duration, ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.SquibFireCheckArm", new WaitCallback(AsyncSquibFireCheckArm), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of PrepareForDiagnostics
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncSquibFireCheckArm(object asyncInfo)
|
|
{
|
|
var packet = (RibeyeServiceAsyncInfo)asyncInfo;
|
|
|
|
packet.Success();
|
|
}
|
|
|
|
void IDiagnosticsActions.TriggerCheckTrigger(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.TriggerCheckTrigger", new WaitCallback(AsyncTriggerCheckTrigger), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of PrepareForDiagnostics
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncTriggerCheckTrigger(object asyncInfo)
|
|
{
|
|
var packet = asyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
packet.Success();
|
|
}
|
|
|
|
void IDiagnosticsActions.TriggerCheckDownload(double delay, double duration, float dummyAAFilterFrequencyHz, uint dummySampleRateHz, ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.TriggerCheckDownload", new WaitCallback(AsyncTriggerCheckDownload), info);
|
|
}
|
|
|
|
/// <summary>
|
|
/// the working guts of PrepareForDiagnostics
|
|
/// </summary>
|
|
/// <param name="asyncInfo">our async data</param>
|
|
private void AsyncTriggerCheckDownload(object asyncInfo)
|
|
{
|
|
var packet = asyncInfo as RibeyeServiceAsyncInfo;
|
|
|
|
packet.Success();
|
|
}
|
|
|
|
public void CorrectT0s(ServiceCallback callback, object userData)
|
|
{
|
|
var info = new RibeyeServiceAsyncInfo(callback, userData);
|
|
|
|
LaunchAsyncWorker("Ribeye.CorrectT0s", new WaitCallback(AsyncCorrectT0s), info);
|
|
}
|
|
private void AsyncCorrectT0s(object asyncInfo)
|
|
{
|
|
var packet = asyncInfo as RibeyeServiceAsyncInfo;
|
|
packet.Error("Not supported");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// EthernetRibeye is a empty wrapper for a Ribeye connected over ethernet
|
|
/// </summary>
|
|
public class EthernetRibeye : Ribeye<EthernetConnection>
|
|
{
|
|
|
|
}
|
|
|
|
|
|
} |