Files
DP44/DataPRO/IService/Classes/SLICE/SliceDB.cs
2026-04-17 14:55:32 -04:00

2013 lines
82 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using DTS.Common;
using DTS.Common.Utilities.Logging;
using DTS.Common.DASResource;
using DTS.Common.ICommunication;
using DTS.DASLib.Command;
using DTS.DASLib.Command.SLICEDB;
using DTS.Common.Enums.Sensors;
using DTS.Common.Interface.Connection;
using DTS.Common.Classes.Connection;
using DTS.Common.Enums;
using DTS.Common.Interface.DASFactory.Diagnostics;
using DTS.Common.Enums.DASFactory;
using DTS.DASLib.Service.Classes.Diagnostics;
using DTS.Common.Interface.DASFactory.ARM;
using DTS.Common.Interface.DASFactory.Download;
using DTS.Common.Interface.DASFactory.Config;
using DTS.Common.Interface.DASFactory;
using DTS.Common.Interface.StatusAndProgressBar;
using DTS.Common.Enums.Hardware;
using DTS.DASLib.Command.SLICE;
using Arm = DTS.DASLib.Command.SLICEDB.Arm;
using Disarm = DTS.DASLib.Command.SLICEDB.Disarm;
using EnableFaultChecking = DTS.DASLib.Command.SLICEDB.EnableFaultChecking;
using DTS.Common.Constant.DASSpecific;
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
using System.IO.Ports;
using DTS.Common.Classes.DSP;
namespace DTS.DASLib.Service
{
public class SliceDB<T> : Communication<T>,
IDASCommunication,
IConfigurationActions,
IDiagnosticsActions,
ITriggerCheckActions,
IRealTimeActions,
IArmActions,
IDownloadActions
where T : IConnection, new()
{
public ExcitationStatus ExcitationStatus { get; set; } = ExcitationStatus.Unknown;
/// <summary>
/// <inheritdoc cref="IConfiguration"/>
/// </summary>
public string TestDirectory { get; set; }
void IDASCommunication.SetIsStreamingSupported(bool supported)
{
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;
public bool IsStreamingSupported { get; set; } = false;
public bool ConnectionCheck()
{
try
{
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines)) return true;
var qosm = new QueryOMAPnStartMon(this, AbstractCommandBase.Default_IO_Timeout);
qosm.SyncExecute();
return true;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
return false;
}
/// <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>
public bool GetCanCheckArmStatus()
{
return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines);
}
public HardwareTypes GetHardwareType()
{
if (SerialNumber.StartsWith("SPE"))
{
return HardwareTypes.SLICE_EthernetController;
}
if (SerialNumber.StartsWith("SPM"))
{
return HardwareTypes.SLICE_Mini_Distributor;
}
return SerialNumber.StartsWith("SLE") ? HardwareTypes.SLICE_LabEthernet : HardwareTypes.SLICE_Distributor;
}
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 SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.ClearLatches(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.SetFirstUseDate(DateTime firstUseDate, ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Error("Not supported");
}
/// <summary>
/// clears any das trigger lines (N/A to sdb ...)
/// </summary>
void IDiagnosticsActions.ClearDASTriggerLine(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
bool IConfiguration.SupportsAutoDetect => false;
void IConfigurationActions.AutoDetect(bool QueryConfiguration, ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <summary>
/// discovers any connected devices
/// SLICE dbs use a different mechanism for discovery devices, it's
/// part of the hello/heartbeat mechanism
/// and no direct query exists currently
/// </summary>
public void QueryConnectedDevices()
{
}
void ITriggerCheckActions.PreStartTriggerCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void ITriggerCheckActions.PostStartTriggerCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.StoreTestSetupXML(ServiceCallback callback, object userData, string testSetupXML)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.CheckAAFilterRate(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.ResetHardwareLines(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.ResetHardwareLines", AsyncResetHardwareLines, info);
}
private static void AsyncResetHardwareLines(object asyncInfo)
{
if (!(asyncInfo is SDBAsyncInfo info))
{
return;
}
info.Success();
}
public string MACAddress { get; set; }
public string[] DownstreamMACAddresses { get; set; }
public bool IsEthernetDistributor() { return true; }
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 bool IgnoreShortedStart
{
get => false;
set { }
}
public bool IgnoreShortedTrigger
{
get => false;
set { }
}
public double[] GetNominalRanges(SensorConstants.BridgeType bridge) { throw new NotImplementedException(); }
public int MaxModules
{
get => 1;
set { }
}
/// <inheritdoc />
/// <summary>
/// slicedbs don't collect or filter data, so safe to say they don't introduce any phase shifts.
/// </summary>
/// <param name="moduleIndex"></param>
/// <param name="actualSampleRate"></param>
/// <param name="hardwareAaf"></param>
/// <param name="originalT0"></param>
/// <returns></returns>
public ulong GetPhaseShiftSamples(uint moduleIndex, double actualSampleRate, uint hardwareAaf, ulong originalT0) { return 0; }
/// <inheritdoc />
/// <summary>
/// initiates background flash erase for units that support it
/// will return immediately after flash erase begins
/// </summary>
/// <param name="callback"></param>
/// <param name="userData"></param>
void IArmActions.BeginBackgroundFlashErase(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// returns whether unit is capable of flash erase
/// </summary>
bool IArmActions.SupportsBackgroundFlashErase => false;
/// <inheritdoc />
/// <summary>
/// returns whether unit has started background flash erase
/// </summary>
bool IArmActions.BackgroundFlashEraseStarted => false;
DateTime? IArmActions.BackgroundFlashEraseStartTime => null;
public int GetDASDisplayOrder() { return -1; }
public int[] GetChannelDisplayOrder() { return new[] { -1 }; }
void IConfiguration.SetDASDisplayOrder(int order) { throw new NotSupportedException("Not supported for SliceDB"); }
void IConfiguration.SetChannelDisplayOrder(int[] order) { throw new NotSupportedException("Not supported for SliceDB"); }
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 SDBAsyncInfo(callback, userData);
info.Success();
}
public bool CheckAAF(float hz) { return true; }
public void CorrectT0s(ServiceCallback callback,
object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Error("Not supported");
return;
}
void IDownloadActions.SetEventInfo(int eventIndex,
string id,
Guid guid,
ulong totalSamples,
ulong[] triggerSamples,
ulong startRecordSample,
uint eventHasDownloaded,
ServiceCallback callback,
object userData)
{
//var info = new TDASServiceAsyncInfo(callback, userData);
//info.Error("Setting event info not supported on TDAS");
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
long IDASCommunication.MaxMemory() { return long.MaxValue; }
uint IDASCommunication.MaxSampleRate(int numberOfConfiguredChannels) { return uint.MaxValue; }
uint IDASCommunication.MinSampleRate() { return uint.MinValue; }
public uint MaxAAFilterRate() { return uint.MaxValue; }
private class SDBAsyncInfo
{
public ServiceCallback Callback { get; }
public object UserData { get; }
public bool DiscardDiagnostics { get; set; } = true;
public SDBAsyncInfo(ServiceCallback callback, object userData)
{
Callback = callback;
UserData = userData;
}
public void Error(string msg, Exception ex)
{
try
{
var cbData = new ServiceCallbackData
{
Status = ServiceCallbackData.CallbackStatus.Failure,
ErrorMessage = msg,
ErrorException = ex,
UserData = UserData
};
Callback(cbData);
}
catch (Exception eex)
{
APILogger.Log("MessageBox", "SDB ERROR", eex);
}
}
public void Error(string msg)
{
Error(msg, null);
}
public void Progress(int value)
{
try
{
var progressData =
new ServiceCallbackData
{
Status = ServiceCallbackData.CallbackStatus.ProgressReport,
ProgressValue = value,
UserData = UserData
};
Callback(progressData);
}
catch (Exception ex)
{
APILogger.Log("MessageBox", "SDB ERROR", ex);
}
}
public void Success()
{
try
{
var success = new ServiceCallbackData
{
Status = ServiceCallbackData.CallbackStatus.Success,
UserData = UserData
};
Callback(success);
}
catch (Exception ex)
{
APILogger.Log("MessageBox", "SDB ERROR", 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.SLICEDBAsyncInfoCancelError, ex);
}
}
}
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> _sliceDBMinimumProtocols = new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
public override void InitMinProto()
{
// SLICE_DB Protocol Limitations
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.Arm] = SLICEDB.MIN_PROTOCOL_ARM;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EnableFaultChecking] = SLICEDB.MIN_PROTOCOL_ENABLEFAULTCHECKING;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.OnOverride] = SLICEDB.MIN_PROTOCOL_ONOVERRIDE;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.OMAP_GPIO] = SLICEDB.MIN_PROTOCOL_OMAP_GPIO;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryBatteryVoltage] = SLICEDB.MIN_PROTOCOL_VER;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics] = SLICEDB.MIN_PROTOCOL_DIAGNOSTICS;
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICEDB.MIN_PROTOCOL_INITHARDWAREINPUTLINES;
//FB 16049 Support ECM cal date
//this is only true for ECM, but SDB will not be using the command port and querying cal date?
_sliceDBMinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = SLICEDB.MIN_PROTOCOL_BASECALDATE;
MinimumProtocols = _sliceDBMinimumProtocols;
}
/// <summary>
/// Verify that the ConfigData property is correctly constructed
/// </summary>
/// <param name="doStrictCheck">Set to true if your're arming</param>
public void VerifyConfig(bool doStrictCheck)
{
VerifyConfig(doStrictCheck, null);
}
void IConfigurationActions.VerifyConfig(bool doStrictCheck, ErrorCallback failedChallengeFunc)
{
VerifyConfig(doStrictCheck, failedChallengeFunc);
}
private void VerifyConfig(bool doStrictCheck, ErrorCallback failedChallengeFunc)
{
if (!doStrictCheck) return;
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines)) return;
var qosm = new QueryOMAPnStartMon(this, AbstractCommandBase.Default_IO_Timeout);
var qoem = new QueryOMAPEventMon(this, AbstractCommandBase.Default_IO_Timeout);
qosm.LogCommands = false;
qoem.LogCommands = false;
try
{
qosm.SyncExecute();
qoem.SyncExecute();
}
catch (Exception ex) { APILogger.Log(ex); }
if (!qosm.Value && !IgnoreShortedStart)
{
//Start Shorted
throw new StartShortedException(string.Format(Strings.StartRecordShorted, SerialNumber));
}
if (qoem.Value && !IgnoreShortedTrigger)
{
//Trigger Shorted
throw new TriggerShortedException(string.Format(Strings.TriggerShorted, SerialNumber));
}
}
void IConfigurationActions.CheckSafetyState(bool bArmed, ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.QueryTestSetup(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
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 SDBAsyncInfo(callback, userData);
ConfigureHasBeenRun = true;
if (discardDiagnostics) { DiagnosticsHasBeenRun = false; }
info.Progress(100);
info.Success();
}
void IConfigurationActions.ApplyLevelTriggers(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
// FB15335: Move UART and ClockProfile sets to RunTest -> Hardware NavStep, add Reboot
void IConfigurationActions.Reboot(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.Reboot", new WaitCallback(AsyncReboot), info);
}
protected virtual void AsyncReboot(object o)
{
if (!(o is SDBAsyncInfo info)) { return; }
try
{
var reboot = new Reboot(this, SetSystemAttribute.Default_IO_Timeout);
reboot.SyncExecute();
info.Success();
}
catch (CanceledException ex)
{
APILogger.Log(ex);
info.Cancel();
}
catch (Exception ex)
{
APILogger.Log(ex);
info.Error(ex.Message, ex);
}
}
void IConfigurationActions.UpdateConfigurationFromFile(ServiceCallback callback, object userData,
string filePath)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SLICEDB.UpdateConfigurationFromFile", new WaitCallback(AsyncUpdateConfigurationFromFile),
info);
}
private void AsyncUpdateConfigurationFromFile(object asyncInfo)
{
var info = asyncInfo as SDBAsyncInfo;
info.Error("Not supported yet");
return;
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SLICE6DB.QueryConfiguration", AsyncQueryConfiguration, info);
}
protected virtual void AsyncQueryConfiguration(object o)
{
var info = o as SDBAsyncInfo;
ConfigData = new ConfigurationData
{
Modules = new[] { new DASModule(0, this) }
};
ConfigData.Modules[0].Channels = new DASChannel[] { new AnalogInputDASChannel((DASModule)ConfigData.Modules[0], 0) };
ConfigData.IDs = new EID[0];
ConfigData.TestID = "";
ConfigData.Description = "";
try
{
var qma = new QueryMACAddress(this);
qma.SyncExecute();
DASInfo.MACAddress = qma.MACAddress;
info?.Success();
}
catch (Exception ex)
{
DASInfo.MACAddress = "";
APILogger.Log(ex);
info?.Error(ex.Message);
}
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
void IConfigurationActions.UpdateId(ServiceCallback callback, object userData, DASModule module, DASChannel channel)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <summary>
/// ConfigData object containing the pre-test setup and configuration
/// of all modules and channels in the hardware. The object is updated
/// when <see cref="ConfigurationService">ConfigurationService.Configure(...)</see> is called, and the properties
/// of the entire DAS unit can be inspected.
/// </summary>
public IConfigurationData ConfigData
{
get;
set;
}
public IDiagnosticActions[] ChannelDiagnostics
{
get;
set;
}
public void SetChannelDiagnosticActions(IDiagnosticActions[] actions, bool setInDb = true)
{
DiagnosticsActions.SetChannelDiagnosticActions(this, actions, setInDb);
}
public IDiagnosticResult[] ChannelDiagnosticsResults
{
get;
set;
}
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; }
public IArmCheckActions ArmCheckActions { get; set; }
public IArmCheckResults ArmCheckResults { get; set; }
public IOptimizationValues OptimizationValues { get; set; }
/// <inheritdoc />
/// <summary>
/// If any of the units to run diagnostics are in
/// <see cref="T:DTS.DASLib.Service.ArmingService">
/// DTS.DASLib.Service.ArmingService.EnterLowPowerMode</see> then the analog circuits must be "warmed up" before accurate
/// diagnostics can be performed. If the units have not been placed into
/// <see cref="T:DTS.DASLib.Service.ArmingService">DTS.DASLib.Service.ArmingService.EnterLowPowerMode</see> then there is no need to call
/// this but since it is quite important habitually calling it everytime
/// diagnostics are performed would be beneficial.
/// </summary>
/// <param name="diagnosticsSampleRateHz">The firmware will use this sample rate when
/// collecting diagnostics data from the channel.</param>
/// <param name="diagnosticsAAFilterFrequencyHz">The firmware will use this Anti-Aliasing
/// filter when collectin diagnostics data from the channel.</param>
/// <param name="callback">The function to call with information.</param>
/// <param name="userData">Whatever you want to pass along.</param>
void IDiagnosticsActions.PrepareForBridgeResistanceMeasurement(uint diagnosticsSampleRateHz,
float diagnosticsAAFilterFrequencyHz,
ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.GetBridgeMeasurement(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.MeasureTransferSpeed(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
/// result in ChannelDiagnosticsResults
/// </summary>
/// <param name="diagnosticsSampleRateHz">sample rate</param>
/// <param name="diagnosticsAAFilterFrequencyHz">AA Filter rate</param>
/// <param name="whichResult"></param>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
void IDiagnosticsActions.PrepareForDiagnostics(uint diagnosticsSampleRateHz,
float diagnosticsAAFilterFrequencyHz,
PrePostResults whichResult,
ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
public 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));
}
}
#region Voltage Check
public void PerformVoltageCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.PerformVoltageCheck", AsyncPerformVoltageCheck, info);
}
private void AsyncPerformVoltageCheck(object o)
{
if (!(o is SDBAsyncInfo info)) { return; }
try
{
BaseInput = new BaseInputValues();
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
{
try
{
var query = new QueryBatteryVoltageMV(this);
query.SyncExecute();
var d = (double)query.BatteryVoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING)
{
d /= 1000.0D;
}
BaseInput.BatteryMilliVolts = d;
}
catch (Exception ex)
{
APILogger.Log("Failed to get battery mv", ex);
}
try
{
var query = new QueryV1VoltageMV(this);
query.SyncExecute();
var d = (double)query.V1VoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING)
{
d /= 1000.0D;
}
BaseInput.InputMilliVolts = d;
}
catch (Exception ex)
{
APILogger.Log("Failed to get input mv", ex);
info.Error(ex.Message);
}
var inputVoltage = Math.Round(BaseInput.InputMilliVolts / 1000D, 1);
var batteryVoltage = Math.Round(BaseInput.BatteryMilliVolts / 1000D, 1);
var batteryChargingStatus = string.Empty;
if (batteryVoltage >= MinimumValidBatteryVoltage)
{
batteryChargingStatus = ConvertInputVoltage2BatteryCharging(inputVoltage);
}
BaseInput.StatusDisplayBattery = batteryVoltage < MinimumValidBatteryVoltage ||
batteryVoltage > MaximumValidBatteryVoltage
? "---"
: batteryVoltage.ToString(System.Globalization.CultureInfo.InvariantCulture) + " V " +
batteryChargingStatus;
BaseInput.BatteryVoltageStatusColor = ConvertBatteryVoltage2Color(batteryVoltage);
BaseInput.StatusDisplayInput = inputVoltage < MinimumValidInputVoltage ||
inputVoltage > MaximumValidInputVoltage
? "---"
: inputVoltage.ToString(System.Globalization.CultureInfo.InvariantCulture) + " V";
BaseInput.InputVoltageStatusColor = ConvertInputVoltage2Color(inputVoltage);
BaseInput.MinimumValidInputVoltage = MinimumValidInputVoltage;
BaseInput.MaximumValidInputVoltage = MaximumValidInputVoltage;
BaseInput.MinimumValidBatteryVoltage = MinimumValidBatteryVoltage;
BaseInput.MaximumValidBatteryVoltage = MaximumValidBatteryVoltage;
}
info.Success();
}
catch (Exception ex)
{
APILogger.Log(ex);
info.Error(ex.Message);
}
}
public string ConvertInputVoltage2BatteryCharging(double inputVoltage)
{
if (inputVoltage > 11.0)
{
return "(Charging)";
}
if (inputVoltage <= 11.0 && inputVoltage >= 9.0)
{
return "(Not charging)";
}
return "(Discharging)";
}
private DFConstantsAndEnums.VoltageStatusColor ConvertBatteryVoltage2Color(double batteryVoltage)
{
if (batteryVoltage > MaximumValidBatteryVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Off; }
if (batteryVoltage > BatteryHighVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Red; }
if (batteryVoltage > BatteryMediumVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Green; }
if (batteryVoltage >= BatteryLowVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Yellow; }
if (batteryVoltage >= MinimumValidBatteryVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Red; }
return DFConstantsAndEnums.VoltageStatusColor.Off;
}
private DFConstantsAndEnums.VoltageStatusColor ConvertInputVoltage2Color(double voltage)
{
if (voltage > MaximumValidInputVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Off; }
if (voltage > InputHighVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Red; }
if (voltage > InputMediumVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Green; }
if (voltage >= InputLowVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Yellow; }
if (voltage >= MinimumValidInputVoltage) { return DFConstantsAndEnums.VoltageStatusColor.Red; }
return DFConstantsAndEnums.VoltageStatusColor.Off;
}
public DFConstantsAndEnums.VoltageStatusColor ConvertBatteryCapacity2Color(double voltage, double capacity)
{
if (!(voltage >= 5.0)) return DFConstantsAndEnums.VoltageStatusColor.Off;
if (capacity > 90) { return DFConstantsAndEnums.VoltageStatusColor.Green; }
if (capacity <= 90 && capacity >= 40) { return DFConstantsAndEnums.VoltageStatusColor.Yellow; }
if (capacity < 40) { return DFConstantsAndEnums.VoltageStatusColor.Red; }
return DFConstantsAndEnums.VoltageStatusColor.Off;
}
public string ConvertInputStatusColor2Status(DFConstantsAndEnums.VoltageStatusColor color, double inputVoltage)
{
switch (color)
{
case DFConstantsAndEnums.VoltageStatusColor.Green:
case DFConstantsAndEnums.VoltageStatusColor.Yellow:
case DFConstantsAndEnums.VoltageStatusColor.Red:
return inputVoltage.ToString();
default: return Command.TDAS.TestAll.VoltageStatus.None.ToString();
}
}
public string ConvertBatteryStatusColor2Status(DFConstantsAndEnums.VoltageStatusColor color, double batteryVoltage)
{
switch (color)
{
case DFConstantsAndEnums.VoltageStatusColor.Green:
case DFConstantsAndEnums.VoltageStatusColor.Yellow:
return batteryVoltage.ToString();
case DFConstantsAndEnums.VoltageStatusColor.Red:
if (batteryVoltage < MinimumValidBatteryVoltage || batteryVoltage > MaximumValidBatteryVoltage)
{
return Command.TDAS.TestAll.VoltageStatus.None.ToString();
}
else
{
return batteryVoltage.ToString();
}
default: return Command.TDAS.TestAll.VoltageStatus.None.ToString();
}
}
public void PerformVoltageCheckTAOnly(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.PerformVoltageCheckTAOnly", AsyncPerformVoltageCheckTAOnly, info);
}
private void AsyncPerformVoltageCheckTAOnly(object o)
{
var info = o as SDBAsyncInfo;
info?.Success();
}
#endregion Voltage Check
void IDiagnosticsActions.PerformArmChecks(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.PerformArmChecks", AsyncPerformArmChecks, info);
}
private void AsyncPerformArmChecks(object o)
{
if (!(o is SDBAsyncInfo info)) { return; }
var dasResults = new ArmCheckResults();
info.Progress(25);
if (null != ArmCheckActions)
{
if (ArmCheckActions.PerformBatteryVoltageCheck)
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
{
try
{
var query = new QueryBatteryVoltageMV(this);
query.SyncExecute();
DASArmStatus.BatteryMilliVolts = query.BatteryVoltageMV;
dasResults.BatteryVoltage = new double?[1];
dasResults.BatteryVoltage[0] = query.BatteryVoltageMV / 1000D;
SetDASArmStatus();
}
catch (Exception ex) { APILogger.Log("Failed to get Battery voltage", ex); }
}
}
if (ArmCheckActions.PerformInputVoltageCheck)
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
{
try
{
var query = new QueryV1VoltageMV(this);
query.SyncExecute();
dasResults.InputVoltage = query.V1VoltageMV / 1000D;
}
catch (Exception ex) { APILogger.Log("Failed to get Input voltage", ex); }
}
}
if (ArmCheckActions.PerformSquibResistanceCheck)
{
// No Squibs in SDB or ECM
}
info.Progress(50);
if (ArmCheckActions.PerformEventLineCheck)
{
((ITriggerCheckActions)this).DoTriggerCheckSync();
}
if (ArmCheckActions.PerformSensorIdCheck)
{
//no sensors to chek
}
}
info.Progress(100);
dasResults.SensorIds = null;
dasResults.TiltSensorDataPre = null;
dasResults.TemperaturesPre = null;
dasResults.SquibResistances = null;
ArmCheckResults = dasResults;
info.Success();
}
public void SaveTiltSensorDataPre(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.SaveTiltSensorData", AsyncSaveTiltSensorDataPre, info);
}
private void AsyncSaveTiltSensorDataPre(object asyncInfo)
{
var info = asyncInfo as SDBAsyncInfo;
info?.Success();
}
public void SaveTemperaturesPre(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.SaveTemperaturesPre", AsyncSaveTemperaturesPre, info);
}
private static void AsyncSaveTemperaturesPre(object asyncInfo)
{
var info = asyncInfo as SDBAsyncInfo;
info?.Success();
}
private const double SDB_ERR_VOLTAGE_REPORTING = 100000.0D;
private class StatusIndicatorPacket
{
public SDBAsyncInfo Info { get; set; }
}
public void SetStatusIndicator(DiagnosticsStatusIndicatorState state, ServiceCallback callback, object userData)
{
var packet = new StatusIndicatorPacket { Info = new SDBAsyncInfo(callback, userData) };
LaunchAsyncWorker("SLICE_DB.SetStatusIndicator", AsyncSetStatusIndicator, packet);
}
private static void AsyncSetStatusIndicator(object asyncInfo)
{
var packet = asyncInfo as StatusIndicatorPacket;
packet?.Info.Success();
}
public void TurnOffT0Lights(ServiceCallback callback, object userData)
{
var packet = new SDBAsyncInfo(callback, userData);
packet.Success();
}
/// <inheritdoc />
/// <summary>
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
/// result in ChannelDiagnosticsResults
/// </summary>
/// <param name="whichResult"></param>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
/// <param name="eventNumber"></param>
void IDiagnosticsActions.DiagnosAndGetResults(int eventNumber,
PrePostResults whichResult,
ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
DiagnosticsHasBeenRun = true;
BaseInput = new BaseInputValues();
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
{
try
{
var query = new QueryBatteryVoltageMV(this);
query.SyncExecute();
var d = (double)query.BatteryVoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING) { d /= 1000.0D; }
BaseInput.BatteryMilliVolts = d;
BaseInput.MinimumValidBatteryVoltage = MinimumValidBatteryVoltage;
BaseInput.MaximumValidBatteryVoltage = MaximumValidBatteryVoltage;
}
catch (Exception ex)
{
APILogger.Log("Failed to get battery mv", ex);
}
try
{
var query = new QueryV1VoltageMV(this);
query.SyncExecute();
var d = (double)query.V1VoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING) { d /= 1000.0D; }
BaseInput.InputMilliVolts = d;
BaseInput.MinimumValidInputVoltage = MinimumValidInputVoltage;
BaseInput.MaximumValidInputVoltage = MaximumValidInputVoltage;
}
catch (Exception ex)
{
APILogger.Log("Failed to get input mv", ex);
}
}
ClearChannelDiagnosticsResults(false);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.SquibFireCheckArm(double delay, double duration, ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.TriggerCheckTrigger(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IDiagnosticsActions.TriggerCheckDownload(double delay, double duration, float dummyAAFilterFrequencyHz, uint dummySampleRateHz, ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
public IBaseInputValues BaseInput
{
get;
set;
}
#region Clock Sync
public bool ClockSyncInUTC { get; set; } = false;
public IDictionary<InputClockSource, bool> DASClockSyncStatus { get; set; } = null;
public byte PTPDomainID { get; set; }
public ClockSyncProfile DASClockSyncProfile { get; set; }
#endregion
/// <inheritdoc />
/// <summary>
/// Here is where the trigger check results are stored
/// </summary>
public ITriggerCheckResult TriggerResult
{
get;
set;
}
/// <inheritdoc />
/// <summary>
/// The list of channels from which to recieve Real Time Data.
/// </summary>
public List<int> RealtimeDASChannels
{
get;
set;
}
public List<double> TiltAxisData { get; set; }
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; } = 19D;
public double MinimumValidBatteryVoltage { get; set; }
public double MaximumValidBatteryVoltage { get; set; } = 9D;
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>true if known to be streaming, false otherwise</returns>
public bool GetIsStreaming()
{
return false;
}
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(IArmStatusData status, bool bSetInDb)
{
ArmStatus.SetArmStatus(this, status, bSetInDb);
}
public void SetDASArmStatus()
{
ArmStatus.SetArmStatus(this, DASArmStatus, true);
}
public DFConstantsAndEnums.CommandStatus AutoArmStatus { get; set; }
public bool AutoArmed { get; set; }
/// <inheritdoc />
/// <summary>
/// This flag is used to tell if arm attributes should be defaulted when arming
/// or not. It also serves to let the user know that this DAS has not been
/// diagnosed.
/// </summary>
public bool DiagnosticsHasBeenRun
{
get => true;
set { }
}
/// <inheritdoc />
/// <summary>
/// this flag is used to tell if configure has been run
/// this is used prior to when diagnostic results are needed, like the
/// diagnostics tab or the acquire tab [when running acquire]
/// </summary>
public bool ConfigureHasBeenRun
{
get => true;
set { }
}
/// <inheritdoc />
/// <summary>
/// Count how many channels are configured.
/// </summary>
/// <returns>Number of configured channels.</returns>
public int NumberOfConfiguredChannels() { return 0; }
/// <inheritdoc />
/// <summary>
/// Count how many channels we have (regardless if they are configured or not).
/// </summary>
/// <returns>Total number of channels</returns>
public int NumberOfChannels() { return 0; }
public bool SupportsAutoArm() { return true; }
public bool SupportsLevelTrigger() { return false; }
public bool SupportsMultipleEvents() { return true; }
public bool SupportsMultipleConfigurations() { return false; }
public bool SupportsRealtime() { return false; }
/// <inheritdoc />
/// <summary>
/// indicates whether the DAS supports streaming
/// 10572 implement SW side for single command streaming realtime
/// </summary>
public bool SupportsIndividualChannelRealtimeStreaming => false;
/// <inheritdoc />
/// <summary>
/// SLICE can invert trigger, not all das will be able to
/// </summary>
/// <returns></returns>
public bool SupportsTriggerInversion()
{
return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Arm);
}
public bool InvertTrigger
{
get => false;
set
{
try
{
if (!SupportsTriggerInversion()) return;
var cmd = new SetInvertTriggerPolarity(this) { Value = value };
cmd.SyncExecute();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
/// <inheritdoc />
/// <summary>
/// slice can invert start, not all das will be able to
/// </summary>
/// <returns></returns>
public bool SupportsStartInversion()
{
return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Arm);
}
public bool InvertStart
{
get => false;
set
{
if (!SupportsStartInversion()) return;
try
{
var cmd = new SetInvertStartPolarity(this) { Value = value };
cmd.SyncExecute();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
/// <inheritdoc />
/// <summary>
/// SLICE Base firmware supports checking the trigger and start lines as of protocol 7,
/// this function returns whether the hardware supports checking input status or not
/// </summary>
/// <returns></returns>
public bool SupportsHardwareInputCheck() { return false; }
/// <inheritdoc />
/// <summary>
/// whether to use multiple sample real time or not
/// for sliceware there are times we need to turn off multiple sample realtime
/// (like when using a slicedb for instance)
/// </summary>
/// <returns></returns>
public bool SupportsMultipleSampleRealtime() { return false; }
/// <inheritdoc />
/// <summary>
/// whether the DASbase actually controls the DAQ for modules
/// in the case of TDAS, the modules actually are responsible for the DAQ and the
/// rack is just a middleman
/// this is relevant because if the DAQ is controlled by the base then the sample numbers
/// should match for all modules.
/// </summary>
/// <returns></returns>
public bool ControlsDAQ() { return false; }
/// <inheritdoc />
/// <summary>
/// What do you want to download?
/// </summary>
public IDownloadRequest WhatToDownload { get; set; }
public void SetWhatToDownload(IDownloadRequest request, bool bSetInDb = true)
{
DownloadRequest.SetWhatToDownload(this, request, bSetInDb);
}
/// <inheritdoc />
/// <summary>
/// The Retrieved information about stored events.
/// </summary>
public IDownloadReport EventInfo { get; set; }
public void SetEventInfo(IDownloadReport eventInfo, bool bSetInDb = true)
{
DownloadReport.SetEventInfo(this, eventInfo, bSetInDb);
}
/// <inheritdoc />
/// <summary>
/// QueryDownloadedStatus will fill this array (indexed by event number, true if
/// HasBeenDownloaded was set for this event, false otherwise)
/// </summary>
public bool[] EventDownloadedStatus { get; set; }
public void SetEventDownloadStatus(bool[] status, bool storeInDb = true)
{
DownloadReport.SetEventDownloadStatus(this, status, storeInDb);
}
/// <inheritdoc />
/// <summary>
/// DASFactory will fill this array (indexed by event number).
/// </summary>
public Guid[] EventGuids { get; set; }
public void SetEventGuids(Guid[] guids, bool storeInDb = true)
{
DownloadReport.SetEventGuids(this, guids, storeInDb);
}
/// <inheritdoc />
/// <summary>
/// DASFactory will fill this array (indexed by event number).
/// </summary>
public ushort[] FaultFlags { get; set; }
public void SetEventFaultFlags(ushort[] flags, bool storeInDb = true)
{
DownloadReport.SetEventFaultFlags(this, flags, storeInDb);
}
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);
}
/// <inheritdoc />
/// <summary>
/// DASFactory will fill this array (indexed by event number).
/// </summary>
public byte[] ArmAttempts { get; set; }
public void SetEventArmAttemps(byte[] armAttempts, bool storeInDb = true)
{
DownloadReport.SetEventArmAttempts(this, armAttempts, storeInDb);
}
/// <inheritdoc />
/// <summary>
/// DASInfo is populated with values from the hardware. It provides information
/// about the entire DAS as well as the functions neccessary to covert between
/// Module, ModuleChannel, and DASChannel values.
/// </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); }
public int CompareTo(IDASCommunication other)
{
return String.Compare(SerialNumber, other.SerialNumber, StringComparison.Ordinal);
}
/// <inheritdoc />
/// <summary>
/// tell DAS to start sending data at specific rate
/// </summary>
/// <param name="samplesPerSec">How many samples per second to receive</param>
/// <param name="msBetweenSamples">the amount of time to sleep between samples
/// 0 is ok</param>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
/// <param name="stopEvent"></param>
/// <param name="channels">
/// channels to operate on, added for
/// 10572 implement SW side for single command streaming realtime
/// </param>
/// <param name="allowMultipleSampleRealtime"></param>
/// <param name="moduleIndex"></param>
void IRealTimeActions.RealTime(int samplesPerSec,
int msBetweenSamples,
ServiceCallback callback,
object userData,
bool allowMultipleSampleRealtime,
int moduleIndex,
ManualResetEvent stopEvent,
byte[] channels,
double aaf,
int minCallbackUpdateTimeMs,
bool UseUDPStreaming,
string hostIPAddress)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IRealTimeActions.RealTimePolling(ServiceCallback callback,
object userData,
ManualResetEvent mre,
byte[] channels)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// Stop sending real time data
/// </summary>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
void IRealTimeActions.ExitRealTimeMode(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IRealTimeActions.RealTimeTiltPolling(ServiceCallback callback, object userData, ManualResetEvent stopEvent)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
public string UDPStreamAddress { get; }
/// <summary>
/// FB15313 Configure S6A udp streaming
/// </summary>
/// <param name="callback">The function to call with information</param>
/// <param name="userData">Whatever you want to pass along</param>
/// <param name="profile">The stream profile to set</param>
void IRealTimeActions.SetUDPStreamProfile(ServiceCallback callback, object userData, UDPStreamProfile profile, string udpAddress, ushort timeChannelId, ushort dataChannelId, uint[] tmnsConfig, ushort irigTimeDataPacketIntervalMs)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IRealTimeActions.GetUDPStreamProfile(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// Start an asynchronous flash erase on a single DAS.
/// </summary>
/// <param name="callback"></param>
/// <param name="userData"></param>
/// <param name="dummyArm"></param>
void IArmActions.BeginFlashErase(ServiceCallback callback, object userData, bool dummyArm)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// Query a single DAS for flash erase progress and an errors that have occurred.
/// </summary>
/// <param name="callback">The function to call with update information</param>
/// <param name="userData"></param>
void IArmActions.QueryFlashEraseStatus(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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>
/// <param name="armNowTimeout"></param>
/// <param name="testingMode"></param>
/// <param name="maxNumberEvents"></param>
/// <param name="sysMode"></param>
void IArmActions.ArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
armNowTimeout, bool testingMode,
int maxNumberEvents, bool sysMode)
{
var info = new SDBAsyncInfo(callback, userData);
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Arm))
{
//this.ConfigData.Modules[0].PostTriggerSeconds;
var spts = new SetPostTriggerSec(this)
{
Value = Convert.ToSingle(ConfigData.Modules[0].PostTriggerSeconds)
};
spts.SyncExecute();
var srm = new SetRecordingMode(this) { Value = (byte)ConfigData.Modules[0].RecordingMode };
srm.SyncExecute();
try
{
var arm = new Arm(this);
arm.SyncExecute();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
return;
}
}
info.Success();
}
void IArmActions.PrepareForArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
armNowTimeout, bool testingMode,
int maxNumberEvents, bool sysMode)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IArmActions.ReArm(ServiceCallback callback, object userData, bool autoArm, bool arm, bool repeatEnable)
{
var info = new SDBAsyncInfo(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 SDBAsyncInfo(callback, userData);
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Arm))
{
var spts = new SetPostTriggerSec(this)
{
Value = Convert.ToSingle(ConfigData.Modules[0].PostTriggerSeconds)
};
spts.SyncExecute();
var srm = new SetRecordingMode(this) { Value = (byte)ConfigData.Modules[0].RecordingMode };
srm.SyncExecute();
try
{
var arm = new Arm(this);
arm.SyncExecute();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
return;
}
}
info.Success();
}
/// <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";
/// <inheritdoc />
/// <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>
/// <param name="armNowTimeout"></param>
/// <param name="testingMode"></param>
/// <param name="diagnosticsDelayMs"></param>
/// <param name="maxNumberEvents"></param>
void IArmActions.AutoArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
armNowTimeout, bool testingMode, uint diagnosticsDelayMs, int maxNumberEvents, bool repeatEnable, bool preserveDiagnostics)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.EnableFaultChecking))
{
var efc = new EnableFaultChecking(this);
efc.SyncExecute();
}
info.Success();
}
catch (Exception ex)
{
APILogger.Log("failed to enable fault checking, ", ex);
info.Error(ex.Message);
}
}
void IArmActions.CheckAlreadyLevelTriggered(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SliceDB.CheckAlreadyLevelTriggered", AsyncCheckAlreadyLevelTriggered, info);
}
private void AsyncCheckAlreadyLevelTriggered(object asyncInfo)
{
if (!(asyncInfo is SDBAsyncInfo info)) { return; }
try
{
foreach (var m in ConfigData.Modules)
{
foreach (var ch in m.Channels)
{
if (!(ch is AnalogInputDASChannel)) continue;
(ch as AnalogInputDASChannel).AlreadyLevelTriggered = false;
(ch as AnalogInputDASChannel).MeasuredEULevelTriggerCheck = double.NaN;
}
}
info.Success();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
}
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Arm))
{
try
{
var disarm = new Disarm(this);
disarm.SyncExecute();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
info.Success();
}
/// <inheritdoc />
/// <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)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
void IArmActions.GetExtendedFaultIds(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
LaunchAsyncWorker("SLICEDB.GetExtendedFaultIds", new WaitCallback(SLICEDBAsyncGetExtendedFaultIds), info);
}
private void SLICEDBAsyncGetExtendedFaultIds(object asyncInfo)
{
var info = (SDBAsyncInfo)asyncInfo;
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
var status = new ArmStatus { IsArmed = false };
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
{
var batteryVoltage = 0.0;
try
{
var query = new QueryBatteryVoltageMV(this, 3000);
query.SyncExecute();
var d = (double)query.BatteryVoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING)
{
d /= 1000.0D;
}
status.BatteryMilliVolts = d;
batteryVoltage = Math.Round(d / 1000, 1);
}
catch (Exception ex)
{
APILogger.Log("Failed to get battery mv", ex);
}
try
{
var query = new QueryV1VoltageMV(this, 3000);
query.SyncExecute();
var d = (double)query.V1VoltageMV;
if (d > SDB_ERR_VOLTAGE_REPORTING)
{
d /= 1000.0D;
}
status.InputMilliVolts = d;
var inputVoltage = Math.Round(d / 1000, 1);
if (batteryVoltage < MinimumValidBatteryVoltage || batteryVoltage > MaximumValidBatteryVoltage)
{
batteryVoltage = 0.0;
}
BaseInput = new BaseInputValues();
var batteryVoltageStatusColor = DFConstantsAndEnums.VoltageStatusColor.Off;
batteryVoltageStatusColor = BaseInput.ChargeCapacityValid
? ConvertBatteryCapacity2Color(batteryVoltage, BaseInput.ChargeCapacity)
: ConvertBatteryVoltage2Color(batteryVoltage);
var batteryChargingStatus = string.Empty;
if (batteryVoltage >= MinimumValidBatteryVoltage)
{
batteryChargingStatus = ConvertInputVoltage2BatteryCharging(inputVoltage);
}
var statusDisplayBattery =
batteryVoltage < MinimumValidBatteryVoltage || batteryVoltage > MaximumValidBatteryVoltage
? "---"
: batteryVoltage.ToString(System.Globalization.CultureInfo.InvariantCulture) + " V " +
batteryChargingStatus;
var inputVoltageStatusColor = ConvertInputVoltage2Color(inputVoltage);
BaseInput.InputVoltageStatusColor = inputVoltageStatusColor;
BaseInput.StatusDisplayInput =
inputVoltage < MinimumValidInputVoltage || inputVoltage > MaximumValidInputVoltage
? "---"
: inputVoltage.ToString(System.Globalization.CultureInfo.InvariantCulture) + " V";
BaseInput.BatteryVoltageStatusColor = batteryVoltageStatusColor;
BaseInput.MinimumValidInputVoltage = MinimumValidInputVoltage;
BaseInput.MaximumValidInputVoltage = MaximumValidInputVoltage;
BaseInput.MinimumValidBatteryVoltage = MinimumValidBatteryVoltage;
BaseInput.MaximumValidBatteryVoltage = MaximumValidBatteryVoltage;
BaseInput.StatusDisplayBattery = statusDisplayBattery;
}
catch (Exception ex)
{
APILogger.Log("Failed to get input mv", ex);
}
}
}
finally
{
SetDASArmStatus(status, true);
}
info.Success();
}
/// <summary>
/// Retrieve the current auto arm status from the DAS
/// </summary>
/// <param name="callback"></param>
/// <param name="userData"></param>
void IArmActions.GetAutoArmStatus(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
DiagnosticsHasBeenRun = false;
ExcitationStatus = ExcitationStatus.Off;
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <summary>
/// Cancel the current operation
/// </summary>
void IDownloadActions.Cancel()
{
}
/// <summary>
/// Clear the cancel flag
/// </summary>
void IDownloadActions.ClearCancel()
{
}
/// <inheritdoc />
/// <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>
/// <param name="eventIndex"></param>
/// <param name="setupInfo"></param>
void IDownloadActions.QueryDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
{
//we don't store events, so we just succeed
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
/// <inheritdoc />
/// <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 SDBAsyncInfo(callback, userData);
info.Success();
}
void IDownloadActions.SetDownloaded(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
#region Trigger check
void ITriggerCheckActions.StartTriggerCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
{
info.Success();
return;
}
var qosm = new QueryOMAPnStartMon(this, AbstractCommandBase.Default_IO_Timeout);
var qoem = new QueryOMAPEventMon(this, AbstractCommandBase.Default_IO_Timeout);
qosm.LogCommands = false;
qoem.LogCommands = false;
try
{
qosm.SyncExecute();
qoem.SyncExecute();
}
catch (Exception ex) { APILogger.Log(ex); }
if (!qosm.Value)
{
info.Error("StartInputShorted");
//Start Shorted
return;
}
if (qoem.Value)
{
info.Error("TriggerInputShorted");
//Trigger Shorted
return;
}
info.Success();
}
/// <summary>
/// the synchronous version of DoTriggerCheck
/// </summary>
void ITriggerCheckActions.DoTriggerCheckSync()
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
{
try
{
var query = new QueryOMAPEventMon(this, 3000);
query.SyncExecute();
var status = new ArmStatus
{
IsTriggered = query.Value,
IsArmed = !query.Value,
IsTriggerShorted = query.Value
};
SetDASArmStatus(status, true);
}
catch (Exception ex)
{
APILogger.Log("Failed to get trigger state", ex);
}
}
}
void ITriggerCheckActions.DoTriggerCheck(ServiceCallback callback, object userData)
{
//why isn't this asynchronous? I don't know but I'll preserve it as is
//[DTM] - 2019-05-23
SDBAsyncInfo info = null;
if (null != callback) { info = new SDBAsyncInfo(callback, userData); }
((ITriggerCheckActions)this).DoTriggerCheckSync();
info?.Success();
}
void ITriggerCheckActions.DoStartCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
{
try
{
var queryStart = new QueryOMAPnStartMon(this, 3000);
queryStart.SyncExecute();
var queryEvent = new QueryOMAPEventMon(this, 3000);
queryEvent.SyncExecute();
var status = new ArmStatus
{
IsArmed = !queryEvent.Value,
IsRecording = queryStart.Value
};
SetDASArmStatus(status, true);
}
catch (Exception ex)
{
APILogger.Log("Failed to get trigger state", ex);
}
}
info.Success();
}
void ITriggerCheckActions.CancelTriggerCheck(ServiceCallback callback, object userData)
{
var info = new SDBAsyncInfo(callback, userData);
info.Success();
}
#endregion
}
}