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 : Communication, IDASCommunication, IConfigurationActions, IDiagnosticsActions, ITriggerCheckActions, IRealTimeActions, IArmActions, IDownloadActions where T : IConnection, new() { public ExcitationStatus ExcitationStatus { get; set; } = ExcitationStatus.Unknown; /// /// /// public string TestDirectory { get; set; } void IDASCommunication.SetIsStreamingSupported(bool supported) { IsStreamingSupported = false; } void IDASCommunication.ReadFirstUseDate() { IsFirstUseDateSupported = false; FirstUseDate = null; } /// /// 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" /// public DateTime? FirstUseDate { get; set; } = null; /// /// 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" /// 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; } /// /// returns true if the unit is capable of reading arm status /// 17800 Trigger status is "waiting" but PPRO has indeed triggered /// /// 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 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"); } /// /// clears any das trigger lines (N/A to sdb ...) /// 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(); } /// /// 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 /// 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 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 { } } /// /// /// slicedbs don't collect or filter data, so safe to say they don't introduce any phase shifts. /// /// /// /// /// /// public ulong GetPhaseShiftSamples(uint moduleIndex, double actualSampleRate, uint hardwareAaf, ulong originalT0) { return 0; } /// /// /// initiates background flash erase for units that support it /// will return immediately after flash erase begins /// /// /// void IArmActions.BeginBackgroundFlashErase(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// returns whether unit is capable of flash erase /// bool IArmActions.SupportsBackgroundFlashErase => false; /// /// /// returns whether unit has started background flash erase /// 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 _sliceDBMinimumProtocols = new Dictionary(); 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; } /// /// Verify that the ConfigData property is correctly constructed /// /// Set to true if your're arming 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 timeChannelIds, Dictionary dataChannelIds, Dictionary streamProfiles, Dictionary streamADCPerPacket, Dictionary irigTDPIntervals, Dictionary addresses, Dictionary tmnsConfigs, Dictionary baudRates, Dictionary dataBits, Dictionary stopBits, Dictionary parities, Dictionary flowControls, Dictionary dataFormats, Dictionary 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; } /// /// /// Retrieve configuration from DAS and store it in the ConfigData property /// /// The function to call with information /// Whatever you want to pass along 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); } } /// /// /// Retrieve the EID's and store it in the ConfigData property /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// ConfigData object containing the pre-test setup and configuration /// of all modules and channels in the hardware. The object is updated /// when ConfigurationService.Configure(...) is called, and the properties /// of the entire DAS unit can be inspected. /// 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; } /// /// /// If any of the units to run diagnostics are in /// /// DTS.DASLib.Service.ArmingService.EnterLowPowerMode then the analog circuits must be "warmed up" before accurate /// diagnostics can be performed. If the units have not been placed into /// DTS.DASLib.Service.ArmingService.EnterLowPowerMode then there is no need to call /// this but since it is quite important habitually calling it everytime /// diagnostics are performed would be beneficial. /// /// The firmware will use this sample rate when /// collecting diagnostics data from the channel. /// The firmware will use this Anti-Aliasing /// filter when collectin diagnostics data from the channel. /// The function to call with information. /// Whatever you want to pass along. 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(); } /// /// /// Perform diagnostics based on the property ChannelDiagnostics and stuff the /// result in ChannelDiagnosticsResults /// /// sample rate /// AA Filter rate /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// /// Perform diagnostics based on the property ChannelDiagnostics and stuff the /// result in ChannelDiagnosticsResults /// /// /// The function to call with information /// Whatever you want to pass along /// 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(); } /// /// /// Retrieve the results from the implicit pre and post event diagnostics /// /// Which event number to Retrieve from /// The pre or post test results? /// The function to call with information /// Whatever you want to pass along 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 DASClockSyncStatus { get; set; } = null; public byte PTPDomainID { get; set; } public ClockSyncProfile DASClockSyncProfile { get; set; } #endregion /// /// /// Here is where the trigger check results are stored /// public ITriggerCheckResult TriggerResult { get; set; } /// /// /// The list of channels from which to recieve Real Time Data. /// public List RealtimeDASChannels { get; set; } public List 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; } /// /// returns true if the unit is known to be streaming /// does not query the hardware, just returns a flag if it has been set /// /// true if known to be streaming, false otherwise 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; } /// /// /// 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. /// public bool DiagnosticsHasBeenRun { get => true; set { } } /// /// /// 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] /// public bool ConfigureHasBeenRun { get => true; set { } } /// /// /// Count how many channels are configured. /// /// Number of configured channels. public int NumberOfConfiguredChannels() { return 0; } /// /// /// Count how many channels we have (regardless if they are configured or not). /// /// Total number of channels public int NumberOfChannels() { return 0; } public bool SupportsAutoArm() { return true; } public bool SupportsLevelTrigger() { return false; } public bool SupportsMultipleEvents() { return true; } public bool SupportsRealtime() { return false; } /// /// /// indicates whether the DAS supports streaming /// 10572 implement SW side for single command streaming realtime /// public bool SupportsIndividualChannelRealtimeStreaming => false; /// /// /// SLICE can invert trigger, not all das will be able to /// /// 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); } } } /// /// /// slice can invert start, not all das will be able to /// /// 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); } } } /// /// /// 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 /// /// public bool SupportsHardwareInputCheck() { return false; } /// /// /// 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) /// /// public bool SupportsMultipleSampleRealtime() { return false; } /// /// /// 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. /// /// public bool ControlsDAQ() { return false; } /// /// /// What do you want to download? /// public IDownloadRequest WhatToDownload { get; set; } public void SetWhatToDownload(IDownloadRequest request, bool bSetInDb = true) { DownloadRequest.SetWhatToDownload(this, request, bSetInDb); } /// /// /// The Retrieved information about stored events. /// public IDownloadReport EventInfo { get; set; } public void SetEventInfo(IDownloadReport eventInfo, bool bSetInDb = true) { DownloadReport.SetEventInfo(this, eventInfo, bSetInDb); } /// /// /// QueryDownloadedStatus will fill this array (indexed by event number, true if /// HasBeenDownloaded was set for this event, false otherwise) /// public bool[] EventDownloadedStatus { get; set; } public void SetEventDownloadStatus(bool[] status, bool storeInDb = true) { DownloadReport.SetEventDownloadStatus(this, status, storeInDb); } /// /// /// DASFactory will fill this array (indexed by event number). /// public Guid[] EventGuids { get; set; } public void SetEventGuids(Guid[] guids, bool storeInDb = true) { DownloadReport.SetEventGuids(this, guids, storeInDb); } /// /// /// DASFactory will fill this array (indexed by event number). /// 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); } /// /// /// DASFactory will fill this array (indexed by event number). /// public byte[] ArmAttempts { get; set; } public void SetEventArmAttemps(byte[] armAttempts, bool storeInDb = true) { DownloadReport.SetEventArmAttempts(this, armAttempts, storeInDb); } /// /// /// 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. /// 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); } /// /// /// tell DAS to start sending data at specific rate /// /// How many samples per second to receive /// the amount of time to sleep between samples /// 0 is ok /// The function to call with information /// Whatever you want to pass along /// /// /// channels to operate on, added for /// 10572 implement SW side for single command streaming realtime /// /// /// 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(); } /// /// /// Stop sending real time data /// /// The function to call with information /// Whatever you want to pass along 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; } /// /// FB15313 Configure S6A udp streaming /// /// The function to call with information /// Whatever you want to pass along /// The stream profile to set 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(); } /// /// /// Start an asynchronous flash erase on a single DAS. /// /// /// /// void IArmActions.BeginFlashErase(ServiceCallback callback, object userData, bool dummyArm) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Query a single DAS for flash erase progress and an errors that have occurred. /// /// The function to call with update information /// void IArmActions.QueryFlashEraseStatus(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Arm a single DAS now /// /// The function to call with information /// Whatever you want to pass along /// A unique GUID that this event will be tagged /// with /// /// /// /// 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(); } /// /// the UDP settings to broadcast auto arm status to on auto arm boot /// 17583 Monitor Test UI /// public string AutoArmUDPSetting { get; set; } = "239.1.2.3:8504"; /// /// /// Auto Arm a single DAS now /// /// The function to call with information /// Whatever you want to pass along /// A unique GUID that this event will be tagged /// with /// /// /// /// 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(); } /// /// /// Arm multiple chained DAS now /// /// The function to call with information /// Whatever you want to pass along 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); } } /// /// /// Disarm the DAS /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// /// DisAutoArm the DAS /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// /// Retrieve the current arm status from the DAS /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// Retrieve the current auto arm status from the DAS /// /// /// void IArmActions.GetAutoArmStatus(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Set the DAS to low power mode /// /// The function to call with information /// Whatever you want to pass along void IArmActions.EnterLowPowerMode(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); DiagnosticsHasBeenRun = false; ExcitationStatus = ExcitationStatus.Off; info.Success(); } /// /// /// Tells the DAS to start record /// /// The function to call with information /// Whatever you want to pass along void IArmActions.StartRecord(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Sends trigger signal to HW /// /// The function to call with information /// Whatever you want to pass along void IArmActions.Trigger(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Download the data specified in the WhatToDownload property /// /// The function to call with information /// Whatever you want to pass along void IDownloadActions.Download(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Cancel the current operation /// void IDownloadActions.Cancel() { } /// /// Clear the cancel flag /// void IDownloadActions.ClearCancel() { } /// /// /// Retrieve info about available events to download /// /// The function to call with information /// Whatever you want to pass along /// /// 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(); } /// /// /// Figure out if events have been downloaded /// /// The function to call with information /// Whatever you want to pass along void IDownloadActions.QueryDownloadedStatus(ServiceCallback callback, object userData) { var info = new SDBAsyncInfo(callback, userData); info.Success(); } /// /// /// Update the recorded trigger sample numbers in HW /// /// The function to call with information /// Whatever you want to pass along 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(); } /// /// the synchronous version of DoTriggerCheck /// 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 } }