init
This commit is contained in:
28
DataPRO/IService/Classes/Arm/ArmCheckActions.cs
Normal file
28
DataPRO/IService/Classes/Arm/ArmCheckActions.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class ArmCheckActions : IArmCheckActions
|
||||
{
|
||||
public bool PerformBatteryVoltageCheck { get; set; }
|
||||
public bool PerformInputVoltageCheck { get; set; }
|
||||
public bool PerformSensorIdCheck { get; set; }
|
||||
public bool PerformEventLineCheck { get; set; }
|
||||
public bool PerformSquibResistanceCheck { get; set; }
|
||||
public bool PerformTiltSensorCheck { get; set; }
|
||||
public bool PerformTemperatureCheck { get; set; }
|
||||
public bool PerformClockSyncCheck { get; set; }
|
||||
|
||||
public ArmCheckActions()
|
||||
{
|
||||
PerformBatteryVoltageCheck = false;
|
||||
PerformInputVoltageCheck = false;
|
||||
PerformSensorIdCheck = false;
|
||||
PerformEventLineCheck = false;
|
||||
PerformSquibResistanceCheck = false;
|
||||
PerformTiltSensorCheck = false;
|
||||
PerformTemperatureCheck = false;
|
||||
PerformClockSyncCheck = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
DataPRO/IService/Classes/Arm/ArmCheckResults.cs
Normal file
32
DataPRO/IService/Classes/Arm/ArmCheckResults.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class ArmCheckResults : IArmCheckResults
|
||||
{
|
||||
/// <summary>
|
||||
/// sensor EIDs, key is index of channel, value is an array of ids
|
||||
/// </summary>
|
||||
public Dictionary<int, string[]> SensorIds { get; set; }
|
||||
public Dictionary<int, double> SquibResistances { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// some DAS (TDAS Pro rack) can have multiple battery voltages for modules ...
|
||||
/// </summary>
|
||||
public double?[] BatteryVoltage { get; set; }
|
||||
public double? InputVoltage { get; set; }
|
||||
public bool? StartLineShorted { get; set; }
|
||||
public bool? EventLineShorted { get; set; }
|
||||
public short[] TiltSensorDataPre { get; set; }
|
||||
public double[] TiltDegrees { get; set; }
|
||||
public Dictionary<byte, short[]> IndexedTiltSensorDataPre { get; set; } = new Dictionary<byte, short[]>();
|
||||
public Dictionary<byte, double[]> IndexedTiltDegrees { get; set; } = new Dictionary<byte, double[]>();
|
||||
public float[] TemperaturesPre { get; set; }
|
||||
public double[] Gains { get; set; }
|
||||
public double[] ZeroData { get; set; }
|
||||
public IDictionary<InputClockSource, bool> InputClockLocks { get; set; }
|
||||
}
|
||||
}
|
||||
254
DataPRO/IService/Classes/Arm/ArmStatus.cs
Normal file
254
DataPRO/IService/Classes/Arm/ArmStatus.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using DASFactoryDb.ARM;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.ARM;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// While a DAS unit is armed and object of this type in the corresponding <see cref="IDASCommunication" />
|
||||
/// can be udated to reflect the unit's status at that moment with a call to
|
||||
/// <see cref="ArmingService.GetArmStatus">ArmingService.GetArmStatus(...)</see>.
|
||||
/// </summary>
|
||||
public class ArmStatus : IArmStatusData
|
||||
{
|
||||
/// <summary>
|
||||
/// returns true if unit received InvalidMode to query commands during initial setup
|
||||
/// 15932 Error when performing test when S6A is streaming
|
||||
/// this is used in some places currently to detect when a unit is streaming
|
||||
/// </summary>
|
||||
public bool ReceivedInvalidModeDuringSetup { get; set; } = false;
|
||||
/// <summary>
|
||||
/// clears any flags set or needed for triggercheck
|
||||
/// </summary>
|
||||
public void ClearTriggerCheckStatus()
|
||||
{
|
||||
IsTriggered = false;
|
||||
IsArmed = false;
|
||||
IsRecording = false;
|
||||
IsTriggerShorted = false;
|
||||
IsStartShorted = false;
|
||||
}
|
||||
public ArmStatus() { }
|
||||
public ArmStatus(IArmStatusData status)
|
||||
{
|
||||
if (null == status) { return; }
|
||||
ReceivedInvalidModeDuringSetup = status.ReceivedInvalidModeDuringSetup;
|
||||
IsArmed = status.IsArmed;
|
||||
IsTriggered = status.IsTriggered;
|
||||
IsFaulted = status.IsFaulted;
|
||||
IsTriggerShorted = status.IsTriggerShorted;
|
||||
IsStartShorted = status.IsStartShorted;
|
||||
IsRecording = status.IsRecording;
|
||||
IsFaulted = status.IsFaulted;
|
||||
IsInRealtime = status.IsInRealtime;
|
||||
IsInFlashWrite = status.IsInFlashWrite;
|
||||
IsUndefined = status.IsUndefined;
|
||||
IsInPostTestDiagnostics = status.IsInPostTestDiagnostics;
|
||||
TimeRemainingSeconds = status.TimeRemainingSeconds;
|
||||
PercentComplete = status.PercentComplete;
|
||||
TotalSamples = status.TotalSamples;
|
||||
CurrentSample = status.CurrentSample;
|
||||
SampleRate = status.SampleRate;
|
||||
InputMilliVolts = status.InputMilliVolts;
|
||||
BatteryMilliVolts = status.BatteryMilliVolts;
|
||||
EventNumber = status.EventNumber;
|
||||
MaxEventsPossible = status.MaxEventsPossible;
|
||||
RecordingMode = status.RecordingMode;
|
||||
FaultMessage = status.FaultMessage;
|
||||
IsRearming = status.IsRearming;
|
||||
HasBeenRecording = status.HasBeenRecording;
|
||||
TimeLeftInArm = status.TimeLeftInArm;
|
||||
}
|
||||
/// <summary>
|
||||
/// Is the DAS currently armed?
|
||||
/// </summary>
|
||||
public bool IsArmed { get; set; }
|
||||
/// <summary>
|
||||
/// Has the DAS sensed a trigger?
|
||||
/// </summary>
|
||||
public bool IsTriggered { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// a little bit distinct from IsTriggered
|
||||
/// in that IsTriggerShorted is only set during TriggerCheck
|
||||
/// while IsTriggered is set in many places
|
||||
/// </summary>
|
||||
public bool IsTriggerShorted { get; set; }
|
||||
/// <summary>
|
||||
/// indicates that trigger was shorted
|
||||
/// is only set during triggercheck
|
||||
/// </summary>
|
||||
public bool IsStartShorted { get; set; }
|
||||
/// <summary>
|
||||
/// Is the DAS currently recording sample data?
|
||||
/// </summary>
|
||||
public bool IsRecording { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has the DAS faulted?
|
||||
/// </summary>
|
||||
public bool IsFaulted { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the DAS in real time mode?
|
||||
/// </summary>
|
||||
public bool IsInRealtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// is the DAS in flash write (G5)
|
||||
/// </summary>
|
||||
public bool IsInFlashWrite { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// used for the times when TDAS ARM STAT READ just doesn't return anything
|
||||
/// </summary>
|
||||
public bool IsUndefined { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the DAS in post test diagnostics
|
||||
/// </summary>
|
||||
public bool IsInPostTestDiagnostics { get; set; }
|
||||
/// <summary>
|
||||
/// How many seconds are left of recording?
|
||||
/// </summary>
|
||||
public double TimeRemainingSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// what percentage is complete [flashwrite]
|
||||
/// </summary>
|
||||
public double PercentComplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many samples total will the DAS be recording this test?
|
||||
/// </summary>
|
||||
public ulong TotalSamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What sample are we currently recording?
|
||||
/// </summary>
|
||||
public ulong CurrentSample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// At what sample rate are we currently recording?
|
||||
/// </summary>
|
||||
public uint SampleRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What's the current input voltage?
|
||||
/// </summary>
|
||||
//public double? InputMilliVolts { get; set; }
|
||||
private double? _inputMilliVolts = null;
|
||||
public double? InputMilliVolts
|
||||
{
|
||||
get => _inputMilliVolts;
|
||||
set
|
||||
{
|
||||
if (null == value) { _inputMilliVolts = null; }
|
||||
else
|
||||
{
|
||||
var d = (double)value;
|
||||
if (d > 100000) { d /= 1000; }
|
||||
_inputMilliVolts = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What's the current battery voltage (null if no battery)?
|
||||
/// </summary>
|
||||
private double? _batteryMilliVolts = null;
|
||||
public double? BatteryMilliVolts
|
||||
{
|
||||
get => _batteryMilliVolts;
|
||||
set
|
||||
{
|
||||
if (null == value) { _batteryMilliVolts = null; }
|
||||
else
|
||||
{
|
||||
var d = (double)value;
|
||||
if (d > 100000) { d /= 1000; }
|
||||
_batteryMilliVolts = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Which event number is currently being recorded?
|
||||
/// </summary>
|
||||
public int? EventNumber { get; set; }
|
||||
//FB 26817
|
||||
/// <summary>
|
||||
/// Max number of events supported by device
|
||||
/// </summary>
|
||||
public ushort? MaxEventsPossible { get; set; }
|
||||
public int RecordingMode { get; set; }
|
||||
/// <summary>
|
||||
/// optional fault message if there is a fault
|
||||
/// (software will flag some faults and when we do we know what caused it)
|
||||
/// </summary>
|
||||
public string FaultMessage { get; set; }
|
||||
|
||||
public bool IsRearming { get; set; }
|
||||
|
||||
public bool HasBeenRecording { get; set; }
|
||||
|
||||
private double? _timeLeftInArm = null;
|
||||
public double? TimeLeftInArm
|
||||
{
|
||||
get => _timeLeftInArm;
|
||||
set
|
||||
{
|
||||
if (null == value) { _timeLeftInArm = null; }
|
||||
else
|
||||
{
|
||||
_timeLeftInArm = (double)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// sets the given status to a given unit, optionally writing to the db
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="bSetInDb"></param>
|
||||
public static void SetArmStatus(IDASCommunication unit, IArmStatusData status, bool bSetInDb)
|
||||
{
|
||||
unit.DASArmStatus = status;
|
||||
if (!DASFactoryDb.DbWrapper.Connected || !bSetInDb) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
ARM.SetArmStatus(unit.RecordId,
|
||||
status.IsArmed,
|
||||
status.IsTriggered,
|
||||
status.IsTriggerShorted,
|
||||
status.IsStartShorted,
|
||||
status.IsRecording,
|
||||
status.IsFaulted,
|
||||
status.IsInRealtime,
|
||||
status.IsInFlashWrite,
|
||||
status.IsUndefined,
|
||||
status.IsInPostTestDiagnostics,
|
||||
status.TimeRemainingSeconds,
|
||||
status.PercentComplete,
|
||||
status.TotalSamples,
|
||||
status.CurrentSample,
|
||||
status.SampleRate,
|
||||
status.InputMilliVolts,
|
||||
status.BatteryMilliVolts,
|
||||
status.EventNumber,
|
||||
status.RecordingMode,
|
||||
status.FaultMessage,
|
||||
status.IsRearming,
|
||||
status.HasBeenRecording,
|
||||
status.TimeLeftInArm);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
135
DataPRO/IService/Classes/BaseInput/BaseInputValues.cs
Normal file
135
DataPRO/IService/Classes/BaseInput/BaseInputValues.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.DASLib.Command.TDAS;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Each time <see cref="DTS.DASLib.Service.DiagnosticsService" />.Diagnose is called these values
|
||||
/// are populated. Each IDASCommunication will have one of these objects. It
|
||||
/// provides information about input voltage to the base unit, like power input,
|
||||
/// presence of a battery and battery output voltage.
|
||||
/// </summary>
|
||||
public class BaseInputValues : IBaseInputValues
|
||||
{
|
||||
/// <summary>
|
||||
/// The current input voltage to the base.
|
||||
/// </summary>
|
||||
public double InputMilliVolts { get; set; }
|
||||
|
||||
|
||||
//18740 DataPRO system settings Power setting values for TDAS rack do not change actual power values on device
|
||||
// added Min/Max valid and tied Valid bool to those values
|
||||
public virtual bool InputMilliVoltsValid => InputMilliVolts > 1000D * MinimumValidInputVoltage && InputMilliVolts < 1000D * MaximumValidInputVoltage;
|
||||
|
||||
/// <summary>
|
||||
/// The current input voltage to the base.
|
||||
/// </summary>
|
||||
public double InputVoltage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The minimum valid input voltage to the base.
|
||||
/// </summary>
|
||||
public double MinimumValidInputVoltage { get; set; } = 6D;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum valid input voltage to the base.
|
||||
/// </summary>
|
||||
public double MaximumValidInputVoltage { get; set; } = 16D;
|
||||
|
||||
public virtual bool BatteryMilliVoltsValid => BatteryMilliVolts > 1000D * MinimumValidBatteryVoltage && BatteryMilliVolts < 1000D * MaximumValidBatteryVoltage;
|
||||
|
||||
/// <summary>
|
||||
/// The current battery voltage.
|
||||
/// </summary>
|
||||
public double BatteryMilliVolts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current battery voltage.
|
||||
/// </summary>
|
||||
public double BatteryVoltage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// battery state of charge - null if not queried
|
||||
/// can be 0 if not available
|
||||
/// this is a percentage
|
||||
/// </summary>
|
||||
public double? BatterySoC { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum valid battery voltage to the base.
|
||||
/// </summary>
|
||||
public double MinimumValidBatteryVoltage { get; set; } = 6D;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum valid battery voltage to the base.
|
||||
/// </summary>
|
||||
public double MaximumValidBatteryVoltage { get; set; } = 16D;
|
||||
|
||||
/// <summary>
|
||||
/// TRUE if the battery is currently charging.
|
||||
/// </summary>
|
||||
public bool BatteryIsCharging { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Temperature sensed by logic in the hardware, in degrees Celsius.
|
||||
/// </summary>
|
||||
public double TemperatureC { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns status
|
||||
/// </summary>
|
||||
public virtual string BatteryVoltageStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns status
|
||||
/// </summary>
|
||||
public virtual string InputVoltageStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns status
|
||||
/// </summary>
|
||||
public virtual string StatusDisplayBattery { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns status
|
||||
/// </summary>
|
||||
public virtual string StatusDisplayInput { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns color
|
||||
/// </summary>
|
||||
public virtual DFConstantsAndEnums.VoltageStatusColor BatteryVoltageStatusColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// returns color
|
||||
/// </summary>
|
||||
public virtual DFConstantsAndEnums.VoltageStatusColor InputVoltageStatusColor { get; set; }
|
||||
|
||||
public double ChargeCapacity { get; set; } = double.NaN;
|
||||
|
||||
public bool ChargeCapacityValid => !double.IsNaN(ChargeCapacity) && ChargeCapacity > 0 && ChargeCapacity < 100;
|
||||
public BaseInputValues() { }
|
||||
public BaseInputValues(IBaseInputValues copy)
|
||||
{
|
||||
InputMilliVolts = copy.InputMilliVolts;
|
||||
InputVoltage = copy.InputVoltage;
|
||||
MinimumValidInputVoltage = copy.MinimumValidInputVoltage;
|
||||
MaximumValidInputVoltage = copy.MaximumValidInputVoltage;
|
||||
BatteryMilliVolts = copy.BatteryMilliVolts;
|
||||
BatteryVoltage = copy.BatteryVoltage;
|
||||
BatterySoC = copy.BatterySoC;
|
||||
MinimumValidBatteryVoltage = copy.MinimumValidBatteryVoltage;
|
||||
MaximumValidBatteryVoltage = copy.MaximumValidBatteryVoltage;
|
||||
BatteryIsCharging = copy.BatteryIsCharging;
|
||||
TemperatureC = copy.TemperatureC;
|
||||
BatteryVoltageStatus = copy.BatteryVoltageStatus;
|
||||
InputVoltageStatus = copy.InputVoltageStatus;
|
||||
StatusDisplayBattery = copy.StatusDisplayBattery;
|
||||
StatusDisplayInput = copy.StatusDisplayInput;
|
||||
BatteryVoltageStatusColor = copy.BatteryVoltageStatusColor;
|
||||
InputVoltageStatusColor = copy.InputVoltageStatusColor;
|
||||
ChargeCapacity = copy.ChargeCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
155
DataPRO/IService/Classes/BaseInput/SLICE.Base.Input.Reader.cs
Normal file
155
DataPRO/IService/Classes/BaseInput/SLICE.Base.Input.Reader.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System.Threading;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICEBaseInputReader
|
||||
{
|
||||
private readonly ICommunication _comm;
|
||||
|
||||
public SLICEBaseInputReader(DTS.Common.Interface.DASFactory.ICommunication comm)
|
||||
{
|
||||
_comm = comm;
|
||||
}
|
||||
|
||||
public virtual double InputMilliVolts
|
||||
{
|
||||
get
|
||||
{
|
||||
var measure = new MeasureBaseDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasureBaseDiagnosticChannel.BaseDiagnosticChannelList.InputVoltage;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement * 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual double TemperatureC
|
||||
{
|
||||
get
|
||||
{
|
||||
var measure = new MeasureBaseDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasureBaseDiagnosticChannel.BaseDiagnosticChannelList.TemperatureC;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement;
|
||||
}
|
||||
}
|
||||
|
||||
public bool BatteryIsCharging
|
||||
{
|
||||
get
|
||||
{
|
||||
var setSwitch = new QuerySwitchImmediate(_comm);
|
||||
setSwitch.Switch = (byte)Switches.BaseSwitches.ChargeStatus;
|
||||
setSwitch.SwitchText = Switches.BaseSwitches.ChargeStatus.ToString();
|
||||
setSwitch.SyncExecute();
|
||||
return setSwitch.Setting == 1;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual double DirectBackupMilliVolts
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!ShouldMeasureBackupPower())
|
||||
{
|
||||
return 0D;
|
||||
}
|
||||
var measure = new MeasureBaseDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasureBaseDiagnosticChannel.BaseDiagnosticChannelList.BackupVoltage;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement * 1000.0;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns true if the unit should check/enable/disable backup power
|
||||
/// originally part of the S6 performance improvements
|
||||
/// note that S6 should not have battery power
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool ShouldEnableBackupPower()
|
||||
{
|
||||
switch (_comm)
|
||||
{
|
||||
case EthernetSlice6 _:
|
||||
case EthernetSlice2 _:
|
||||
case EthernetSlice6Air _:
|
||||
case EthernetSlice6AirBridge _:
|
||||
case EthernetTsrAir _:
|
||||
case WinUSBSlice6 _:
|
||||
case CDCUSBSlice _:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// previously there was no ShouldMeasureBackupPower
|
||||
/// and only ShouldEnableBackupPower existed, however
|
||||
/// TSR AIR SHOULD measure backup power and SHOULD NOT
|
||||
/// enable backup power ...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ShouldMeasureBackupPower()
|
||||
{
|
||||
switch (_comm)
|
||||
{
|
||||
case EthernetSlice6 _:
|
||||
case EthernetSlice6Air _:
|
||||
case EthernetSlice6AirBridge _:
|
||||
case WinUSBSlice6 _:
|
||||
case CDCUSBSlice _:
|
||||
return false;
|
||||
case EthernetSlice2 _:
|
||||
case EthernetTsrAir _:
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public double BackupMilliVolts
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ShouldEnableBackupPower())
|
||||
{
|
||||
EnableBackupPower();
|
||||
// wait for a second
|
||||
Thread.Sleep(1500);
|
||||
}
|
||||
return DirectBackupMilliVolts;
|
||||
}
|
||||
finally
|
||||
{
|
||||
DisableBackupPower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableBackupPower()
|
||||
{
|
||||
if (!ShouldEnableBackupPower()) { return; }
|
||||
var setSwitch = new SetSwitchImmediate(_comm);
|
||||
setSwitch.Switch = (byte)Switches.BaseSwitches.BackupPower;
|
||||
setSwitch.SwitchText = Switches.BaseSwitches.BackupPower.ToString();
|
||||
setSwitch.Setting = 1;
|
||||
setSwitch.SyncExecute();
|
||||
}
|
||||
|
||||
private void DisableBackupPower()
|
||||
{
|
||||
if (!ShouldEnableBackupPower()) { return; }
|
||||
var setSwitch = new SetSwitchImmediate(_comm);
|
||||
setSwitch.Switch = (byte)Switches.BaseSwitches.BackupPower;
|
||||
setSwitch.SwitchText = Switches.BaseSwitches.BackupPower.ToString();
|
||||
setSwitch.Setting = 0;
|
||||
setSwitch.SyncExecute();
|
||||
}
|
||||
}
|
||||
}
|
||||
72
DataPRO/IService/Classes/BaseInput/SLICEBaseInputValues.cs
Normal file
72
DataPRO/IService/Classes/BaseInput/SLICEBaseInputValues.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICEBaseInputValues : BaseInputValues
|
||||
{
|
||||
public enum PossibleVoltageStatus
|
||||
{
|
||||
GREEN,
|
||||
YELLOW,
|
||||
RED,
|
||||
OFF
|
||||
}
|
||||
|
||||
public enum PossibleBatteryStatus
|
||||
{
|
||||
GREEN,
|
||||
YELLOW,
|
||||
RED,
|
||||
NOBATTERY,
|
||||
OFF
|
||||
}
|
||||
public override string BatteryVoltageStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BatteryMilliVoltsValid)
|
||||
{
|
||||
if (ChargeCapacityValid)
|
||||
{
|
||||
if (ChargeCapacity > 70)
|
||||
{
|
||||
return PossibleBatteryStatus.GREEN.ToString();
|
||||
}
|
||||
return ChargeCapacity > 40 ? PossibleBatteryStatus.YELLOW.ToString() : PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
if (InputMilliVoltsValid)
|
||||
{
|
||||
if (InputMilliVolts > 11000)
|
||||
{
|
||||
if (BatteryMilliVolts > 7.6)
|
||||
{
|
||||
return PossibleBatteryStatus.GREEN.ToString();
|
||||
}
|
||||
return BatteryMilliVolts > 7.6 ? PossibleBatteryStatus.YELLOW.ToString() : PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
if (InputMilliVolts > 9000)
|
||||
{
|
||||
if (BatteryMilliVolts > 7.8)
|
||||
{
|
||||
return PossibleBatteryStatus.GREEN.ToString();
|
||||
}
|
||||
return BatteryMilliVolts > 7.4 ? PossibleBatteryStatus.YELLOW.ToString() : PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
if (InputMilliVolts < 9)
|
||||
{
|
||||
if (BatteryMilliVolts > 7.8)
|
||||
{
|
||||
return PossibleBatteryStatus.GREEN.ToString();
|
||||
}
|
||||
return BatteryMilliVolts > 7.4 ? PossibleBatteryStatus.YELLOW.ToString() : PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
return PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
return PossibleBatteryStatus.RED.ToString();
|
||||
}
|
||||
return PossibleBatteryStatus.NOBATTERY.ToString();
|
||||
}
|
||||
set {; }//ignore, always generate as needed
|
||||
}
|
||||
}
|
||||
}
|
||||
109
DataPRO/IService/Classes/CAN/CANConfig.cs
Normal file
109
DataPRO/IService/Classes/CAN/CANConfig.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class CANConfig : IXmlSerializable
|
||||
{
|
||||
private readonly Dictionary<string, CANModuleConfig> _modules = new Dictionary<string, CANModuleConfig>();
|
||||
public Dictionary<string, CANModuleConfig> Modules { get { return _modules; } }
|
||||
private readonly string _fileName;
|
||||
public string FileName { get { return _fileName; } }
|
||||
|
||||
public CANConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public CANConfig(string fileName, bool deleteIfPresent)
|
||||
{
|
||||
const string dasConfigs = "DASConfigs";
|
||||
var location = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), dasConfigs), fileName);
|
||||
|
||||
_fileName = location;
|
||||
if (File.Exists(location))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (deleteIfPresent)
|
||||
{
|
||||
try { File.Delete(_fileName); }
|
||||
catch (Exception ex) { APILogger.Log("Problem deleting ", _fileName, ex); }
|
||||
}
|
||||
else { using (var sr = new StreamReader(_fileName)) { ReadXml(XmlReader.Create(sr)); } }
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Problem reading ", _fileName, ex); }
|
||||
}
|
||||
}
|
||||
public void SetModule(CANModuleConfig module)
|
||||
{
|
||||
if (_modules.ContainsKey(module.SerialNumber)) { _modules[module.SerialNumber] = module; }
|
||||
else { _modules.Add(module.SerialNumber, module); }
|
||||
}
|
||||
public CANModuleConfig GetModule(CANModuleConfig module)
|
||||
{
|
||||
if (_modules.ContainsKey(module.SerialNumber)) { return _modules[module.SerialNumber]; }
|
||||
else
|
||||
{
|
||||
_modules.Add(module.SerialNumber, module);
|
||||
return module;
|
||||
}
|
||||
}
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Generates an object from its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// reader:
|
||||
// The System.Xml.XmlReader stream from which the object is deserialized.
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
reader.ReadStartElement("CANConfig");
|
||||
|
||||
reader.ReadStartElement("Modules");
|
||||
|
||||
while (reader.MoveToContent() == XmlNodeType.Element)
|
||||
{
|
||||
CANModuleConfig tConfig = new CANModuleConfig();
|
||||
tConfig.ReadXml(reader);
|
||||
SetModule(tConfig);
|
||||
}
|
||||
|
||||
reader.ReadEndElement();
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Converts an object into its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// writer:
|
||||
// The System.Xml.XmlWriter stream to which the object is serialized.
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("CANConfig");
|
||||
|
||||
writer.WriteStartElement("Modules");
|
||||
writer.Flush();
|
||||
|
||||
foreach (CANModuleConfig module in _modules.Values)
|
||||
{
|
||||
module.WriteXml(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
260
DataPRO/IService/Classes/CAN/CANModuleConfig.cs
Normal file
260
DataPRO/IService/Classes/CAN/CANModuleConfig.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class CANModuleConfig : IXmlSerializable
|
||||
{
|
||||
public string SerialNumber { get; set; } = "";
|
||||
public string TestId { get; set; } = "";
|
||||
public string TestDescription { get; set; } = "";
|
||||
|
||||
public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; } = DFConstantsAndEnums.RecordingMode.InvalidArmMode;
|
||||
public float AAFilterRateHz { get; set; } = 0;
|
||||
public double PreTriggerSeconds { get; set; } = 0;
|
||||
public double PostTriggerSeconds { get; set; } = 0;
|
||||
|
||||
private readonly Dictionary<int, DASChannel> _channels = new Dictionary<int, DASChannel>();
|
||||
|
||||
private readonly string _fileName;
|
||||
public string FileName { get { return _fileName; } }
|
||||
|
||||
public string FirmwareVersion { get; set; } = "";
|
||||
public UInt64? MaxEventStorageSpaceInBytes { get; set; } = 0;
|
||||
public int ModuleArrayIndex { get; set; } = 0;
|
||||
|
||||
public CANModuleConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public CANModuleConfig(string fileName)
|
||||
{
|
||||
const string dasConfigs = "DASConfigs";
|
||||
var location = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), dasConfigs), fileName);
|
||||
_fileName = location;
|
||||
if (File.Exists(_fileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(_fileName))
|
||||
{
|
||||
ReadXml(System.Xml.XmlReader.Create(sr));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem reading ", _fileName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void SetChannel(CANInputDASChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { _channels[channel.ModuleChannelNumber] = channel; }
|
||||
else { _channels.Add(channel.ModuleChannelNumber, channel); }
|
||||
}
|
||||
public CANInputDASChannel GetChannel(CANInputDASChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { return _channels[channel.ModuleChannelNumber] as CANInputDASChannel; }
|
||||
else
|
||||
{
|
||||
_channels.Add(channel.ModuleChannelNumber, channel);
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Generates an object from its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// reader:
|
||||
// The System.Xml.XmlReader stream from which the object is deserialized.
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
reader.ReadStartElement("CANModule");
|
||||
reader.ReadStartElement("SerialNumber");
|
||||
SerialNumber = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("TestId");
|
||||
TestId = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("TestDescription");
|
||||
TestDescription = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("RecordingMode");
|
||||
string recordingMode = reader.ReadString();
|
||||
try
|
||||
{
|
||||
RecordingMode = (DFConstantsAndEnums.RecordingMode)Enum.Parse(typeof(DFConstantsAndEnums.RecordingMode), recordingMode);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load RecordingMode ", recordingMode, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("AAFilterRateHz");
|
||||
string aaFilterRateHz = reader.ReadString();
|
||||
try
|
||||
{
|
||||
AAFilterRateHz = (float)Convert.ToDouble(aaFilterRateHz);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load AAFilterRateHz ", aaFilterRateHz, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("PreTriggerSeconds");
|
||||
string preTriggerSeconds = reader.ReadString();
|
||||
try
|
||||
{
|
||||
PreTriggerSeconds = Convert.ToDouble(preTriggerSeconds);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load PreTriggerSeconds ", preTriggerSeconds, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("PostTriggerSeconds");
|
||||
string postTriggerSeconds = reader.ReadString();
|
||||
try
|
||||
{
|
||||
PostTriggerSeconds = Convert.ToDouble(postTriggerSeconds);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load PostTriggerSeconds ", postTriggerSeconds, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("FirmwareVersion");
|
||||
FirmwareVersion = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("MaxEventStorageSpaceInBytes");
|
||||
string maxEventStorageSpaceInBytes = reader.ReadString();
|
||||
|
||||
double d;
|
||||
if (double.TryParse(maxEventStorageSpaceInBytes, out d))
|
||||
{
|
||||
if (d >= 0 && d < ulong.MaxValue) { MaxEventStorageSpaceInBytes = Convert.ToUInt64(d); }
|
||||
else { APILogger.Log("Failed to load MaxEventStorageSpaceInBytes ", maxEventStorageSpaceInBytes); }
|
||||
}
|
||||
else { APILogger.Log("Failed to load MaxEventStorageSpaceInBytes ", maxEventStorageSpaceInBytes); }
|
||||
|
||||
reader.ReadEndElement();
|
||||
ReadModuleArray(reader);
|
||||
|
||||
reader.ReadStartElement("Channels");
|
||||
|
||||
while (reader.MoveToContent() == XmlNodeType.Element)
|
||||
{
|
||||
CANInputDASChannel cic = new CANInputDASChannel();
|
||||
cic.ReadXml(reader);
|
||||
SetChannel(cic);
|
||||
}
|
||||
|
||||
reader.ReadEndElement();
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
//FB 45086 sonarqube - reduce cyclomatic complexity
|
||||
private void ReadModuleArray(XmlReader reader)
|
||||
{
|
||||
try
|
||||
{
|
||||
reader.ReadStartElement("ModuleArrayIndex");
|
||||
string moduleArrayIndex = reader.ReadString();
|
||||
|
||||
int m;
|
||||
if (int.TryParse(moduleArrayIndex, out m))
|
||||
{
|
||||
if (m >= 0 && m < int.MaxValue) { ModuleArrayIndex = Convert.ToInt32(m); }
|
||||
else { APILogger.Log("Failed to load ModuleArrayIndex ", moduleArrayIndex); }
|
||||
}
|
||||
else { APILogger.Log("Failed to load ModuleArrayIndex ", moduleArrayIndex); }
|
||||
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//This must be an old config file
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Converts an object into its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// writer:
|
||||
// The System.Xml.XmlWriter stream to which the object is serialized.
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
//writer.WriteStartElement ( attributeExtractor.ExtractAttachedAttributeFromObject ( this
|
||||
writer.WriteStartElement("CANModule");
|
||||
writer.WriteStartElement("SerialNumber");
|
||||
writer.WriteString(SerialNumber);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("TestId");
|
||||
writer.WriteString(TestId);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("TestDescription");
|
||||
writer.WriteString(TestDescription);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("RecordingMode");
|
||||
writer.WriteString(RecordingMode.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("AAFilterRateHz");
|
||||
writer.WriteString(AAFilterRateHz.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("PreTriggerSeconds");
|
||||
writer.WriteString(PreTriggerSeconds.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("PostTriggerSeconds");
|
||||
writer.WriteString(PostTriggerSeconds.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("FirmwareVersion");
|
||||
writer.WriteString(FirmwareVersion);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("MaxEventStorageSpaceInBytes");
|
||||
writer.WriteString(MaxEventStorageSpaceInBytes.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("ModuleArrayIndex");
|
||||
writer.WriteString(ModuleArrayIndex.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("Channels");
|
||||
writer.Flush();
|
||||
|
||||
foreach (DASChannel channel in _channels.Values)
|
||||
{
|
||||
channel.WriteElementStart(writer);
|
||||
channel.WriteXml(writer);
|
||||
channel.WriteElementEnd(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
writer.Flush();
|
||||
}
|
||||
public virtual void WriteElementStart(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("CANModule");
|
||||
var tgt = GetType();
|
||||
writer.WriteAttributeString("xsi", "type", null, tgt.Name);
|
||||
}
|
||||
|
||||
public virtual void WriteElementEnd(XmlWriter writer)
|
||||
{
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
2629
DataPRO/IService/Classes/CAN/SLICEProFD.cs
Normal file
2629
DataPRO/IService/Classes/CAN/SLICEProFD.cs
Normal file
File diff suppressed because it is too large
Load Diff
1401
DataPRO/IService/Classes/Channels/AnalogInputDASChannel.cs
Normal file
1401
DataPRO/IService/Classes/Channels/AnalogInputDASChannel.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
// Custom comparer for the IDASCommunication class.
|
||||
public class AnalogInputDASChannelComparer : IEqualityComparer<AnalogInputDASChannel>
|
||||
{
|
||||
// GainInfo are equal if their Gain is equal.
|
||||
public bool Equals(AnalogInputDASChannel x, AnalogInputDASChannel y)
|
||||
{
|
||||
// Check whether the compared objects reference the same data.
|
||||
if (ReferenceEquals(x, y))
|
||||
return true;
|
||||
|
||||
// Check whether any of the compared objects is null.
|
||||
if (x is null || y is null)
|
||||
return false;
|
||||
|
||||
if (x.OwningModule == null || y.OwningModule == null)
|
||||
return false;
|
||||
|
||||
if (x.OwningModule.OwningDAS == null || y.OwningModule.OwningDAS == null)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(x.OwningModule.OwningDAS.SerialNumber) ||
|
||||
string.IsNullOrEmpty(y.OwningModule.OwningDAS.SerialNumber))
|
||||
return false;
|
||||
|
||||
// Check whether they are equal.
|
||||
return x.ModuleChannelNumber == y.ModuleChannelNumber &&
|
||||
x.OwningModule.ModuleArrayIndex == y.OwningModule.ModuleArrayIndex &&
|
||||
x.OwningModule.OwningDAS.SerialNumber == y.OwningModule.OwningDAS.SerialNumber &&
|
||||
x.AbsoluteDisplayOrder == y.AbsoluteDisplayOrder &&
|
||||
x.UnitConverision == y.UnitConverision;
|
||||
}
|
||||
|
||||
// If Equals() returns true for a pair of objects,
|
||||
// GetHashCode must return the same value for these objects.
|
||||
|
||||
public int GetHashCode(AnalogInputDASChannel analog)
|
||||
{
|
||||
// Check whether the object is null.
|
||||
|
||||
if (string.IsNullOrEmpty(analog.OwningModule?.OwningDAS?.SerialNumber))
|
||||
return 0;
|
||||
|
||||
// Get the hash code for the fields
|
||||
return analog.ModuleChannelNumber.GetHashCode() ^
|
||||
analog.OwningModule.ModuleArrayIndex.GetHashCode() ^
|
||||
analog.OwningModule.OwningDAS.SerialNumber.GetHashCode() ^
|
||||
analog.AbsoluteDisplayOrder.GetHashCode() ^
|
||||
analog.UnitConverision.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
21
DataPRO/IService/Classes/Channels/AnalogOutputDASChannel.cs
Normal file
21
DataPRO/IService/Classes/Channels/AnalogOutputDASChannel.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Analog output channel.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class AnalogOutputDASChannel : OutputDASChannel
|
||||
{
|
||||
public AnalogOutputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public AnalogOutputDASChannel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
122
DataPRO/IService/Classes/Channels/CANInputDASChannel.cs
Normal file
122
DataPRO/IService/Classes/Channels/CANInputDASChannel.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using System.Xml;
|
||||
using System.IO.Ports;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for storing/applying CAN settings as a channel
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CANInputDASChannel : InputDASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public CANInputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
SerialNumber = owner.SerialNumber();
|
||||
}
|
||||
|
||||
public CANInputDASChannel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Serial number of the sensor.
|
||||
/// </summary>
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the hardware channel
|
||||
/// </summary>
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public bool IsFD { get; set; }
|
||||
public int ArbBaseBitrate { get; set; }
|
||||
public int ArbBaseSJW { get; set; }
|
||||
public int DataBitrate { get; set; }
|
||||
public int DataSJW { get; set; }
|
||||
public string FileType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the channel has a serial number in the SerialNumber field, it is "Configured".
|
||||
/// </summary>
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return !string.IsNullOrEmpty(SerialNumber);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CAN{ModuleChannelNumber}";
|
||||
}
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
// SerialNumber
|
||||
XMLHelper.PutString(writer, "SerialNumber", SerialNumber);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutString(writer, "IsFD", IsFD.ToString());
|
||||
XMLHelper.PutString(writer, "ArbBaseBitrate", ArbBaseBitrate.ToString());
|
||||
XMLHelper.PutString(writer, "ArbBaseSJW", ArbBaseSJW.ToString());
|
||||
XMLHelper.PutString(writer, "DataBitrate", DataBitrate.ToString());
|
||||
XMLHelper.PutString(writer, "DataSJW", DataSJW.ToString());
|
||||
XMLHelper.PutString(writer, "FileType", FileType);
|
||||
}
|
||||
private const string SERIALNUMBER_TAG = "SerialNumber";
|
||||
private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName";
|
||||
private const string ISFD_TAG = "IsFD";
|
||||
private const string ARBBASEBITRATE_TAG = "ArbBaseBitrate";
|
||||
private const string ARBBASESJW_TAG = "ArbBaseSJW";
|
||||
private const string DATABITRATE_TAG = "DataBitrate";
|
||||
private const string DATASJW_TAG = "DataSJW";
|
||||
private const string FILETYPE_TAG = "FileType";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case SERIALNUMBER_TAG:
|
||||
SerialNumber = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case HARDWARECHANNELNAME_TAG:
|
||||
HardwareChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case ISFD_TAG:
|
||||
IsFD = Convert.ToBoolean(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case ARBBASEBITRATE_TAG:
|
||||
ArbBaseBitrate = Convert.ToInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case ARBBASESJW_TAG:
|
||||
ArbBaseSJW = Convert.ToInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case DATABITRATE_TAG:
|
||||
DataBitrate = Convert.ToInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case DATASJW_TAG:
|
||||
DataSJW = Convert.ToInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case FILETYPE_TAG:
|
||||
FileType = XMLHelper.GetString(reader);
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
377
DataPRO/IService/Classes/Channels/DASChannel.cs
Normal file
377
DataPRO/IService/Classes/Channels/DASChannel.cs
Normal file
@@ -0,0 +1,377 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Base class for all DAS channels.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class DASChannel : IDASChannel, IXmlSerializable // (subset of sensor class)
|
||||
{
|
||||
|
||||
public string SetupEID { get; set; } = string.Empty;
|
||||
public string DataCollectionEID { get; set; } = string.Empty;
|
||||
|
||||
public DFConstantsAndEnums.ConfigMode ConfigurationMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// whether the channel should be put in Diagnostics mode or not
|
||||
/// </summary>
|
||||
public bool DiagnosticsMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Channel number with respect to it's containing module <see cref="OwningModule"/>
|
||||
/// </summary>
|
||||
public int ModuleChannelNumber { get; set; }
|
||||
|
||||
public int AbsoluteDisplayOrder { get; set; } = 1;
|
||||
|
||||
public double UnitConverision { get; set; } = 1D;
|
||||
|
||||
public bool AtCapacity { get; set; } = false;
|
||||
|
||||
public double CapacityOutputIsBasedOn { get; set; } = 1D;
|
||||
|
||||
public SensorConstants.SensUnits SensitivityUnits { get; set; } =
|
||||
SensorConstants.SensUnits.NONE;
|
||||
|
||||
/// <summary>
|
||||
/// A link back to the Module that contains this channel.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public DASModule OwningModule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The "stack channel number" of this channel with respect to the owning
|
||||
/// DAS (0 based).
|
||||
/// </summary>
|
||||
public byte Number
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return OwningModule.OwningDAS.DASInfo.MapModuleArrayIndexAndChannelNum2DASChannel(OwningModule.ModuleArrayIndex, ModuleChannelNumber);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ApplicationException("encountered problem getting " + GetType().FullName + ".Number property value", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array of (string, byte[]) for EID
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public IEID[] IDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// time stamp of this event
|
||||
/// </summary>
|
||||
public DateTime EventStartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="bool"/> value indicating whether or not this channel has registered a level trigger.
|
||||
/// </summary>
|
||||
public bool LevelTriggerSeen { get; set; }
|
||||
|
||||
public string IsoChannelName { get; set; }
|
||||
public string ChannelGroupName { get; set; }
|
||||
public string UserCode { get; set; }
|
||||
public string UserChannelName { get; set; }
|
||||
public string LinearSensorCalibration { get; set; }
|
||||
/// <summary>
|
||||
/// the number of samples to qualify over
|
||||
/// </summary>
|
||||
public int QualificationSamples { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// Number of samples that T0 on DASes that did not directly experience the level trigger must be shifted
|
||||
///// to time align with this channel's directly level triggered T0. A null value indicates that this channel
|
||||
///// did not directly receive a level trigger.
|
||||
///// </summary>
|
||||
public int? LevelTriggerT0AdjustmentSamples { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ModuleChannelNumber.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this channel configured? 'Configured' means a sensor is connected and/or there is
|
||||
/// information in the containg device's ConfigData object, put there with a call to
|
||||
/// ConfigureService.Configure(...) in the API.
|
||||
/// </summary>
|
||||
/// <returns>True if it is configured, False otherwise.</returns>
|
||||
public virtual bool IsConfigured()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public DASChannel(DASModule owner, int channelNumber)
|
||||
{
|
||||
ConfigurationMode = DFConstantsAndEnums.ConfigMode.Normal;
|
||||
ModuleChannelNumber = channelNumber;
|
||||
OwningModule = owner;
|
||||
IDs = null;
|
||||
EventStartTime = DateTime.Now;
|
||||
DiagnosticsMode = false;
|
||||
}
|
||||
|
||||
public DASChannel()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void WriteElementStart(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("DASChannel");
|
||||
//writer.WriteStartAttribute("type", "xsi");
|
||||
var tgt = GetType();
|
||||
writer.WriteAttributeString("xsi", "type", null, tgt.Name);
|
||||
}
|
||||
|
||||
public virtual void WriteElementEnd(XmlWriter writer)
|
||||
{
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
public virtual void WriteXmlCRC32(XmlWriter writer)
|
||||
{
|
||||
// ConfigurationMode
|
||||
XMLHelper.PutString(writer, "ConfigurationMode", ConfigurationMode.ToString());
|
||||
|
||||
// ModuleChannelNumber
|
||||
XMLHelper.PutInt(writer, "ModuleChannelNumber", ModuleChannelNumber);
|
||||
XMLHelper.PutInt(writer, "AbsoluteDisplayOrder", AbsoluteDisplayOrder);
|
||||
XMLHelper.PutBool(writer, "DiagnosticsMode", DiagnosticsMode);
|
||||
XMLHelper.PutDouble(writer, "UnitConversion", UnitConverision);
|
||||
// EventStartTime
|
||||
//XMLHelper.PutString(writer, "EventStartTime", EventStartTime.ToString("o", XMLHelper.InvariantCulture));
|
||||
}
|
||||
public virtual void WriteXml(XmlWriter writer)
|
||||
{
|
||||
// ConfigurationMode
|
||||
XMLHelper.PutString(writer, "ConfigurationMode", ConfigurationMode.ToString());
|
||||
|
||||
// ModuleChannelNumber
|
||||
XMLHelper.PutInt(writer, "ModuleChannelNumber", ModuleChannelNumber);
|
||||
|
||||
XMLHelper.PutInt(writer, "AbsoluteDisplayOrder", AbsoluteDisplayOrder);
|
||||
// EventStartTime
|
||||
XMLHelper.PutString(writer, "EventStartTime", EventStartTime.ToString("o", XMLHelper.InvariantCulture));
|
||||
|
||||
//XMLHelper.PutString(writer, "QualificationSamples", QualificationSamples.ToString());
|
||||
XMLHelper.PutInt(writer, "QualificationSamples", QualificationSamples);
|
||||
|
||||
XMLHelper.PutBool(writer, "DiagnosticsMode", DiagnosticsMode);
|
||||
|
||||
XMLHelper.PutDouble(writer, "UnitConversion", UnitConverision);
|
||||
|
||||
XMLHelper.PutBool(writer, "AtCapacity", AtCapacity);
|
||||
|
||||
XMLHelper.PutDouble(writer, "CapacityOutputIsBasedOn", CapacityOutputIsBasedOn);
|
||||
|
||||
XMLHelper.PutString(writer, "SensitivityUnits", SensitivityUnits.ToString());
|
||||
|
||||
XMLHelper.PutString(writer, "IsoChannelName", IsoChannelName);
|
||||
XMLHelper.PutString(writer, "UserCode", UserCode);
|
||||
XMLHelper.PutString(writer, "UserChannelName", UserChannelName);
|
||||
XMLHelper.PutString(writer, "LinearSensorCalibration", LinearSensorCalibration);
|
||||
if (!string.IsNullOrEmpty(UserValue1))
|
||||
{
|
||||
XMLHelper.PutString(writer, "UserValue1", UserValue1);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(UserValue2))
|
||||
{
|
||||
XMLHelper.PutString(writer, "UserValue2", UserValue2);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(UserValue3))
|
||||
{
|
||||
XMLHelper.PutString(writer, "UserValue3", UserValue3);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(SetupEID))
|
||||
{
|
||||
XMLHelper.PutString(writer, SETUPEID_TAG, SetupEID);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DataCollectionEID))
|
||||
{
|
||||
XMLHelper.PutString(writer, DATACOLLECTIONEID_TAG, DataCollectionEID);
|
||||
}
|
||||
}
|
||||
private const string CONFIGUARATIONMODE_TAG = "ConfigurationMode";
|
||||
private const string MODULECHANNELNUMBER_TAG = "ModuleChannelNumber";
|
||||
private const string EVENTSTARTTIME_TAG = "EventStartTime";
|
||||
private const string QUALIFICATIONSAMPLES_TAG = "QualificationSamples";
|
||||
private const string DIAGNOSTICSMODE_TAG = "DiagnosticsMode";
|
||||
private const string ABSOLUTEDISPLAYORDER_TAG = "AbsoluteDisplayOrder";
|
||||
private const string UNITCONVERSION_TAG = "UnitConversion";
|
||||
private const string ATCAPACITY_TAG = "AtCapacity";
|
||||
private const string LINEARSENSORCALIBRATION_TAG = "LinearSensorCalibration";
|
||||
private const string USERCHANNELNAME_TAG = "UserChannelName";
|
||||
private const string USERCODE_TAG = "UserCode";
|
||||
private const string ISOCHANNELNAME_TAG = "IsoChannelName";
|
||||
private const string CAPACITYOUTPUTISBASEDON_TAG = "CapacityOutputIsBasedOn";
|
||||
private const string SENSITIVITYUNITS_TAG = "SensitivityUnits";
|
||||
private const string USERVALUE1_TAG = "UserValue1";
|
||||
private const string USERVALUE2_TAG = "UserValue2";
|
||||
private const string USERVALUE3_TAG = "UserValue3";
|
||||
private const string SETUPEID_TAG = "SetupEID";
|
||||
private const string DATACOLLECTIONEID_TAG = "DataCollectionEID";
|
||||
|
||||
protected virtual void HandleElement(XmlReader reader)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case CONFIGUARATIONMODE_TAG:
|
||||
var confMode = XMLHelper.GetString(reader);
|
||||
ConfigurationMode = (DFConstantsAndEnums.ConfigMode)Enum.Parse(typeof(DFConstantsAndEnums.ConfigMode), confMode);
|
||||
break;
|
||||
case MODULECHANNELNUMBER_TAG:
|
||||
ModuleChannelNumber = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case EVENTSTARTTIME_TAG:
|
||||
var est = XMLHelper.GetString(reader);
|
||||
EventStartTime = DateTime.Parse(est);
|
||||
break;
|
||||
case QUALIFICATIONSAMPLES_TAG:
|
||||
QualificationSamples = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case DIAGNOSTICSMODE_TAG:
|
||||
DiagnosticsMode = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case ABSOLUTEDISPLAYORDER_TAG:
|
||||
AbsoluteDisplayOrder = XMLHelper.TryGetInt(reader, 1);
|
||||
break;
|
||||
case UNITCONVERSION_TAG:
|
||||
UnitConverision = XMLHelper.TryGetDouble(reader, 1D);
|
||||
break;
|
||||
case ATCAPACITY_TAG:
|
||||
try { AtCapacity = XMLHelper.GetBool(reader); }
|
||||
catch (Exception) { }
|
||||
break;
|
||||
case LINEARSENSORCALIBRATION_TAG:
|
||||
LinearSensorCalibration = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case USERCHANNELNAME_TAG:
|
||||
UserChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case USERCODE_TAG:
|
||||
UserCode = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case ISOCHANNELNAME_TAG:
|
||||
IsoChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case CAPACITYOUTPUTISBASEDON_TAG:
|
||||
CapacityOutputIsBasedOn = XMLHelper.TryGetDouble(reader, 1D);
|
||||
break;
|
||||
case SENSITIVITYUNITS_TAG:
|
||||
var su = XMLHelper.GetString(reader);
|
||||
SensitivityUnits = (SensorConstants.SensUnits)Enum.Parse(typeof(SensorConstants.SensUnits), su);
|
||||
break;
|
||||
case USERVALUE1_TAG:
|
||||
UserValue1 = XMLHelper.TryGetString(reader, "");
|
||||
break;
|
||||
case USERVALUE2_TAG:
|
||||
UserValue2 = XMLHelper.TryGetString(reader, "");
|
||||
break;
|
||||
case USERVALUE3_TAG:
|
||||
UserValue3 = XMLHelper.TryGetString(reader, "");
|
||||
break;
|
||||
case SETUPEID_TAG:
|
||||
try { SetupEID = XMLHelper.GetString(reader); }
|
||||
catch(Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
case DATACOLLECTIONEID_TAG:
|
||||
try { DataCollectionEID = XMLHelper.GetString(reader); }
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
return;
|
||||
}
|
||||
}
|
||||
public virtual void ReadXml(XmlReader reader)
|
||||
{
|
||||
// it must be an Element
|
||||
if (reader.NodeType != XmlNodeType.Element)
|
||||
{
|
||||
throw new XmlException("DASChannel.ReadXml: Unknown input: " + reader.NodeType.ToString());
|
||||
}
|
||||
|
||||
// skip our start tag
|
||||
if (reader.Name == "DASChannel")
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
// try to find our data
|
||||
do
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
HandleElement(reader);
|
||||
}
|
||||
if (!reader.Read())
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (!(reader.Name.Equals("DASChannel") && reader.NodeType == XmlNodeType.EndElement));
|
||||
|
||||
// we're going to end with an EndElement, so clean up
|
||||
if (reader.Name.Equals("DASChannel") && reader.NodeType == XmlNodeType.EndElement)
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns true if the channel is re-programable [can be switched from IEPE to analog]
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool CanReProgram()
|
||||
{
|
||||
if (null == OwningModule) { return false; }
|
||||
if (null == OwningModule.OwningDAS) { return false; }
|
||||
if (null == OwningModule.OwningDAS.DASInfo) { return false; }
|
||||
if (null == OwningModule.OwningDAS.DASInfo.Modules) { return false; }
|
||||
if (0 == OwningModule.OwningDAS.DASInfo.Modules.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return OwningModule.OwningDAS.DASInfo.Modules[0].IsProgrammable;
|
||||
}
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public const int DEFAULT_ID_TYPE = 0;
|
||||
public const int BRIDGE_ID_TYPE = 1;
|
||||
public const int IEPE_ID_TYPE = 2;
|
||||
public const int BRIDGE_G5_ID_TYPE = 3;
|
||||
|
||||
public int IdType { get; set; } = DEFAULT_ID_TYPE;
|
||||
|
||||
public string UserValue1 { get; set; } = "";
|
||||
public string UserValue2 { get; set; } = "";
|
||||
public string UserValue3 { get; set; } = "";
|
||||
|
||||
}
|
||||
}
|
||||
21
DataPRO/IService/Classes/Channels/DigitalOutputDASChannel.cs
Normal file
21
DataPRO/IService/Classes/Channels/DigitalOutputDASChannel.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Digital output channel.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class DigitalOutputDASChannel : OutputDASChannel
|
||||
{
|
||||
public DigitalOutputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public DigitalOutputDASChannel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
27
DataPRO/IService/Classes/Channels/InputDASChannel.cs
Normal file
27
DataPRO/IService/Classes/Channels/InputDASChannel.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Base class for input channels.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class InputDASChannel : DASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public InputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public InputDASChannel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
21
DataPRO/IService/Classes/Channels/OutputDASChannel.cs
Normal file
21
DataPRO/IService/Classes/Channels/OutputDASChannel.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Base class for output channels.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class OutputDASChannel : DASChannel
|
||||
{
|
||||
public OutputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public OutputDASChannel()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
360
DataPRO/IService/Classes/Channels/OutputSquibChannel.cs
Normal file
360
DataPRO/IService/Classes/Channels/OutputSquibChannel.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Base class for SQUIB channels.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class OutputSquibChannel : AnalogOutputDASChannel, IComparable
|
||||
{
|
||||
public SquibFireMode[] SupportedSquibFireModes { get; set; } = { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE };
|
||||
public IDiagnosticResult Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
IDiagnosticResult[] allChannelDiagnostics;
|
||||
IEnumerable<IDiagnosticResult> theseChannelDiagnostics;
|
||||
if (null == (allChannelDiagnostics = OwningModule.OwningDAS.ChannelDiagnosticsResults))
|
||||
throw new InvalidDataException("No diagnostics available (for any channel)");
|
||||
if (null == (theseChannelDiagnostics = (allChannelDiagnostics.Where(r => r.DASChannelNumber == Number))))
|
||||
throw new NullReferenceException("No diagnostics available (for this channel)");
|
||||
if (theseChannelDiagnostics.Count() > 1)
|
||||
throw new InvalidDataException("Several diagnostics results were found for the specified channel; only one was expected");
|
||||
if (theseChannelDiagnostics.Count() < 1)
|
||||
{
|
||||
throw new NullReferenceException("No diagnostics available (for this channel)");
|
||||
}
|
||||
return theseChannelDiagnostics.First();
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ApplicationException("encountered problem getting diagnostics for channel ", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SquibDescription.Trim()))
|
||||
return SquibDescription.Trim();
|
||||
return base.ToString();
|
||||
}
|
||||
int IComparable.CompareTo(object o)
|
||||
{
|
||||
if (null == o) { return 1; }
|
||||
if (o is OutputSquibChannel)
|
||||
{
|
||||
return SquibDescription.CompareTo((o as OutputSquibChannel).SquibDescription);
|
||||
}
|
||||
return SquibDescription.CompareTo(o.ToString());
|
||||
}
|
||||
|
||||
public SquibFireMode FireMode { get; set; } = SquibFireMode.NONE;
|
||||
|
||||
public SquibMeasurementType MeasurementType { get; set; } = SquibMeasurementType.NONE;
|
||||
|
||||
public bool BypassCurrentFilter { get; set; } = false;
|
||||
|
||||
public bool BypassVoltageFilter { get; set; } = false;
|
||||
|
||||
public double SquibToleranceLow { get; set; } = 0D;
|
||||
|
||||
public double SquibToleranceHigh { get; set; } = 0D;
|
||||
|
||||
public double SquibOutputCurrent { get; set; } = 0D;
|
||||
|
||||
public double SquibMeasuredOhms { get; set; } = 0D;
|
||||
|
||||
public bool SquibFiredValid { get; set; } = false;
|
||||
|
||||
public bool SquibFiredPassed { get; set; } = false;
|
||||
|
||||
public double DelayMS { get; set; } = 0D;
|
||||
|
||||
public double DurationMS { get; set; } = 0D;
|
||||
|
||||
public string SquibDescription { get; set; } = "";
|
||||
|
||||
public string ISOCode { get; set; } = "";
|
||||
|
||||
public string ChannelId { get; set; }
|
||||
|
||||
public string ChannelName2 { get; set; }
|
||||
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public bool LimitDuration { get; set; }
|
||||
|
||||
public short PreTestDataZeroLevelADC { get; set; }
|
||||
|
||||
public double ScaleFactorMv { get; set; } = 0D;
|
||||
|
||||
public bool LocalOnly { get; set; } = false;
|
||||
|
||||
public string LastModifiedBy { get; set; }
|
||||
public string Sensor { get; set; }
|
||||
|
||||
public string SerialNumber { get; set; } = "";
|
||||
/// <summary>
|
||||
/// controls the frequency of software filters for squib channels
|
||||
/// 8747 - TDC by default will filter at 1650hz
|
||||
/// </summary>
|
||||
public double SoftwareFilterFrequency { get; set; }
|
||||
public OutputSquibChannel(XmlReader reader)
|
||||
{
|
||||
SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE };
|
||||
IDs = new[] { new EID() };
|
||||
ReadXml(reader);
|
||||
}
|
||||
public OutputSquibChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE };
|
||||
IDs = new[] { new EID() };
|
||||
}
|
||||
|
||||
public OutputSquibChannel()
|
||||
{
|
||||
SupportedSquibFireModes = new[] { SquibFireMode.AC, SquibFireMode.CAP, SquibFireMode.CONSTANT, SquibFireMode.NONE };
|
||||
IDs = new[] { new EID() };
|
||||
}
|
||||
public override void WriteXmlCRC32(XmlWriter writer)
|
||||
{
|
||||
base.WriteXmlCRC32(writer);
|
||||
|
||||
XMLHelper.PutBool(writer, "BypassCurrentFilter", BypassCurrentFilter);
|
||||
XMLHelper.PutBool(writer, "BypassVoltageFilter", BypassVoltageFilter);
|
||||
XMLHelper.PutDouble(writer, "DelayMS", DelayMS);
|
||||
XMLHelper.PutDouble(writer, "DurationMS", DurationMS);
|
||||
XMLHelper.PutString(writer, "FireMode", FireMode.ToString());
|
||||
XMLHelper.PutString(writer, "ISOCode", ISOCode);
|
||||
XMLHelper.PutString(writer, "MeasurementType", MeasurementType.ToString());
|
||||
XMLHelper.PutString(writer, "SquibDescription", SquibDescription);
|
||||
XMLHelper.PutString(writer, "ChannelName2", ChannelName2);
|
||||
XMLHelper.PutString(writer, "ChannelId", ChannelId);
|
||||
XMLHelper.PutString(writer, "ChannelGroupName", ChannelGroupName);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutDouble(writer, "SquibOutputCurrent", SquibOutputCurrent);
|
||||
XMLHelper.PutDouble(writer, "SquibToleranceHigh", SquibToleranceHigh);
|
||||
XMLHelper.PutDouble(writer, "SquibToleranceLow", SquibToleranceLow);
|
||||
XMLHelper.PutBool(writer, "LimitDuration", LimitDuration);
|
||||
XMLHelper.PutString(writer, "ArticleId", "");
|
||||
|
||||
XMLHelper.PutString(writer, "SupportedSquibFireModes", GetSerializedSupportedSquibFireModes());
|
||||
XMLHelper.PutDouble(writer, "SoftwareFilterFrequency", SoftwareFilterFrequency);
|
||||
XMLHelper.PutString(writer, "Sensor", Sensor);
|
||||
}
|
||||
private readonly string _SEPARATOR = "@";
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
XMLHelper.PutBool(writer, "BypassCurrentFilter", BypassCurrentFilter);
|
||||
XMLHelper.PutBool(writer, "BypassVoltageFilter", BypassVoltageFilter);
|
||||
XMLHelper.PutDouble(writer, "DelayMS", DelayMS);
|
||||
XMLHelper.PutDouble(writer, "DurationMS", DurationMS);
|
||||
XMLHelper.PutString(writer, "FireMode", FireMode.ToString());
|
||||
XMLHelper.PutString(writer, "ISOCode", ISOCode);
|
||||
XMLHelper.PutString(writer, "MeasurementType", MeasurementType.ToString());
|
||||
XMLHelper.PutString(writer, "SquibDescription", SquibDescription);
|
||||
XMLHelper.PutString(writer, "ChannelName2", ChannelName2);
|
||||
XMLHelper.PutString(writer, "ChannelId", ChannelId);
|
||||
XMLHelper.PutString(writer, "ChannelGroupName", ChannelGroupName);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutBool(writer, "SquibFirePassed", SquibFiredPassed);
|
||||
XMLHelper.PutBool(writer, "SquibFireValid", SquibFiredValid);
|
||||
XMLHelper.PutDouble(writer, "SquibOhms", SquibMeasuredOhms);
|
||||
XMLHelper.PutDouble(writer, "SquibOutputCurrent", SquibOutputCurrent);
|
||||
XMLHelper.PutDouble(writer, "SquibToleranceHigh", SquibToleranceHigh);
|
||||
XMLHelper.PutDouble(writer, "SquibToleranceLow", SquibToleranceLow);
|
||||
XMLHelper.PutBool(writer, "LimitDuration", LimitDuration);
|
||||
XMLHelper.PutDouble(writer, "ScaleFactorMv", ScaleFactorMv);
|
||||
XMLHelper.PutInt(writer, "PreTestDataZeroLevelADC", PreTestDataZeroLevelADC);
|
||||
XMLHelper.PutString(writer, "ArticleId", "");
|
||||
XMLHelper.PutString(writer, "SupportedSquibFireModes", GetSerializedSupportedSquibFireModes());
|
||||
XMLHelper.PutDouble(writer, "SoftwareFilterFrequency", SoftwareFilterFrequency);
|
||||
XMLHelper.PutString(writer, "Sensor", Sensor);
|
||||
XMLHelper.PutString(writer, "SerialNumber", SerialNumber);
|
||||
}
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
public string GetSerializedSupportedSquibFireModes()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (var s in SupportedSquibFireModes)
|
||||
{
|
||||
if (sb.Length > 0) { sb.Append(_SEPARATOR); }
|
||||
sb.Append(s);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private SquibFireMode[] DeserializeSquibFireModes(string s)
|
||||
{
|
||||
var modes = new List<SquibFireMode>();
|
||||
var tokens = s.Split(new[] { _SEPARATOR }, StringSplitOptions.None);
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (Enum.TryParse(token, out SquibFireMode mode)) { modes.Add(mode); }
|
||||
}
|
||||
return modes.ToArray();
|
||||
}
|
||||
|
||||
private const string BYPASSCURRENTFILTER_TAG = "BypassCurrentFilter";
|
||||
private const string BYPASSVOLTAGEFILTER_TAG = "BypassVoltageFilter";
|
||||
private const string DELAYMS_TAG = "DelayMS";
|
||||
private const string DURATIONMS_TAG = "DurationMS";
|
||||
private const string FIREMODE_TAG = "FireMode";
|
||||
private const string ISOCODE_TAG = "ISOCode";
|
||||
private const string MEASUREMENTTYPE_TAG = "MeasurementType";
|
||||
private const string SQUIBDESCRIPTION_TAG = "SquibDescription";
|
||||
private const string CHANNELID_TAG = "ChannelId";
|
||||
private const string CHANNELGROUPNAME_TAG = "ChannelGroupName";
|
||||
private const string CHANNELNAME2_TAG = "ChannelName2";
|
||||
private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName";
|
||||
private const string SQUIBFIREPASSED_TAG = "SquibFirePassed";
|
||||
private const string SQUIBFIREVALID_TAG = "SquibFireValid";
|
||||
private const string SQUIBOHMS_TAG = "SquibOhms";
|
||||
private const string SQUIBOUTPUTCURRENT_TAG = "SquibOutputCurrent";
|
||||
private const string SQUIBTOLERANCEHIGH_TAG = "SquibToleranceHigh";
|
||||
private const string SQUIBTOLERANCELOW_TAG = "SquibToleranceLow";
|
||||
private const string LIMITDURATION_TAG = "LimitDuration";
|
||||
private const string SCALEFACTORMV_TAG = "ScaleFactorMv";
|
||||
private const string PRETESTDATAZEROLEVELADC_TAG = "PreTestDataZeroLevelADC";
|
||||
private const string ARTICLEID_TAG = "ArticleId";
|
||||
private const string SUPPORTEDSQUIBFIREMODES_TAG = "SupportedSquibFireModes";
|
||||
private const string SOFTWAREFILTERHZ_TAG = "SoftwareFilterFrequency";
|
||||
private const string SENSOR_TAG = "Sensor";
|
||||
private const string SERIALNUMBER_TAG = "SerialNumber";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case BYPASSCURRENTFILTER_TAG:
|
||||
BypassCurrentFilter = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case BYPASSVOLTAGEFILTER_TAG:
|
||||
BypassVoltageFilter = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case DELAYMS_TAG:
|
||||
DelayMS = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case DURATIONMS_TAG:
|
||||
DurationMS = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case FIREMODE_TAG:
|
||||
String mode = XMLHelper.GetString(reader);
|
||||
try
|
||||
{
|
||||
FireMode = (SquibFireMode)Enum.Parse(typeof(SquibFireMode), mode);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load firemode ", mode, ex); }
|
||||
break;
|
||||
case ISOCODE_TAG:
|
||||
ISOCode = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case MEASUREMENTTYPE_TAG:
|
||||
string measurementType = XMLHelper.GetString(reader);
|
||||
try
|
||||
{
|
||||
MeasurementType = (SquibMeasurementType)Enum.Parse(typeof(SquibMeasurementType), measurementType);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to load MeasurementType ", measurementType, ex); }
|
||||
break;
|
||||
case SQUIBDESCRIPTION_TAG:
|
||||
SquibDescription = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case CHANNELID_TAG:
|
||||
ChannelId = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case SENSOR_TAG:
|
||||
Sensor = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case SERIALNUMBER_TAG:
|
||||
SerialNumber = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case CHANNELGROUPNAME_TAG:
|
||||
ChannelGroupName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case CHANNELNAME2_TAG:
|
||||
ChannelName2 = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case HARDWARECHANNELNAME_TAG:
|
||||
HardwareChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case SQUIBFIREPASSED_TAG:
|
||||
SquibFiredPassed = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case SQUIBFIREVALID_TAG:
|
||||
SquibFiredValid = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case SQUIBOHMS_TAG:
|
||||
SquibMeasuredOhms = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case SQUIBOUTPUTCURRENT_TAG:
|
||||
SquibOutputCurrent = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case SQUIBTOLERANCEHIGH_TAG:
|
||||
SquibToleranceHigh = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case SQUIBTOLERANCELOW_TAG:
|
||||
SquibToleranceLow = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case LIMITDURATION_TAG:
|
||||
LimitDuration = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case SCALEFACTORMV_TAG:
|
||||
ScaleFactorMv = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case PRETESTDATAZEROLEVELADC_TAG:
|
||||
PreTestDataZeroLevelADC = Convert.ToInt16(XMLHelper.GetInt(reader));
|
||||
break;
|
||||
case ARTICLEID_TAG:
|
||||
//2021-05-21 - why aren't we using this id? -DTM
|
||||
_ = XMLHelper.GetString(reader);
|
||||
IDs = new EID[] { new EID() };
|
||||
break;
|
||||
case SUPPORTEDSQUIBFIREMODES_TAG:
|
||||
string s = XMLHelper.GetString(reader);
|
||||
SupportedSquibFireModes = DeserializeSquibFireModes(s);
|
||||
break;
|
||||
case SOFTWAREFILTERHZ_TAG:
|
||||
var freq = XMLHelper.GetOptionalDouble(reader);
|
||||
if (null != freq) { SoftwareFilterFrequency = (double)freq; }
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return FireMode != SquibFireMode.NONE && !string.IsNullOrEmpty(SquibDescription);
|
||||
}
|
||||
|
||||
public const double DEFAULT_MIN_FIRE_DURATION_MS = 0.20; // FB 5439; don't allow user to set below min duration
|
||||
public const double DEFAULT_MIN_FIRE_DELAY_MS = 0.0D; // FB 5827 Saving squibs with invalid delay settings
|
||||
public const double DEFAULT_DEFINEINTEST_FIRE_DELAY_FLAG = -1; // FB 14623 A flag which specifies the Delay has to be defined in the test setup, also when updating please update the -1 check for SquibDelay in EditSquibControl
|
||||
public const double DEFAULT_MAX_FIRE_DURATION_MS = 25.5D; //stole it out of the UI in datapro
|
||||
public const double DEFAULT_MAX_FIRE_DELAY_MS = 99000D; //also stolen
|
||||
}
|
||||
}
|
||||
111
DataPRO/IService/Classes/Channels/OutputTOMDigitalChannel.cs
Normal file
111
DataPRO/IService/Classes/Channels/OutputTOMDigitalChannel.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for SQUIB channels.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class OutputTOMDigitalChannel : DigitalOutputDASChannel
|
||||
{
|
||||
public DigitalOutputModes OutputMode { get; set; } = DigitalOutputModes.NONE;
|
||||
|
||||
public double DelayMS { get; set; } = 0D;
|
||||
|
||||
public bool LimitDuration { get; set; } = false;
|
||||
|
||||
public double DurationMS { get; set; } = 0D;
|
||||
|
||||
public string DigitalChannelDescription { get; set; } = "";
|
||||
|
||||
public string LastModifiedBy { get; set; } = "";
|
||||
|
||||
public DateTime LastModified { get; set; }
|
||||
|
||||
public bool LocalOnly { get; set; } = false;
|
||||
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public OutputTOMDigitalChannel(XmlReader reader)
|
||||
{
|
||||
IDs = new[] { new EID() };
|
||||
ReadXml(reader);
|
||||
}
|
||||
|
||||
public OutputTOMDigitalChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public OutputTOMDigitalChannel()
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
XMLHelper.PutDouble(writer, "DelayMS", DelayMS);
|
||||
XMLHelper.PutString(writer, "ChannelDescription", DigitalChannelDescription);
|
||||
XMLHelper.PutDouble(writer, "DurationMS", DurationMS);
|
||||
XMLHelper.PutString(writer, "OutputMode", OutputMode.ToString());
|
||||
XMLHelper.PutBool(writer, "LimitDuration", LimitDuration);
|
||||
}
|
||||
public int Version { get; set; }
|
||||
|
||||
public DateTime Date { get; }
|
||||
|
||||
|
||||
public override void WriteXmlCRC32(XmlWriter writer)
|
||||
{
|
||||
base.WriteXmlCRC32(writer);
|
||||
|
||||
XMLHelper.PutDouble(writer, "DelayMS", DelayMS);
|
||||
XMLHelper.PutString(writer, "ChannelDescription", DigitalChannelDescription);
|
||||
XMLHelper.PutDouble(writer, "DurationMS", DurationMS);
|
||||
XMLHelper.PutString(writer, "OutputMode", OutputMode.ToString());
|
||||
XMLHelper.PutBool(writer, "LimitDuration", LimitDuration);
|
||||
}
|
||||
private const string OUTPUTMODE_TAG = "OutputMode";
|
||||
private const string CHANNELDESCRIPTION_TAG = "ChannelDescription";
|
||||
private const string DELAYMS_TAG = "DelayMS";
|
||||
private const string DURATIONMS_TAG = "DurationMS";
|
||||
private const string LIMITDURATION_TAG = "LimitDuration";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case OUTPUTMODE_TAG:
|
||||
OutputMode = (DigitalOutputModes)Enum.Parse(typeof(DigitalOutputModes), XMLHelper.GetString(reader));
|
||||
break;
|
||||
case CHANNELDESCRIPTION_TAG:
|
||||
DigitalChannelDescription = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case DELAYMS_TAG:
|
||||
DelayMS = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case DURATIONMS_TAG:
|
||||
DurationMS = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case LIMITDURATION_TAG:
|
||||
LimitDuration = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return OutputMode != DigitalOutputModes.NONE && !string.IsNullOrEmpty(DigitalChannelDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
87
DataPRO/IService/Classes/Channels/StreamInputDASChannel.cs
Normal file
87
DataPRO/IService/Classes/Channels/StreamInputDASChannel.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for storing/applying Streaming output settings as a channel
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StreamInputDASChannel : InputDASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public StreamInputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public StreamInputDASChannel()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Serial number of the sensor.
|
||||
/// </summary>
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the hardware channel
|
||||
/// </summary>
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public string UDPAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// If the channel has a serial number in the SerialNumber field, it is "Configured".
|
||||
/// </summary>
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return !string.IsNullOrEmpty(SerialNumber);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Stream{ModuleChannelNumber}";
|
||||
}
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
// SerialNumber
|
||||
XMLHelper.PutString(writer, "SerialNumber", SerialNumber);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutString(writer, "UDPAddress", UDPAddress.ToString());
|
||||
|
||||
}
|
||||
private const string SERIALNUMBER_TAG = "SerialNumber";
|
||||
private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName";
|
||||
private const string UDPADDRESS_TAG = "UDPAddress";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
var value = string.Empty;
|
||||
switch (reader.Name)
|
||||
{
|
||||
case SERIALNUMBER_TAG:
|
||||
SerialNumber = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case HARDWARECHANNELNAME_TAG:
|
||||
HardwareChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case UDPADDRESS_TAG:
|
||||
UDPAddress = XMLHelper.GetString(reader);
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
130
DataPRO/IService/Classes/Channels/StreamOutputDASChannel.cs
Normal file
130
DataPRO/IService/Classes/Channels/StreamOutputDASChannel.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using DTS.Common.Enums;
|
||||
using System.Text;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Classes.Sensors;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for storing/applying Streaming output settings as a channel
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StreamOutputDASChannel : OutputDASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public StreamOutputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public StreamOutputDASChannel()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Serial number of the sensor.
|
||||
/// </summary>
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the hardware channel
|
||||
/// </summary>
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public string UDPProfileName { get; set; } = UDPStreamProfile.CH10_ANALOG_2HDR.ToString();
|
||||
public ushort UDPTimeChannelId { get; set; }
|
||||
public ushort UDPDataChannelId { get; set; }
|
||||
public ushort IRIGTimeDataPacketIntervalMs { get; set; }
|
||||
/// <summary>
|
||||
/// time between sending TMATS information while streaming
|
||||
/// http://manuscript.dts.local/f/cases/29987/Add-CG-DP-TMATS-interval-UI-support
|
||||
/// </summary>
|
||||
public ushort TMATSIntervalMs { get; set; } = StreamOutputRecord.DEFAULT_TMATS_INTERVAL_MS;
|
||||
public string UDPAddress { get; set; } = string.Empty;
|
||||
public uint[] UDPTmNSConfig { get; set; } = new uint[8];
|
||||
|
||||
/// <summary>
|
||||
/// If the channel has a serial number in the SerialNumber field, it is "Configured".
|
||||
/// </summary>
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return !string.IsNullOrEmpty(SerialNumber);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Stream{ModuleChannelNumber}";
|
||||
}
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
// SerialNumber
|
||||
XMLHelper.PutString(writer, "SerialNumber", SerialNumber);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutString(writer, "UDPProfileName", UDPProfileName);
|
||||
XMLHelper.PutString(writer, "UDPTimeChannelId", UDPTimeChannelId.ToString());
|
||||
XMLHelper.PutString(writer, "UDPDataChannelId", UDPDataChannelId.ToString());
|
||||
XMLHelper.PutString(writer, "IRIGTimeDataPacketIntervalMs", IRIGTimeDataPacketIntervalMs.ToString());
|
||||
XMLHelper.PutString(writer, TMATS_INTERVAL_MS_TAG, TMATSIntervalMs.ToString());
|
||||
XMLHelper.PutString(writer, "UDPAddress", UDPAddress.ToString());
|
||||
XMLHelper.PutString(writer, "UDPTmNSConfig", ArrayToString.ArrayObjectToString(UDPTmNSConfig));
|
||||
}
|
||||
private const string SERIALNUMBER_TAG = "SerialNumber";
|
||||
private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName";
|
||||
private const string UDPPROFILENAME_TAG = "UDPProfileName";
|
||||
private const string UDPTIMECHANNELID_TAG = "UDPTimeChannelId";
|
||||
private const string UDPDATACHANNELID_TAG = "UDPDataChannelId";
|
||||
private const string IRIGTIMEDATAPACKETINTERVALMS_TAG = "IRIGTimeDataPacketIntervalMs";
|
||||
private const string UDPADDRESS_TAG = "UDPAddress";
|
||||
private const string UDPTMNSCONFIG_TAG = "UDPTmNSConfig";
|
||||
private const string TMATS_INTERVAL_MS_TAG = "TMATSIntervalMs";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
var value = string.Empty;
|
||||
switch (reader.Name)
|
||||
{
|
||||
case SERIALNUMBER_TAG:
|
||||
SerialNumber = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case HARDWARECHANNELNAME_TAG:
|
||||
HardwareChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case UDPPROFILENAME_TAG:
|
||||
UDPProfileName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case UDPTIMECHANNELID_TAG:
|
||||
UDPTimeChannelId = Convert.ToUInt16(XMLHelper.GetInt(reader));
|
||||
break;
|
||||
case UDPDATACHANNELID_TAG:
|
||||
UDPDataChannelId = Convert.ToUInt16(XMLHelper.GetInt(reader));
|
||||
break;
|
||||
case IRIGTIMEDATAPACKETINTERVALMS_TAG:
|
||||
IRIGTimeDataPacketIntervalMs = Convert.ToUInt16(XMLHelper.GetInt(reader));
|
||||
break;
|
||||
case UDPADDRESS_TAG:
|
||||
UDPAddress = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case UDPTMNSCONFIG_TAG:
|
||||
UDPTmNSConfig = ArrayToString.StringToUIntArray(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case TMATS_INTERVAL_MS_TAG:
|
||||
TMATSIntervalMs = Convert.ToUInt16(XMLHelper.GetInt(reader));
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
DataPRO/IService/Classes/Channels/TimestampDASChannel.cs
Normal file
73
DataPRO/IService/Classes/Channels/TimestampDASChannel.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for channels encoding sample timestamps
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TimestampDASChannel : InputDASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public TimestampDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public TimestampDASChannel()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the rtc channel exists, it is "Configured".
|
||||
/// </summary>
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public const string MARKER = "MARKER";
|
||||
public const string SEC_H = "SECONDS_HIGH";
|
||||
public const string SEC_L = "SECONDS_LOW";
|
||||
public const string NANOS_H = "NANOSECONDS_HIGH";
|
||||
public const string NANOS_L = "NANOSECONDS_LOW";
|
||||
public const string RSVD = "RESERVED";
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
switch (OwningModule.ModuleType())
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.EmbeddedClockSecondsAndMarker:
|
||||
switch (ModuleChannelNumber)
|
||||
{
|
||||
case 0:
|
||||
return MARKER;
|
||||
case 1:
|
||||
return SEC_H;
|
||||
case 2:
|
||||
return SEC_L;
|
||||
}
|
||||
break;
|
||||
case DFConstantsAndEnums.ModuleType.EmbeddedClockNanosAndPad:
|
||||
switch (ModuleChannelNumber)
|
||||
{
|
||||
case 0:
|
||||
return NANOS_H;
|
||||
case 1:
|
||||
return NANOS_L;
|
||||
case 2:
|
||||
return RSVD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ModuleChannelNumber.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
144
DataPRO/IService/Classes/Channels/UARTInputDASChannel.cs
Normal file
144
DataPRO/IService/Classes/Channels/UARTInputDASChannel.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using System.Xml;
|
||||
using System.IO.Ports;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for storing/applying UART settings as a channel
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class UARTInputDASChannel : InputDASChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR to populate a channel's owning module and channel WRT that module. Calls
|
||||
/// base class CTOR.
|
||||
/// </summary>
|
||||
/// <param name="owner">Module that contains this channel.</param>
|
||||
/// <param name="channelNumber">ChannelNumber of this channel WRT owning module.</param>
|
||||
public UARTInputDASChannel(DASModule owner, int channelNumber)
|
||||
: base(owner, channelNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public UARTInputDASChannel()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Serial number of the sensor.
|
||||
/// </summary>
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the hardware channel
|
||||
/// </summary>
|
||||
public string HardwareChannelName { get; set; }
|
||||
|
||||
public uint BaudRate { get; set; }
|
||||
|
||||
public uint DataBits { get; set; }
|
||||
|
||||
public StopBits StopBits { get; set; }
|
||||
|
||||
public Parity Parity { get; set; }
|
||||
|
||||
public Handshake FlowControl { get; set; }
|
||||
|
||||
public UartDataFormat DataFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the channel has a serial number in the SerialNumber field, it is "Configured".
|
||||
/// </summary>
|
||||
public override bool IsConfigured()
|
||||
{
|
||||
return !string.IsNullOrEmpty(SerialNumber);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"UART{ModuleChannelNumber}";
|
||||
}
|
||||
public override void WriteXml(XmlWriter writer)
|
||||
{
|
||||
base.WriteXml(writer);
|
||||
|
||||
// SerialNumber
|
||||
XMLHelper.PutString(writer, "SerialNumber", SerialNumber);
|
||||
XMLHelper.PutString(writer, "HardwareChannelName", HardwareChannelName);
|
||||
XMLHelper.PutString(writer, "BaudRate", BaudRate.ToString());
|
||||
XMLHelper.PutString(writer, "DataBits", DataBits.ToString());
|
||||
XMLHelper.PutString(writer, "StopBits", StopBits.ToString());
|
||||
XMLHelper.PutString(writer, "Parity", Parity.ToString());
|
||||
XMLHelper.PutString(writer, "FlowControl", FlowControl.ToString());
|
||||
XMLHelper.PutString(writer, "DataFormat", DataFormat.ToString());
|
||||
|
||||
}
|
||||
private const string SERIALNUMBER_TAG = "SerialNumber";
|
||||
private const string HARDWARECHANNELNAME_TAG = "HardwareChannelName";
|
||||
private const string BAUDRATE_TAG = "BaudRate";
|
||||
private const string DATABITS_TAG = "DataBits";
|
||||
private const string STOPBITS_TAG = "StopBits";
|
||||
private const string PARITY_TAG = "Parity";
|
||||
private const string FLOWCONTROL_TAG = "FlowControl";
|
||||
private const string DATAFORMAT_TAG = "DataFormat";
|
||||
protected override void HandleElement(XmlReader reader)
|
||||
{
|
||||
base.HandleElement(reader);
|
||||
if (reader.NodeType == XmlNodeType.Element)
|
||||
{
|
||||
var value = string.Empty;
|
||||
switch (reader.Name)
|
||||
{
|
||||
case SERIALNUMBER_TAG:
|
||||
SerialNumber = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case HARDWARECHANNELNAME_TAG:
|
||||
HardwareChannelName = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case BAUDRATE_TAG:
|
||||
BaudRate = Convert.ToUInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case DATABITS_TAG:
|
||||
DataBits = Convert.ToUInt32(XMLHelper.GetString(reader));
|
||||
break;
|
||||
case STOPBITS_TAG:
|
||||
try
|
||||
{
|
||||
StopBits = (StopBits)Enum.Parse(typeof(StopBits), XMLHelper.GetString(reader));
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
case PARITY_TAG:
|
||||
try
|
||||
{
|
||||
Parity = (Parity)Enum.Parse(typeof(Parity), XMLHelper.GetString(reader));
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
case FLOWCONTROL_TAG:
|
||||
try
|
||||
{
|
||||
FlowControl = (Handshake)Enum.Parse(typeof(Handshake), XMLHelper.GetString(reader));
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
case DATAFORMAT_TAG:
|
||||
try
|
||||
{
|
||||
DataFormat = (UartDataFormat)Enum.Parse(typeof(UartDataFormat), XMLHelper.GetString(reader));
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
DataPRO/IService/Classes/ConfigurationConstants.cs
Normal file
12
DataPRO/IService/Classes/ConfigurationConstants.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public abstract class ConfigurationConstants
|
||||
{
|
||||
public enum VerifyConfig_Errors
|
||||
{
|
||||
DefaultHardwareFilterRateOutOfRange
|
||||
}
|
||||
}
|
||||
}
|
||||
437
DataPRO/IService/Classes/ConfigurationData.cs
Normal file
437
DataPRO/IService/Classes/ConfigurationData.cs
Normal file
@@ -0,0 +1,437 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DASFactoryDb.Config;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Each IDASCommunication will have an instance of this class. It provides information
|
||||
/// about the configuration of the DAS as a whole with regards to the current test/event.
|
||||
/// The ConfigData object in an IDASCommunication will contain arrays representing the
|
||||
/// specific modules and channels therein, of which the configurations may be set and
|
||||
/// retrieved through the ConfigurationData object.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[XmlInclude(typeof(DASChannel))]
|
||||
[XmlInclude(typeof(InputDASChannel))]
|
||||
[XmlInclude(typeof(AnalogInputDASChannel))]
|
||||
//[XmlInclude(typeof(DigitalInputDASChannel))]
|
||||
[XmlInclude(typeof(OutputDASChannel))]
|
||||
[XmlInclude(typeof(AnalogOutputDASChannel))]
|
||||
[XmlInclude(typeof(DigitalOutputDASChannel))]
|
||||
public class ConfigurationData : IConfigurationData, IXmlSerializable
|
||||
{
|
||||
/// <summary>
|
||||
/// Array of Module objects in the DAS.
|
||||
/// </summary>
|
||||
public IDASModule[] Modules { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EID's for the whole DAS.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public IEID[] IDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the current test/event.
|
||||
/// </summary>
|
||||
public string TestID { get; set; }
|
||||
public string TestSetupUniqueId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of an instance of a test run, for the purpose
|
||||
/// of identifying where to download data.
|
||||
/// </summary>
|
||||
public string InstanceID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A description of the current test/event.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
[XmlIgnore()]
|
||||
public bool ClearSetup { get; set; } = false;
|
||||
/// <summary>
|
||||
/// Counts how many channels are configured. If a channel's
|
||||
/// 'IsConfigured' property is 'true' it is configured.
|
||||
/// </summary>
|
||||
/// <returns>Number of configured channels</returns>
|
||||
public int NumberOfConfiguredChannels()
|
||||
{
|
||||
if (Modules == null || Modules.Length == 0)
|
||||
return 0;
|
||||
return Modules.Sum(module => module.NumberOfConfiguredChannels());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Count how many channels we have (regardless if they are configured or not).
|
||||
/// </summary>
|
||||
/// <returns>Total number of channels</returns>
|
||||
public int NumberOfChannels()
|
||||
{
|
||||
if (Modules == null || Modules.Length == 0)
|
||||
return 0;
|
||||
return Modules.Sum(module => module.NumberOfChannels());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Count how many downloadable channels (i.e. not UART, StreamOut, etc.) we have (regardless if they are configured or not).
|
||||
/// </summary>
|
||||
/// <returns>Total number of downloadable channels</returns>
|
||||
public int NumberOfDownloadChannels()
|
||||
{
|
||||
if (Modules == null || Modules.Length == 0)
|
||||
return 0;
|
||||
return Modules.Where(module => !module.IsStreamOut() && !module.IsUart()).Sum(module => module.NumberOfChannels());
|
||||
}
|
||||
public ConfigurationData()
|
||||
{
|
||||
Modules = null;
|
||||
IDs = null;
|
||||
TestID = "";
|
||||
TestSetupUniqueId = null;
|
||||
Description = "Default Test ID";
|
||||
InstanceID = null;
|
||||
}
|
||||
public int[] DisplayOrder { get; set; } = new int[] { -1 };
|
||||
public int DasDisplayOrder { get; set; } = -1;
|
||||
|
||||
public int GetDisplayOrder(uint channelIdx)
|
||||
{
|
||||
if (channelIdx >= DisplayOrder.Length) { return -1; }
|
||||
else { return DisplayOrder[channelIdx]; }
|
||||
}
|
||||
|
||||
#region Serialization functions
|
||||
|
||||
/// <summary>
|
||||
/// Serialize configuration data to a file
|
||||
/// </summary>
|
||||
/// <param name="file">File name to write to</param>
|
||||
/// <param name="config">The configuration to serialize</param>
|
||||
public static void Serialize(string file, ConfigurationData config)
|
||||
{
|
||||
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(config.GetType());
|
||||
|
||||
StreamWriter writer = File.CreateText(file);
|
||||
|
||||
xs.Serialize(writer, config);
|
||||
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize configuration data to a string
|
||||
/// </summary>
|
||||
/// <param name="config">The configuration to serialize</param>
|
||||
/// <returns>The serialized data in XML form</returns>
|
||||
public static string Serialize(ConfigurationData config)
|
||||
{
|
||||
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(config.GetType());
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
System.Xml.XmlWriterSettings xmlsettings = new System.Xml.XmlWriterSettings();
|
||||
xmlsettings.NewLineChars = "";
|
||||
System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(writer, xmlsettings);
|
||||
|
||||
try
|
||||
{
|
||||
xs.Serialize(xmlwriter, config);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex); // Maybe useful for forensics?
|
||||
APILogger.Log($"Current writer buffer:{writer.ToString()}");
|
||||
|
||||
// http://manuscript.dts.local/f/cases/26802/Fail-on-serialization-error-for-XML-config-data
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
throw;
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
writer.Close();
|
||||
var xmlStr = writer.ToString();
|
||||
return xmlStr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize configuration data to a binary block
|
||||
/// </summary>
|
||||
/// <param name="config">The configuration to serialize</param>
|
||||
/// <returns>The serialized data in binary form</returns>
|
||||
public static byte[] SerializeBin(ConfigurationData config)
|
||||
{
|
||||
BinaryFormatter bf = new BinaryFormatter();
|
||||
byte[] bytes;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
bf.Serialize(ms, config);
|
||||
ms.Seek(0, 0);
|
||||
bytes = ms.ToArray();
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize an XML string into a new configuration object
|
||||
/// </summary>
|
||||
/// <param name="SerializedText">The XML data</param>
|
||||
/// <returns>A new configuration object</returns>
|
||||
public static ConfigurationData DeserializeFromString(string SerializedText)
|
||||
{
|
||||
if (string.IsNullOrEmpty(SerializedText)) { return null; }
|
||||
|
||||
XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(ConfigurationData));
|
||||
|
||||
StringReader reader = new StringReader(SerializedText);
|
||||
try
|
||||
{
|
||||
ConfigurationData config = (ConfigurationData)xs.Deserialize(reader);
|
||||
return config;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Failed to read config", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize from an XML file to a configuration object
|
||||
/// </summary>
|
||||
/// <param name="file">The file name to read from</param>
|
||||
/// <returns>A new configuration object</returns>
|
||||
public static ConfigurationData Deserialize(string file)
|
||||
{
|
||||
var xs = new XmlSerializer(typeof(ConfigurationData));
|
||||
|
||||
if (File.Exists(file))
|
||||
{
|
||||
APILogger.Log("reading 67 ", file);
|
||||
using (StreamReader reader = File.OpenText(file))
|
||||
{
|
||||
var c = (ConfigurationData)xs.Deserialize(reader);
|
||||
reader.Close();
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ConfigurationData();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void WriteXml(XmlWriter writer)
|
||||
{
|
||||
//writer.WriteStartElement("ConfigurationData");
|
||||
// <ConfigurationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
|
||||
writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
|
||||
|
||||
|
||||
// Modules
|
||||
writer.WriteStartElement("Modules");
|
||||
if (Modules != null)
|
||||
{
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
module.WriteXml(writer);
|
||||
}
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
|
||||
// TestID
|
||||
XMLHelper.PutString(writer, "TestID", TestID);
|
||||
|
||||
// Description
|
||||
XMLHelper.PutString(writer, "Description", Description);
|
||||
|
||||
// TestSetupUniqueId
|
||||
XMLHelper.PutString(writer, "TestSetupUniqueId", TestSetupUniqueId);
|
||||
|
||||
// InstanceID
|
||||
XMLHelper.PutString(writer, "InstanceID", InstanceID);
|
||||
|
||||
XMLHelper.PutString(writer, "UDPReceiveAddress", UDPReceiveAddress);
|
||||
//writer.WriteEndElement();
|
||||
}
|
||||
|
||||
private void DumpXml(XmlReader reader)
|
||||
{
|
||||
using (var writer = new StreamWriter("xmldump.txt"))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
string n, t, v;
|
||||
try
|
||||
{
|
||||
n = reader.Name;
|
||||
if (string.IsNullOrEmpty(n))
|
||||
{
|
||||
n = "<null>";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
n = "<no-name>";
|
||||
}
|
||||
try
|
||||
{
|
||||
t = reader.NodeType.ToString();
|
||||
if (string.IsNullOrEmpty(t))
|
||||
{
|
||||
t = "<null>";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
t = "<no-type>";
|
||||
}
|
||||
try
|
||||
{
|
||||
v = reader.Value;
|
||||
if (string.IsNullOrEmpty(v))
|
||||
{
|
||||
v = "<null>";
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
v = "<no-value>";
|
||||
}
|
||||
writer.WriteLine("Name: " + n + " Type: " + t + " Value: " + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
private const string CONFIG_START_TAG = "ConfigurationData";
|
||||
private const string MODULES_START_TAG = "Modules";
|
||||
private const string DASMODULE_START_TAG = "DASModule";
|
||||
private const string TESTID_START_TAG = "TestID";
|
||||
private const string DESCRIPTION_START_TAG = "Description";
|
||||
|
||||
private List<string> KNOWN_STARTING_TAGS = new List<string>(new[] { CONFIG_START_TAG, MODULES_START_TAG, DASMODULE_START_TAG, TESTID_START_TAG, DESCRIPTION_START_TAG });
|
||||
|
||||
private void ReadModules(XmlReader reader)
|
||||
{
|
||||
var myModules = new List<DASModule>();
|
||||
var keepGoing = reader.ReadToFollowing(DASMODULE_START_TAG);
|
||||
while (keepGoing)
|
||||
{
|
||||
var deserializedModule = new DASModule();
|
||||
deserializedModule.ReadXml(reader);
|
||||
myModules.Add(deserializedModule);
|
||||
|
||||
if (reader.Name == MODULES_START_TAG && reader.NodeType == XmlNodeType.EndElement)
|
||||
{
|
||||
keepGoing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
keepGoing = reader.Name == DASMODULE_START_TAG && reader.NodeType == XmlNodeType.Element || reader.ReadToFollowing(DASMODULE_START_TAG);
|
||||
}
|
||||
}
|
||||
Modules = myModules.ToArray();
|
||||
}
|
||||
public virtual void ReadXml(XmlReader reader)
|
||||
{
|
||||
// it must be an Element
|
||||
if (reader.NodeType != XmlNodeType.Element)
|
||||
{
|
||||
throw new XmlException("ConfigurationData.ReadXml: Unknown input: " + reader.NodeType.ToString());
|
||||
}
|
||||
|
||||
// remove our start tag
|
||||
if (reader.Name == CONFIG_START_TAG)
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (reader.Name != CONFIG_START_TAG)
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
// try to find our data
|
||||
do
|
||||
{
|
||||
if (reader.NodeType != XmlNodeType.Element) { continue; }
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "Modules": // DASModule[]
|
||||
ReadModules(reader);
|
||||
break;
|
||||
case "TestID":
|
||||
TestID = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case "Description":
|
||||
Description = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case "TestSetupUniqueId":
|
||||
TestSetupUniqueId = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case "InstanceID":
|
||||
InstanceID = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case "UDPReceiveAddress":
|
||||
UDPReceiveAddress = XMLHelper.GetString(reader);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
//throw new XmlException("ConfigurationData.ReadXml: Unknown tag: " + reader.Name);
|
||||
//return;
|
||||
}
|
||||
} while (reader.Read());
|
||||
|
||||
// we're going to end with an EndElement, so clean up
|
||||
if (reader.NodeType == XmlNodeType.EndElement)
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public const int DIAGNOSTIC_FILESTORE = 0;
|
||||
public const int EVENT_FILE_STORE = 1;
|
||||
/// <summary>
|
||||
/// writes the current configuration to the db if available
|
||||
/// </summary>
|
||||
public static void SetConfiguration(IDASCommunication das, string xml, int fileStore)
|
||||
{
|
||||
if (!DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
try
|
||||
{
|
||||
Config.SetConfiguration(das.RecordId, xml, fileStore);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
public string UDPReceiveAddress { get; set; } = "UDP://239.1.2.10:8401";
|
||||
}
|
||||
}
|
||||
814
DataPRO/IService/Classes/DASModule.cs
Normal file
814
DataPRO/IService/Classes/DASModule.cs
Normal file
@@ -0,0 +1,814 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utils;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This represents one Module on a DAS unit. A DAS unit can have numerous Modules and a Module can have
|
||||
/// numerous channels. The channels that are connected to this module are in the <see cref="DASModule.Channels" />
|
||||
/// array property. See <see cref="DASChannel" />. Another property, <see cref="DASModule.ModuleArrayIndex" />
|
||||
/// is the index of this object in any array of Modules in the corresponding <see cref="IDASCommunication" />
|
||||
/// however it may also be addressed by it's Device ID. The first module in a DAS will have a ModuleArrayIndex
|
||||
/// of 0 but a DeviceID of 1. See <see cref="DTS.DASLib.Service.InfoResult" />.MapDASChannelNumber2ModuleDeviceID and
|
||||
/// <see cref="DTS.DASLib.Service.InfoResult" />.MapModuleDeviceIDAndChannelNum2DASChannel
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class DASModule : IDASModule, IXmlSerializable
|
||||
{
|
||||
/// <summary>
|
||||
/// An array of <see cref="DASChannel" /> objects representing the channels attatched to this
|
||||
/// module, indexable by ModuleChannelNumber of the Channel.
|
||||
/// </summary>
|
||||
public IDASChannel[] Channels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// EID's for the module corresponding to the sensors on each of the channels.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public IEID[] IDs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Index of this Module in any array of Modules. The first module in a DAS unit will have a
|
||||
/// ModuleArrayIndex of 0.
|
||||
/// </summary>
|
||||
public int ModuleArrayIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For use only with Circular-Buffer mode.
|
||||
/// See <see cref="DASModule.RecordingMode" />.
|
||||
/// The number of requested seconds for this Module to sample data before a 'Trigger' event; the number of
|
||||
/// seconds to sample BEFORE time-zero.
|
||||
/// </summary>
|
||||
public double RequestedPreTriggerSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For use with all recording modes.
|
||||
/// See <see cref="DASModule.RecordingMode" />.
|
||||
/// The number of requested seconds to sample data from sensors after time-zero, that is after
|
||||
/// a trigger or start event.
|
||||
/// </summary>
|
||||
public double RequestedPostTriggerSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For use only with Circular-Buffer mode.
|
||||
/// See <see cref="DASModule.RecordingMode" />.
|
||||
/// The number of seconds for this Module to sample data before a 'Trigger' event; the number of
|
||||
/// seconds to sampel BEFORE time-zero.
|
||||
/// </summary>
|
||||
public double PreTriggerSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For use with all recording modes.
|
||||
/// See <see cref="DASModule.RecordingMode" />.
|
||||
/// The number of seconds to sample data from sensors after time-zero, that is after
|
||||
/// a trigger or start event.
|
||||
/// </summary>
|
||||
public double PostTriggerSeconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of events to collect before disarming.
|
||||
/// </summary>
|
||||
public int NumberOfEvents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of seconds of inactivity before going back to sleep.
|
||||
/// </summary>
|
||||
public int WakeUpMotionTimeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The version of the firmware on a module.
|
||||
/// </summary>
|
||||
public string FirmwareVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A string that describes the module, for example, to know if it was created for the
|
||||
/// purposes of adding it to the .dts file during download of Slice6 Distributor attributes.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum storage space for a module.
|
||||
/// </summary>
|
||||
public UInt64? MaxEventStorageSpaceInBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is set after a recording session and is the total number of samples this Module
|
||||
/// captured during the last data acquisition run.
|
||||
/// </summary>
|
||||
public UInt64 NumberOfSamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of sample numbers where a trigger was activated.
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public UInt64[] TriggerSampleNumbers { get; set; }
|
||||
|
||||
public int GetLevelTriggerT0AdjustmentSamplesAutoApplied()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
//temporary hack/workaround to correct leveltriggert0adjustmentsamples
|
||||
if (OwningDAS is IDASReconfigure)
|
||||
{
|
||||
//we do qualifications +1 at request of Loc/Tim, see them for details
|
||||
var channelsWithAdjustments = Channels.Where(c => c.LevelTriggerSeen);
|
||||
return channelsWithAdjustments.Count() > 0 ? channelsWithAdjustments.First().QualificationSamples : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Figure out what the number of samples that would have been auto-applied to
|
||||
// this module is.
|
||||
//
|
||||
var channelsWithAdjustments = Channels.Where(c => null != c.LevelTriggerT0AdjustmentSamples);
|
||||
var channelsWithMaxAdjustment = channelsWithAdjustments.Max(c => c.LevelTriggerT0AdjustmentSamples);
|
||||
return channelsWithAdjustments.Count() > 0 ? (int)(channelsWithAdjustments.First().LevelTriggerT0AdjustmentSamples) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new ApplicationException(
|
||||
"encountered problem getting number of level trigger T0 adjustment samples already applied to module "
|
||||
+ (null != OwningDAS && null != OwningDAS.SerialNumber ? "\"" + OwningDAS.SerialNumber + "\"" : "<NULL>")
|
||||
+ ", module "
|
||||
+ ModuleArrayIndex.ToString(),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The sample number where recording started.
|
||||
/// </summary>
|
||||
public ulong StartRecordSampleNumber { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public uint StartRecordTimestampSec { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public uint TriggerTimestampSec { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public uint StartRecordTimestampNanoSec { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public uint TriggerTimestampNanoSec { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool PTPMasterSync { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisXDegreesPre { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisYDegreesPre { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisZDegreesPre { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisXDegreesPost { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisYDegreesPost { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TiltSensorAxisZDegreesPost { get; set; }
|
||||
public float TemperatureLocation1Pre { get; set; } = float.NaN;
|
||||
|
||||
public float TemperatureLocation2Pre { get; set; } = float.NaN;
|
||||
public float TemperatureLocation3Pre { get; set; } = float.NaN;
|
||||
public float TemperatureLocation4Pre { get; set; } = float.NaN;
|
||||
public float TemperatureLocation1Post { get; set; } = float.NaN;
|
||||
public float TemperatureLocation2Post { get; set; } = float.NaN;
|
||||
public float TemperatureLocation3Post { get; set; } = float.NaN;
|
||||
public float TemperatureLocation4Post { get; set; } = float.NaN;
|
||||
|
||||
/// <summary>
|
||||
/// The sample rate in Hz at which the Module will sample sensor data.
|
||||
/// </summary>
|
||||
public uint SampleRateHz { get; set; }
|
||||
|
||||
//FB 25558
|
||||
/// <summary>
|
||||
/// The actual sample rate in Hz currently used in realtime for TSR AIR
|
||||
/// </summary>
|
||||
public uint ActualSampleRateHz { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The sample rate in Hz at which any Embedded Modules will sample sensor data.
|
||||
/// </summary>
|
||||
public uint[] EmbeddedSampleRateHz { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// xml string tag for AAFilterRateHz
|
||||
/// </summary>
|
||||
public const string AAFilterRateHzTag = "AAFilterRateHz";
|
||||
/// <summary>
|
||||
/// Hardware anti-alias filter rate.
|
||||
/// </summary>
|
||||
public float AAFilterRateHz { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What type of recording mode is this Module in?
|
||||
/// See <see cref="Test.Module.RecordingMode.RecorderMode" />.
|
||||
/// </summary>
|
||||
public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; }
|
||||
public DateTime ScheduledStartTime { get; set; }
|
||||
public int RecordingInterval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FB15388: The UDP streaming profile set (for supporting DAS).
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public UDPStreamProfile StreamProfile { get; set; }
|
||||
|
||||
#region Slice 6 Tilt Feature
|
||||
|
||||
/// <summary>
|
||||
/// Defines which 2 axis will be used for the bubble level feature for Slice 6.
|
||||
/// </summary>
|
||||
public DFConstantsAndEnums.TiltAxes TiltAxes { get; set; }
|
||||
|
||||
public double TargetAxisOne { get; set; }
|
||||
|
||||
public double TargetAxisTwo { get; set; }
|
||||
|
||||
public float TargetAngleAxisX { get; set; }
|
||||
public float TargetAngleAxisY { get; set; }
|
||||
public float TargetAngleAxisZ { get; set; }
|
||||
|
||||
public double MountOffsetAxisOne { get; set; }
|
||||
|
||||
public double MountOffsetAxisTwo { get; set; }
|
||||
|
||||
public string SystemLocation { get; set; }
|
||||
|
||||
public string SystemID { get; set; }
|
||||
|
||||
public int AxisIgnored { get; set; }
|
||||
|
||||
public byte TiltID { get; set; }
|
||||
|
||||
public string TiltSerialNumber { get; set; }
|
||||
|
||||
public double LevelTolerance { get; set; }
|
||||
|
||||
public bool UseForTiltCalculation { get; set; }
|
||||
public double InputVoltage { get; set; }
|
||||
public double BatteryVoltage { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
[XmlIgnore]
|
||||
public IDASCommunication OwningDAS { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Count how many channels are configured in this Module.
|
||||
/// See <see cref="AnalogInputDASChannel.IsConfigured" />.
|
||||
/// </summary>
|
||||
/// <returns>Number of configured channels</returns>
|
||||
public int NumberOfConfiguredChannels()
|
||||
{
|
||||
if (Channels == null || Channels.Length == 0)
|
||||
return 0;
|
||||
var configuredChannels = from ch in Channels.AsParallel() where ch.IsConfigured() select ch;
|
||||
if (configuredChannels.Count() > 0)
|
||||
{
|
||||
var channels = configuredChannels.ToArray();
|
||||
}
|
||||
return configuredChannels.Count();
|
||||
}
|
||||
/// <summary>
|
||||
/// Count how many TOM channels are configured in this module
|
||||
/// </summary>
|
||||
/// <returns>Number of configured TOM channels</returns>
|
||||
public int NumberOfConfiguredTOMChannels()
|
||||
{
|
||||
if (Channels == null || Channels.Length == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
var configuredTOMChannels = from ch in Channels.AsParallel() where (ch.IsConfigured() && ch is OutputSquibChannel) select ch;
|
||||
return configuredTOMChannels.Count();
|
||||
}
|
||||
public bool IsDummyArmed()
|
||||
{
|
||||
int numConfiguredChannels = NumberOfConfiguredChannels();
|
||||
return numConfiguredChannels < 1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Count how many channels this module has (regardless if they are configured
|
||||
/// or not).
|
||||
/// </summary>
|
||||
/// <returns>Total number of channels</returns>
|
||||
public int NumberOfChannels()
|
||||
{
|
||||
if (Channels == null || Channels.Length == 0)
|
||||
return 0;
|
||||
return Channels.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the serial number from DASInfo
|
||||
/// </summary>
|
||||
/// <returns>The serial number of this module</returns>
|
||||
public string SerialNumber()
|
||||
{
|
||||
if (OwningDAS == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get serialnumber but OwningDAS is null");
|
||||
}
|
||||
if (OwningDAS.DASInfo == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get serialnumber but OwningDAS.DASInfo is null");
|
||||
}
|
||||
if (OwningDAS.DASInfo.Modules == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get serialnumber but OwningDAS.DASInfo.Modules is null");
|
||||
}
|
||||
|
||||
for (int i = 0; i < OwningDAS.DASInfo.Modules.Length; i++)
|
||||
{
|
||||
if (OwningDAS.DASInfo.Modules[i]?.ModuleArrayIndex == ModuleArrayIndex)
|
||||
{
|
||||
var sn = OwningDAS.DASInfo.Modules[i].SerialNumber;
|
||||
if (string.IsNullOrEmpty(sn))
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get serialnumber but it's null or empty");
|
||||
}
|
||||
else { return sn; }
|
||||
}
|
||||
}
|
||||
throw new NullReferenceException("DASModule: Trying to get serialnumber but ModuleArrayIndex is invalid");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo
|
||||
/// </summary>
|
||||
/// <returns>The type of this module</returns>
|
||||
public DFConstantsAndEnums.ModuleType ModuleType()
|
||||
{
|
||||
if (OwningDAS == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get module type but OwningDAS is null");
|
||||
}
|
||||
if (OwningDAS.DASInfo == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get module type but OwningDAS.DASInfo is null");
|
||||
}
|
||||
if (OwningDAS.DASInfo.Modules == null)
|
||||
{
|
||||
throw new NullReferenceException("DASModule: Trying to get module type but OwningDAS.DASInfo.Modules is null");
|
||||
}
|
||||
|
||||
foreach (InfoResult.Module module in OwningDAS.DASInfo.Modules)
|
||||
{
|
||||
if (module.ModuleArrayIndex != ModuleArrayIndex) continue;
|
||||
var dasType = module.TypeOfModule;
|
||||
return dasType;
|
||||
}
|
||||
throw new NullReferenceException("DASModule: Trying to get module type but ModuleArrayIndex is invalid");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo and return whether or not it's a clock type
|
||||
/// </summary>
|
||||
/// <returns>Whether the type of this module is a clock</returns>
|
||||
public bool IsClock()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.EmbeddedClockNanosAndPad ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedClockSecondsAndMarker;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo and return whether or not it's a uart type
|
||||
/// </summary>
|
||||
/// <returns>Whether the type of this module is a uart</returns>
|
||||
public bool IsUart()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.UART;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo and return whether or not it's a stream output type
|
||||
/// </summary>
|
||||
/// <returns>Whether the type of this module is a stream output</returns>
|
||||
public bool IsStreamOut()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.StreamOut;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo and return whether or not it's a stream input type
|
||||
/// </summary>
|
||||
/// <returns>Whether the type of this module is a stream output</returns>
|
||||
public bool IsStreamIn()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.StreamIn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the module type from DASInfo and return whether or not it's an embedded type
|
||||
/// </summary>
|
||||
/// <returns>Whether the type of this module is embedded</returns>
|
||||
public bool IsEmbedded()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.EmbeddedLinearAccelLowG ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedLinearAccelHighG ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedAngularRate ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedAngularAccel ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedAtmospheric ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedMagnetInput ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedMagnetometer ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedMicrophone ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedOptical ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedClockNanosAndPad ||
|
||||
moduleType == DFConstantsAndEnums.ModuleType.EmbeddedClockSecondsAndMarker;
|
||||
}
|
||||
public bool IsThermocoupler()
|
||||
{
|
||||
DFConstantsAndEnums.ModuleType moduleType = ModuleType();
|
||||
return moduleType == DFConstantsAndEnums.ModuleType.Thermocoupler;
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor for a DASModule that initializes the object with a
|
||||
/// ModuleArrayIndex and a parent DAS as an IDASCommunication.
|
||||
/// </summary>
|
||||
/// <param name="moduleArrayIdx"></param>
|
||||
/// <param name="_OwningDAS"></param>
|
||||
public DASModule(int moduleArrayIdx, IDASCommunication _OwningDAS)
|
||||
{
|
||||
Channels = null;
|
||||
IDs = null;
|
||||
ModuleArrayIndex = moduleArrayIdx;
|
||||
PreTriggerSeconds = 0;
|
||||
PostTriggerSeconds = 0;
|
||||
NumberOfSamples = 0;
|
||||
TriggerSampleNumbers = null;
|
||||
|
||||
StartRecordSampleNumber = 0;
|
||||
SampleRateHz = 10000;
|
||||
AAFilterRateHz = 0;
|
||||
RecordingMode = DFConstantsAndEnums.RecordingMode.RecorderMode;
|
||||
OwningDAS = _OwningDAS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor for serialization methods compliance.
|
||||
/// </summary>
|
||||
public DASModule()
|
||||
{
|
||||
}
|
||||
public virtual void WriteXmlCRC32(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("DASModule");
|
||||
|
||||
// Channels
|
||||
writer.WriteStartElement("Channels");
|
||||
if (Channels != null)
|
||||
{
|
||||
foreach (var channel in Channels)
|
||||
{
|
||||
channel.WriteElementStart(writer);
|
||||
channel.WriteXmlCRC32(writer);
|
||||
channel.WriteElementEnd(writer);
|
||||
}
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
|
||||
// ModuleArrayIndex
|
||||
XMLHelper.PutInt(writer, "ModuleArrayIndex", ModuleArrayIndex);
|
||||
|
||||
// PreTriggerSeconds
|
||||
//XMLHelper.PutDouble(writer, "PreTriggerSeconds", PreTriggerSeconds);
|
||||
|
||||
// PostTriggerSeconds
|
||||
//XMLHelper.PutDouble(writer, "PostTriggerSeconds", PostTriggerSeconds);
|
||||
|
||||
// NumberOfSamples
|
||||
//XMLHelper.PutUInt64(writer, "NumberOfSamples", NumberOfSamples);
|
||||
|
||||
// StartRecordSampleNumber
|
||||
//XMLHelper.PutUInt64(writer, "StartRecordSampleNumber", StartRecordSampleNumber);
|
||||
|
||||
// SampleRateHz
|
||||
//XMLHelper.PutUInt(writer, "SampleRateHz", SampleRateHz);
|
||||
|
||||
// AAFilterRateHz, we write this one as a double
|
||||
//XMLHelper.PutDouble(writer, AAFilterRateHzTag, (double)AAFilterRateHz);
|
||||
|
||||
// RecordingMode
|
||||
//XMLHelper.PutString(writer, "RecordingMode", RecordingMode.ToString());
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
public virtual void WriteXml(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("DASModule");
|
||||
|
||||
// Channels
|
||||
writer.WriteStartElement("Channels");
|
||||
if (Channels != null)
|
||||
{
|
||||
foreach (var channel in Channels)
|
||||
{
|
||||
channel.WriteElementStart(writer);
|
||||
channel.WriteXml(writer);
|
||||
channel.WriteElementEnd(writer);
|
||||
}
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
|
||||
// ModuleArrayIndex
|
||||
XMLHelper.PutInt(writer, "ModuleArrayIndex", ModuleArrayIndex);
|
||||
|
||||
// PreTriggerSeconds
|
||||
XMLHelper.PutDouble(writer, "PreTriggerSeconds", PreTriggerSeconds);
|
||||
|
||||
// PostTriggerSeconds
|
||||
XMLHelper.PutDouble(writer, "PostTriggerSeconds", PostTriggerSeconds);
|
||||
|
||||
// NumberOfSamples
|
||||
XMLHelper.PutUInt64(writer, "NumberOfSamples", NumberOfSamples);
|
||||
|
||||
// StartRecordSampleNumber
|
||||
XMLHelper.PutUInt64(writer, "StartRecordSampleNumber", StartRecordSampleNumber);
|
||||
|
||||
// SampleRateHz
|
||||
XMLHelper.PutUInt(writer, "SampleRateHz", SampleRateHz);
|
||||
|
||||
// AAFilterRateHz, we write this one as a double
|
||||
XMLHelper.PutDouble(writer, AAFilterRateHzTag, AAFilterRateHz);
|
||||
|
||||
// RecordingMode
|
||||
XMLHelper.PutString(writer, "RecordingMode", RecordingMode.ToString());
|
||||
|
||||
// ScheduledStartTime
|
||||
XMLHelper.PutString(writer, "ScheduledStartTime", ScheduledStartTime.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
|
||||
// RecordingInterval
|
||||
XMLHelper.PutString(writer, "RecordingInterval", RecordingInterval.ToString());
|
||||
|
||||
// Slice 6 Tilt variables
|
||||
XMLHelper.PutString(writer, "TiltAxes", TiltAxes.ToString());
|
||||
XMLHelper.PutString(writer, "SystemID", SystemID);
|
||||
XMLHelper.PutString(writer, "SystemLocation", SystemLocation);
|
||||
XMLHelper.PutDouble(writer, "TargetAxisOne", TargetAxisOne);
|
||||
XMLHelper.PutDouble(writer, "TargetAxisTwo", TargetAxisTwo);
|
||||
XMLHelper.PutDouble(writer, "MountOffsetAxisOne", MountOffsetAxisOne);
|
||||
XMLHelper.PutDouble(writer, "MountOffsetAxisTwo", MountOffsetAxisTwo);
|
||||
XMLHelper.PutDouble(writer, "LevelTolerance", LevelTolerance);
|
||||
XMLHelper.PutInt(writer, "AxisIgnored", AxisIgnored);
|
||||
XMLHelper.PutBool(writer, "UseForTiltCalculation", UseForTiltCalculation);
|
||||
XMLHelper.PutDouble(writer, "InputVoltage", InputVoltage);
|
||||
XMLHelper.PutDouble(writer, "BatteryVoltage", BatteryVoltage);
|
||||
|
||||
// FB 26980 Write NumberOfEvents to XML
|
||||
XMLHelper.PutInt(writer, "NumberOfEvents", NumberOfEvents);
|
||||
XMLHelper.PutInt(writer, "WakeUpMotionTimeout", WakeUpMotionTimeout);
|
||||
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
private void ReadChannels(XmlReader reader)
|
||||
{
|
||||
var myChannels = new List<DASChannel>();
|
||||
do
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element && reader.Name == "DASChannel")
|
||||
{
|
||||
var chanType = "DTS.DASLib.Service." + reader.GetAttribute("xsi:type");
|
||||
var channelClassType = Type.GetType(chanType);
|
||||
var deserializedChannel = Activator.CreateInstance(channelClassType) as DASChannel;
|
||||
deserializedChannel.ReadXml(reader);
|
||||
myChannels.Add(deserializedChannel);
|
||||
}
|
||||
//if we are at </channels> break out now, don't want to do a read()
|
||||
if (reader.Name == "Channels" && (reader.NodeType == XmlNodeType.EndElement || reader.IsEmptyElement))
|
||||
{
|
||||
break;
|
||||
}
|
||||
//if we are at <DASChannel> we don't want to do a read, otherwise we do
|
||||
if (!(reader.NodeType == XmlNodeType.Element && reader.Name == "DASChannel"))
|
||||
{
|
||||
if (!reader.Read()) { break; }
|
||||
}
|
||||
|
||||
} while (!(reader.Name == "Channels" && reader.NodeType == XmlNodeType.EndElement));
|
||||
|
||||
Channels = myChannels.ToArray();
|
||||
}
|
||||
private const string CHANNELS_TAG = "Channels";
|
||||
private const string MODULEARRAYINDEX_TAG = "ModuleArrayIndex";
|
||||
private const string PRETRIGGERSECONDS_TAG = "PreTriggerSeconds";
|
||||
private const string POSTTRIGGERSECONDS_TAG = "PostTriggerSeconds";
|
||||
private const string NUMBEROFSECONDS_TAG = "NumberOfSamples";
|
||||
private const string TRIGGERSAMPLENUMBERS_TAG = "TriggerSampleNumbers";
|
||||
private const string STARTRECORDSAMPLENUMBER_TAG = "StartRecordSampleNumber";
|
||||
private const string SAMPLERATEHZ_TAG = "SampleRateHz";
|
||||
private const string AAFILTERRATEHZ_TAG = "AAFilterRateHz";
|
||||
private const string RECORDINGMODE_TAG = "RecordingMode";
|
||||
private const string SCHEDULEDSTARTTIME_TAG = "ScheduledStartTime";
|
||||
private const string RECORDINGINTERVAL_TAG = "RecordingInterval";
|
||||
private const string TILT_AXES_TAG = "TiltAxes";
|
||||
private const string SYSTEMID_TAG = "SystemID";
|
||||
private const string SYSTEMLOCATION_TAG = "SystemLocation";
|
||||
private const string MOUNTOFFSETAXISONE_TAG = "MountOffsetAxisOne";
|
||||
private const string MOUNTOFFSETAXISTWO_TAG = "MountOffsetAxisTwo";
|
||||
private const string TARGETAXISONE_TAG = "TargetAxisOne";
|
||||
private const string TARGETAXISTWO_TAG = "TargetAxisTwo";
|
||||
private const string LEVELTOLERANCE_TAG = "LevelTolerance";
|
||||
private const string AXISIGNORED_TAG = "AxisIgnored";
|
||||
private const string USEFORTILTCALCULATION_TAG = "UseForTiltCalculation";
|
||||
private const string INPUTVOLTAGE_TAG = "InputVoltage";
|
||||
private const string BATTERYVOLTAGE_TAG = "BatteryVoltage";
|
||||
private const string NUMBEROFEVENTS_TAG = "NumberOfEvents";
|
||||
private const string WAKEUPTIMEOUT_TAG = "WakeUpTimeout";
|
||||
|
||||
protected virtual void HandleElement(XmlReader reader)
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case CHANNELS_TAG:
|
||||
ReadChannels(reader);
|
||||
break;
|
||||
case MODULEARRAYINDEX_TAG:
|
||||
ModuleArrayIndex = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case PRETRIGGERSECONDS_TAG:
|
||||
PreTriggerSeconds = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case POSTTRIGGERSECONDS_TAG:
|
||||
PostTriggerSeconds = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case NUMBEROFSECONDS_TAG:
|
||||
NumberOfSamples = XMLHelper.GetUInt64(reader);
|
||||
break;
|
||||
case TRIGGERSAMPLENUMBERS_TAG: // UInt64[]
|
||||
throw new XmlException("DASModule.ReadXml: Unexpected TriggerSampleNumbers tag in data");
|
||||
case STARTRECORDSAMPLENUMBER_TAG:
|
||||
StartRecordSampleNumber = XMLHelper.GetUInt64(reader);
|
||||
break;
|
||||
case SAMPLERATEHZ_TAG:
|
||||
SampleRateHz = XMLHelper.GetUInt(reader);
|
||||
break;
|
||||
case AAFilterRateHzTag:
|
||||
AAFilterRateHz = XMLHelper.GetFloat(reader);
|
||||
break;
|
||||
case RECORDINGMODE_TAG:
|
||||
var value = XMLHelper.GetString(reader);
|
||||
if (!Enum.TryParse(value, out DFConstantsAndEnums.RecordingMode mode))
|
||||
{
|
||||
if (value.Equals("ActiveMode"))
|
||||
{
|
||||
RecordingMode = DFConstantsAndEnums.RecordingMode.Aerospace;
|
||||
}
|
||||
}
|
||||
else { RecordingMode = mode; }
|
||||
break;
|
||||
case SCHEDULEDSTARTTIME_TAG:
|
||||
var scheduledStartTime = XMLHelper.GetString(reader);
|
||||
ScheduledStartTime = DateTime.Parse(scheduledStartTime, System.Globalization.CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case RECORDINGINTERVAL_TAG:
|
||||
RecordingInterval = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case TILT_AXES_TAG:
|
||||
var ta = XMLHelper.GetString(reader);
|
||||
TiltAxes = (DFConstantsAndEnums.TiltAxes)Enum.Parse(typeof(DFConstantsAndEnums.TiltAxes), ta);
|
||||
break;
|
||||
case SYSTEMID_TAG:
|
||||
SystemID = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case SYSTEMLOCATION_TAG:
|
||||
SystemLocation = XMLHelper.GetString(reader);
|
||||
break;
|
||||
case MOUNTOFFSETAXISONE_TAG:
|
||||
MountOffsetAxisOne = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case MOUNTOFFSETAXISTWO_TAG:
|
||||
MountOffsetAxisTwo = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case TARGETAXISONE_TAG:
|
||||
TargetAxisOne = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case TARGETAXISTWO_TAG:
|
||||
TargetAxisTwo = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case LEVELTOLERANCE_TAG:
|
||||
LevelTolerance = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case AXISIGNORED_TAG:
|
||||
AxisIgnored = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case USEFORTILTCALCULATION_TAG:
|
||||
UseForTiltCalculation = XMLHelper.GetBool(reader);
|
||||
break;
|
||||
case INPUTVOLTAGE_TAG:
|
||||
InputVoltage = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
case BATTERYVOLTAGE_TAG:
|
||||
BatteryVoltage = XMLHelper.GetDouble(reader);
|
||||
break;
|
||||
//FB 26980
|
||||
case NUMBEROFEVENTS_TAG:
|
||||
NumberOfEvents = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
case WAKEUPTIMEOUT_TAG:
|
||||
WakeUpMotionTimeout = XMLHelper.GetInt(reader);
|
||||
break;
|
||||
default:
|
||||
// let child handle it
|
||||
break;
|
||||
}
|
||||
}
|
||||
public virtual void ReadXml(XmlReader reader)
|
||||
{
|
||||
// it must be an Element
|
||||
if (reader.NodeType != XmlNodeType.Element)
|
||||
{
|
||||
throw new XmlException("DASModule.ReadXml: Unknown input: " + reader.NodeType.ToString());
|
||||
}
|
||||
|
||||
// remove our start tag
|
||||
if (reader.Name == "DASModule")
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (reader.NodeType != XmlNodeType.EndElement)
|
||||
{
|
||||
HandleElement(reader);
|
||||
}
|
||||
if (!reader.Read()) { break; }
|
||||
} while (!(reader.Name.Equals("DASModule") && reader.NodeType == XmlNodeType.EndElement));
|
||||
|
||||
|
||||
// we're going to end with an EndElement, so clean up
|
||||
if (reader.NodeType == XmlNodeType.EndElement && reader.Name.Equals("DASModule"))
|
||||
{
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual ushort GetCRC32()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
using (var writer = XmlWriter.Create(sb))
|
||||
{
|
||||
WriteXmlCRC32(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
var lData = new List<byte>(Encoding.UTF8.GetBytes(sb.ToString()));
|
||||
|
||||
if (0 != lData.Count % 2) { lData.Add(0x00); }
|
||||
byte[] data = lData.ToArray();
|
||||
|
||||
ushort crc = 0xFFFF;
|
||||
for (int i = 0; i < data.Length; i += 2)
|
||||
{
|
||||
crc = Utils.Math_DoCRC16Step(BitConverter.ToUInt16(data, i), crc);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
150
DataPRO/IService/Classes/Diagnostics/DiagnosticActions.cs
Normal file
150
DataPRO/IService/Classes/Diagnostics/DiagnosticActions.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using DASFactoryDb.Diagnostics;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class holds instructions about how a single channel
|
||||
/// is to be diagnosed. The results from these tests will populate the
|
||||
/// DiagnosticsResults[] object in the IDASCommunication object. The results
|
||||
/// can then be compared against the hardware specifications for a sensor to
|
||||
/// determine if the channel is set up correctly before arming and recording.
|
||||
/// </summary>
|
||||
public class DiagnosticsActions : IDiagnosticActions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Which DAS Channel (CH# WRT entire DAS unit) are these diagnostic test
|
||||
/// instructions for?
|
||||
/// </summary>
|
||||
public int DASChannelNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we measure the excitation volatge being applied to this sensor?
|
||||
/// </summary>
|
||||
public bool MeasureExcitation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we measure the sensor's offset from 0? (If measured, the returned offset can
|
||||
/// be checked against the high and low offset limits that are properties of the
|
||||
/// AnalogInputDasChannel object corresponding to this sensor.)
|
||||
/// </summary>
|
||||
public bool MeasureOffset { get; set; }
|
||||
/// <summary>
|
||||
/// should we check the open/closed/low/high nature of a digital input channel?
|
||||
/// </summary>
|
||||
public bool CheckDigitalState { get; set; }
|
||||
|
||||
public bool MeasureInternalOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the firmware compensate for the offset from 0 of this sensor?
|
||||
/// </summary>
|
||||
public bool RemoveOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we measure the noise floor as a percentage of full scale readings?
|
||||
/// </summary>
|
||||
public bool MeasureNoise { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should an emulated shunt-check be performed on this sensor.
|
||||
/// </summary>
|
||||
public bool PerformShuntCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// should run a squib fire check on channel
|
||||
/// </summary>
|
||||
public bool SquibFireCheck { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// perform a voltage insertion gain check (SLICE Pro)
|
||||
/// </summary>
|
||||
public bool PerformVoltageInsertCheck { get; set; }
|
||||
/// <summary>
|
||||
/// Should a Calibration signal-check be performed on this sensor.
|
||||
/// </summary>
|
||||
public bool PerformCalSignalCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the resistance of the bridge be measured?
|
||||
/// </summary>
|
||||
public bool MeasureBridgeResistance { get; set; }
|
||||
|
||||
public DiagnosticsActions()
|
||||
{
|
||||
DASChannelNumber = 0;
|
||||
MeasureExcitation = false;
|
||||
MeasureOffset = false;
|
||||
RemoveOffset = false;
|
||||
MeasureNoise = false;
|
||||
PerformShuntCheck = false;
|
||||
PerformCalSignalCheck = false;
|
||||
PerformVoltageInsertCheck = false;
|
||||
MeasureInternalOffset = false;
|
||||
CheckDigitalState = false;
|
||||
}
|
||||
|
||||
public bool AllActionsDisabled()
|
||||
{
|
||||
return !MeasureExcitation && !MeasureOffset && !RemoveOffset && !MeasureNoise && !PerformShuntCheck &&
|
||||
!MeasureBridgeResistance
|
||||
&& !PerformCalSignalCheck && !PerformVoltageInsertCheck && !MeasureInternalOffset && !SquibFireCheck &&
|
||||
!CheckDigitalState;
|
||||
}
|
||||
|
||||
public static void SetChannelDiagnosticActions(IDASCommunication unit, IDiagnosticActions[] actions,
|
||||
bool setInDb)
|
||||
{
|
||||
unit.ChannelDiagnostics = actions;
|
||||
if (!DASFactoryDb.DbWrapper.Connected || !setInDb) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Diagnostics.ClearDiagnosticActionsAllChannels(unit.RecordId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
|
||||
if (null != actions)
|
||||
{
|
||||
foreach (var action in actions)
|
||||
{
|
||||
InsertAction(unit.RecordId, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertAction(int dasRecordId, IDiagnosticActions action)
|
||||
{
|
||||
try
|
||||
{
|
||||
Diagnostics.InsertDiagnosticAction(dasRecordId,
|
||||
action.DASChannelNumber,
|
||||
action.MeasureExcitation,
|
||||
action.MeasureOffset,
|
||||
action.CheckDigitalState,
|
||||
action.MeasureInternalOffset,
|
||||
action.RemoveOffset,
|
||||
action.MeasureNoise,
|
||||
action.PerformShuntCheck,
|
||||
action.SquibFireCheck,
|
||||
action.PerformVoltageInsertCheck,
|
||||
action.PerformCalSignalCheck,
|
||||
action.MeasureBridgeResistance);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
194
DataPRO/IService/Classes/Diagnostics/DiagnosticsResult.cs
Normal file
194
DataPRO/IService/Classes/Diagnostics/DiagnosticsResult.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// This class holds the results from one channel's diagnostics. These results are arbitrary on
|
||||
/// thier own but can be checked against the hardware specifications or settings for the sensor on the
|
||||
/// corresponding channel to provide pre-recording checks or diagnostic feedback about how the channel is
|
||||
/// set up. For example this DiagnosticsResult will provide the acutal voltage that is being applied to
|
||||
/// sensor for excitation, and this can be verified correct or incorrect based on what the sensor
|
||||
/// actually needs for excitation. The sensor specific values can be found in the corresponding DASChannel
|
||||
/// (<see cref="AnalogInputDASChannel" />) object in the ConfigData object for the IDASCommunication where this channel lives,
|
||||
/// but they must be put there by a call to ConfigureService.Configure(...).
|
||||
/// </summary>
|
||||
public class DiagnosticsResult : IDiagnosticResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Which DASChannel from which this diagnostics is returning.
|
||||
/// </summary>
|
||||
public int DASChannelNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event number that this diagnostics is relevant for.
|
||||
/// </summary>
|
||||
public int EventNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The firmware calculates a scale factory for the channel's input. The hardware will
|
||||
/// deliver raw, unprocessed data upon download, but to diagnos this data to
|
||||
/// reflect real world votages it must be scaled based on the DAS unit's factory
|
||||
/// diagnostics as well as results from this diagnose. The samples that
|
||||
/// will be downloaded will be straight from the A to D Converter so this scale
|
||||
/// factor is MANDATORY and must be used at the software level to scale the data
|
||||
/// to the real sensed voltages and engineering units.
|
||||
/// </summary>
|
||||
public double ScalefactorMilliVoltsPerADC { get; set; } = 1;
|
||||
public double ScalefactorEngineeringUnitsPerADC { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The factory excitation value (mandatory)
|
||||
/// </summary>
|
||||
public double ExpectedExcitationMilliVolts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// gets what will probably be the datazerolevel adc for the channel
|
||||
/// </summary>
|
||||
/// <param name="zeroMethod"></param>
|
||||
/// <returns></returns>
|
||||
public short GetExpectedDataZeroLevelADC(ZeroMethodType zeroMethod)
|
||||
{
|
||||
switch (zeroMethod)
|
||||
{
|
||||
case ZeroMethodType.None:
|
||||
return ZeroMVInADC;
|
||||
default:
|
||||
// if FinalOffsetADC is NOT null, offset has been measured after calibration
|
||||
// and that's the amount is what we should use
|
||||
if (FinalOffsetADC != null)
|
||||
{
|
||||
return (short)FinalOffsetADC;
|
||||
}
|
||||
// OK, FinalOffsetADC was null so we need to check MeasuredOffsetMilliVolts
|
||||
// if it's NOT null, that's what we'll use
|
||||
if (MeasuredOffsetMilliVolts != null)
|
||||
{
|
||||
return (short)((double)MeasuredOffsetMilliVolts / ScalefactorMilliVoltsPerADC);
|
||||
}
|
||||
// both of them are null so the only thing we can do is return 0
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Excitation voltage provided to sensor as measured by the firmware during
|
||||
/// calibration. When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? MeasuredExcitationMilliVolts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// flag to indicate whether MeasuredExcitationMilliVolts was negative when it was initially read
|
||||
/// 14233 Negative Excitation Reported by TDAS hardware not showing in Diagnostics
|
||||
/// this was created to relate to legacy TDC/TDAS broken sensor/wire warnings carried through
|
||||
/// the excitation reading
|
||||
/// </summary>
|
||||
public bool NegativeExcitation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the sensor's offset reading from the 0 level? This is measured by firmware
|
||||
/// during the calibration. When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? MeasuredOffsetMilliVolts { get; set; }
|
||||
|
||||
public double? MeasuredInternalOffsetMilliVolts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the sensor's offset reading from the 0 level? This is measured by firmware
|
||||
/// during the calibration. When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? MeasuredOffsetEngineeringUnits { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// when a channel is autozero'd (remove offset)
|
||||
/// this is the devation from 0 (from RW Auto zero is checking for +/- 5% from 0 in counts.)
|
||||
/// </summary>
|
||||
private double? _autoZeroPercentDeviation;
|
||||
public double? AutoZeroPercentDeviation
|
||||
{
|
||||
get => _autoZeroPercentDeviation;
|
||||
set => _autoZeroPercentDeviation = null != value ? (double?)System.Math.Abs((double)value) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="DTS.DASLib.Service.DiagnosticsService" />.Calibrate method was called with the "RemoveOffset" boolean variable set
|
||||
/// to TRUE then the firmware will attempt to remove the offset of the sensor, moving it's base
|
||||
/// reading back to 0. This value is how much offset is present after removing the offset. While the
|
||||
/// offset my not be compeletely removed it may have been reduced to fall within the high and low
|
||||
/// limits for acceptable offsets for the sensor. See <see cref="AnalogInputDASChannel" /> to find
|
||||
/// these sensor specific values. When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public short? FinalOffsetADC { get; set; }
|
||||
|
||||
public int? RemovedOffsetADC { get; set; }
|
||||
|
||||
public int? RemovedInternalOffsetADC { get; set; }
|
||||
/// <summary>
|
||||
/// FullScaleSignal to Noise ratio as a percentage. When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? NoisePercentFullScale { get; set; }
|
||||
|
||||
public bool ShuntDeflectionFailed { get; set; }
|
||||
|
||||
public bool CalSignalCheckFailed { get; set; }
|
||||
/// <summary>
|
||||
/// If an emulated shunt test is performed the measured shunt deflection in mV detected
|
||||
/// during the test will be here.
|
||||
/// <see cref="DTS.DASLib.Service.DiagnosticsActions" />.PerformShuntCheck
|
||||
/// When read from event attributes, a value of 0.0 might actually mean null
|
||||
/// (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? MeasuredShuntDeflectionMv { get; set; }
|
||||
|
||||
public double? MeasuredCalSignalMv { get; set; }
|
||||
public double? TargetCalSignalMv { get; set; }
|
||||
|
||||
public double? MeasuredDurationMS { get; set; }
|
||||
|
||||
public double? MeasuredDelayMS { get; set; }
|
||||
public bool? SquibFirePassed { get; set; }
|
||||
public bool? SquibDurationPassed { get; set; }
|
||||
public bool? SquibDelayPassed { get; set; }
|
||||
public double[] SquibFireCurrentData { get; set; }
|
||||
public double[] SquibFireVoltageData { get; set; }
|
||||
public double[] SquibFireTimeAxis { get; set; }
|
||||
public double SquibThreshold { get; set; }
|
||||
|
||||
public double SquibVoltageScaler { get; set; }
|
||||
public double SquibCurrentScaler { get; set; }
|
||||
|
||||
public double? TargetGain { get; set; }
|
||||
public double? MeasuredGain { get; set; }
|
||||
public double? QueriedGain { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If an emulated shunt test is performed the target shunt deflection in mV will be here.
|
||||
/// CalibrateActions.PerformShuntCheck When read from event attributes, a value of 0.0 might actually
|
||||
/// mean null (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? TargetShuntDeflectionMv { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If the bridge resistance of the sensor was measured, the measured resistance in
|
||||
/// ohms will be here. <see cref="DiagnosticsActions.MeasureBridgeResistance" />
|
||||
/// When read from event attributes, a value of 0.0 might actually mean null
|
||||
/// (i.e. was not measured).
|
||||
/// </summary>
|
||||
public double? BridgeResistance { get; set; }
|
||||
|
||||
public short ZeroMVInADC { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// WindowAverageADC is the average ADC over the averaging window specified for the channel
|
||||
/// short.MinValue indicates an unitialized or invalid value
|
||||
/// </summary>
|
||||
public short WindowAverageADC { get; set; } = short.MinValue;
|
||||
public bool DigitalInputActiveState { get; set; }
|
||||
}
|
||||
}
|
||||
158
DataPRO/IService/Classes/Diagnostics/DiagnosticsResultActions.cs
Normal file
158
DataPRO/IService/Classes/Diagnostics/DiagnosticsResultActions.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service.Classes.Diagnostics
|
||||
{
|
||||
public static class DiagnosticsResultActions
|
||||
{
|
||||
/// <summary>
|
||||
/// clears all diagnostics from all events and channels, and optionally clears from db
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="bClearDb"></param>
|
||||
public static void ClearChannelDiagnosticsResults(IDASCommunication unit, bool bClearDb = true)
|
||||
{
|
||||
unit.ChannelDiagnosticsResults = new IDiagnosticResult[0];
|
||||
unit.ChannelDiagnostics = new IDiagnosticActions[0];
|
||||
|
||||
if (!DASFactoryDb.DbWrapper.Connected || !bClearDb) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
DASFactoryDb.Diagnostics.Diagnostics.ClearExistingDiagnosticsAllChannels(unit.RecordId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// sets the channel diagnostics, optionally writes to the db
|
||||
/// </summary>
|
||||
/// <param name="unit"></param>
|
||||
/// <param name="results"></param>
|
||||
/// <param name="setInDb"></param>
|
||||
public static void SetChannelDiagnosticsResults(IDASCommunication unit, IDiagnosticResult[] results, bool setInDb)
|
||||
{
|
||||
unit.ChannelDiagnosticsResults = results;
|
||||
if (!DASFactoryDb.DbWrapper.Connected || !setInDb) { return; }
|
||||
try
|
||||
{
|
||||
foreach (var result in results)
|
||||
{
|
||||
var moduleNumber = unit.DASInfo.MapDASChannelNumber2ModuleArrayIndex(result.DASChannelNumber);
|
||||
var channelIndex = unit.DASInfo.MapDASChannelNumber2ModuleChannelNumber(result.DASChannelNumber);
|
||||
var channel = unit.ConfigData.Modules[moduleNumber].Channels[channelIndex];
|
||||
if (channel is AnalogInputDASChannel aic)
|
||||
{
|
||||
if (aic.DigitalInputChannel)
|
||||
{
|
||||
InsertDiagnosticsResultDigital(unit, aic, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
InsertDiagnosticsResultAnalog(unit, aic, result);
|
||||
}
|
||||
}
|
||||
else if (channel is OutputSquibChannel squib)
|
||||
{
|
||||
InsertDiagnosticsResultsSquib(unit, squib, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// writes a single digital result to the db
|
||||
/// </summary>
|
||||
/// <param name="das"></param>
|
||||
/// <param name="aic"></param>
|
||||
/// <param name="result"></param>
|
||||
private static void InsertDiagnosticsResultDigital(IDASCommunication das, AnalogInputDASChannel aic,
|
||||
IDiagnosticResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
DASFactoryDb.Diagnostics.Diagnostics.InsertDigitalDiagnosticResult(das.RecordId,
|
||||
result.DASChannelNumber,
|
||||
result.EventNumber,
|
||||
result.DigitalInputActiveState);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// writes a single analog result to the db
|
||||
/// </summary>
|
||||
/// <param name="das"></param>
|
||||
/// <param name="aic"></param>
|
||||
/// <param name="result"></param>
|
||||
private static void InsertDiagnosticsResultAnalog(IDASCommunication das, AnalogInputDASChannel aic,
|
||||
IDiagnosticResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
DASFactoryDb.Diagnostics.Diagnostics.InsertAnalogDiagnosticResult(
|
||||
das.RecordId,
|
||||
result.DASChannelNumber,
|
||||
result.EventNumber,
|
||||
result.ScalefactorMilliVoltsPerADC,
|
||||
result.ExpectedExcitationMilliVolts,
|
||||
result.MeasuredExcitationMilliVolts,
|
||||
result.NegativeExcitation,
|
||||
result.MeasuredOffsetMilliVolts,
|
||||
result.MeasuredInternalOffsetMilliVolts,
|
||||
result.AutoZeroPercentDeviation,
|
||||
result.FinalOffsetADC,
|
||||
result.RemovedOffsetADC,
|
||||
result.RemovedInternalOffsetADC,
|
||||
result.NoisePercentFullScale,
|
||||
result.ShuntDeflectionFailed,
|
||||
result.CalSignalCheckFailed,
|
||||
result.MeasuredShuntDeflectionMv,
|
||||
result.MeasuredCalSignalMv,
|
||||
result.TargetCalSignalMv,
|
||||
result.TargetGain,
|
||||
result.MeasuredGain,
|
||||
result.QueriedGain,
|
||||
result.TargetShuntDeflectionMv,
|
||||
result.BridgeResistance,
|
||||
result.ZeroMVInADC,
|
||||
result.WindowAverageADC);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// writes a single squib diagnostic to the db
|
||||
/// </summary>
|
||||
/// <param name="das"></param>
|
||||
/// <param name="squib"></param>
|
||||
/// <param name="result"></param>
|
||||
private static void InsertDiagnosticsResultsSquib(IDASCommunication das, OutputSquibChannel squib,
|
||||
IDiagnosticResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
DASFactoryDb.Diagnostics.Diagnostics.InsertSquibDiagnosticResult(das.RecordId,
|
||||
result.DASChannelNumber, result.EventNumber, result.SquibFireCurrentData,
|
||||
result.SquibFireVoltageData, result.SquibFireTimeAxis, result.MeasuredDurationMS,
|
||||
result.MeasuredDelayMS, result.SquibFirePassed, result.SquibDurationPassed, result.SquibDelayPassed,
|
||||
result.SquibThreshold, result.SquibVoltageScaler, result.SquibCurrentScaler);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//for now just skip the logging
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
14
DataPRO/IService/Classes/Diagnostics/OptimizationValues.cs
Normal file
14
DataPRO/IService/Classes/Diagnostics/OptimizationValues.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DTS.DASLib.Service.Classes.Diagnostics
|
||||
{
|
||||
public class OptimizationValues : IOptimizationValues
|
||||
{
|
||||
public float TransferSpeed { get; set; }
|
||||
}
|
||||
}
|
||||
325
DataPRO/IService/Classes/Download/DownloadReport.cs
Normal file
325
DataPRO/IService/Classes/Download/DownloadReport.cs
Normal file
@@ -0,0 +1,325 @@
|
||||
|
||||
using DASFactoryDb.Download;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Interface.DASFactory.Download;
|
||||
using DTS.Common.Interface.DownloadEvent;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
using System.Data.SqlClient;
|
||||
using System.Data.SqlTypes;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// This class represent all events stored on the DAS. It is populated during
|
||||
/// <see cref="DownloadService.QueryDownload" />.
|
||||
/// </summary>
|
||||
public class DownloadReport : IDownloadReport
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represent one event/test.
|
||||
/// </summary>
|
||||
public class EventInfo : IEventInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Information about each module that was part of the event. Addressable by
|
||||
/// ModuleArrayIndex of the corresponding module.
|
||||
/// </summary>
|
||||
public IDASModule[] Modules { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event number this information is regarding.
|
||||
/// </summary>
|
||||
public int EventNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The GUID of the corresponding event.
|
||||
/// </summary>
|
||||
public Guid TestGUID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fault flags (if any)
|
||||
/// </summary>
|
||||
public ushort FaultFlags { get; set; }
|
||||
/// <summary>
|
||||
/// fault flags extended (if any)
|
||||
/// </summary>
|
||||
public ushort FaultFlagsEx { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Arm Attempts (if any)
|
||||
/// </summary>
|
||||
public byte ArmAttempts { get; set; }
|
||||
/// <summary>
|
||||
/// The timestamp of this event.
|
||||
/// </summary>
|
||||
public DateTime TestTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of this event.
|
||||
/// </summary>
|
||||
public string TestID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A text description that was stored.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if this event has already been downloaded.
|
||||
/// </summary>
|
||||
public bool HasBeenDownloaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if this event received a trigger.
|
||||
/// </summary>
|
||||
public bool WasTriggered { get; set; }
|
||||
/// <summary>
|
||||
/// clears any fault flags
|
||||
/// </summary>
|
||||
public void ClearFaults()
|
||||
{
|
||||
FaultFlags = 0;
|
||||
FaultFlagsEx = 0;
|
||||
}
|
||||
public EventInfo() { }
|
||||
public EventInfo(EventInfo copy)
|
||||
{
|
||||
Modules = copy.Modules;
|
||||
|
||||
EventNumber = copy.EventNumber;
|
||||
|
||||
TestGUID = copy.TestGUID;
|
||||
|
||||
FaultFlags = copy.FaultFlags;
|
||||
FaultFlagsEx = copy.FaultFlagsEx;
|
||||
|
||||
ArmAttempts = copy.ArmAttempts;
|
||||
TestTime = copy.TestTime;
|
||||
|
||||
TestID = copy.TestID;
|
||||
|
||||
Description = copy.Description;
|
||||
|
||||
HasBeenDownloaded = copy.HasBeenDownloaded;
|
||||
|
||||
WasTriggered = copy.WasTriggered;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class represent one event/test.
|
||||
/// </summary>
|
||||
public class UARTEventInfo : IUARTEventInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// From which event do we want to download data?
|
||||
/// </summary>
|
||||
public ushort EventNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is data present?
|
||||
/// </summary>
|
||||
public bool DataPresent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has data already been downloaded?
|
||||
/// </summary>
|
||||
public bool DataDownloaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How much data is there?
|
||||
/// </summary>
|
||||
public ulong TotalByteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Where in the data did the trigger occur?
|
||||
/// </summary>
|
||||
public ulong TriggerByteCount { get; set; }
|
||||
/// <summary>
|
||||
/// Where are the faults?
|
||||
/// </summary>
|
||||
public ulong FaultByteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When did the UART stream start?
|
||||
/// </summary>
|
||||
public ulong StartTimestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When did the UART stream end?
|
||||
/// </summary>
|
||||
public ulong EndTimestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What was the baud rate during UART recording?
|
||||
/// </summary>
|
||||
public uint BaudRate { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An array of all events stored on this DAS.
|
||||
/// </summary>
|
||||
public IEventInfo[] Events { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of all UART events stored on this DAS.
|
||||
/// </summary>
|
||||
public IUARTEventInfo[] UARTEvents { get; set; }
|
||||
|
||||
public static void SetEventDownloadStatus(IDASCommunication das, bool[] status, bool bStoreInDb)
|
||||
{
|
||||
if (null == das) { return; }
|
||||
das.EventDownloadedStatus = status;
|
||||
if (!bStoreInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingEventDownloadStatus(das.RecordId);
|
||||
if (null == status) { return; }
|
||||
foreach (var statum in status)
|
||||
{
|
||||
Download.InsertEventDownloadStatus(das.RecordId, statum);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
public static void SetEventArmAttempts(IDASCommunication das, byte[] armAttempts, bool storeInDb)
|
||||
{
|
||||
if (null == das) { return; }
|
||||
das.ArmAttempts = armAttempts;
|
||||
|
||||
if (!storeInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingEventArmAttempts(das.RecordId);
|
||||
if (null == armAttempts) { return; }
|
||||
foreach (byte armAttempt in armAttempts)
|
||||
{
|
||||
Download.InsertEventArmAttempts(das.RecordId, armAttempt);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
public static void SetEventFaultFlags(IDASCommunication das, ushort[] faultFlags, bool storeInDb)
|
||||
{
|
||||
if (null == das) { return; }
|
||||
das.FaultFlags = faultFlags;
|
||||
if (!storeInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingFaultFlags(das.RecordId);
|
||||
if (null == faultFlags) { return; }
|
||||
foreach (var flag in faultFlags)
|
||||
{
|
||||
Download.InsertEventFaultFlags(das.RecordId, flag);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetEventInfo(IDASCommunication das, IDownloadReport eventInfo, bool storeInDB)
|
||||
{
|
||||
if (null == das) { return; }
|
||||
das.EventInfo = eventInfo;
|
||||
if (!storeInDB || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingDownloadReports(das.RecordId);
|
||||
if (null == eventInfo || null == eventInfo.Events) { return; }
|
||||
foreach (var eventData in eventInfo.Events)
|
||||
{
|
||||
InsertEventInfo(das, eventData);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertEventInfo(IDASCommunication das, IEventInfo eventInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (null == eventInfo || null == das)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var xml = string.Empty;
|
||||
using (var sw = new StringWriter())
|
||||
{
|
||||
using (var xw = XmlWriter.Create(sw,
|
||||
new XmlWriterSettings() { ConformanceLevel = ConformanceLevel.Document }))
|
||||
{
|
||||
xw.WriteStartDocument();
|
||||
xw.WriteStartElement("Modules");
|
||||
foreach (var mod in eventInfo.Modules)
|
||||
{
|
||||
mod.WriteXml(xw);
|
||||
}
|
||||
|
||||
xw.WriteEndElement();
|
||||
xw.WriteEndDocument();
|
||||
}
|
||||
sw.Flush();
|
||||
xml = sw.ToString();
|
||||
}
|
||||
|
||||
Download.InsertEventInfo(das.RecordId,
|
||||
eventInfo.EventNumber,
|
||||
eventInfo.TestGUID,
|
||||
eventInfo.FaultFlags,
|
||||
eventInfo.ArmAttempts,
|
||||
eventInfo.TestTime,
|
||||
eventInfo.TestID,
|
||||
eventInfo.Description,
|
||||
eventInfo.HasBeenDownloaded,
|
||||
eventInfo.WasTriggered,
|
||||
xml
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
public static void SetEventGuids(IDASCommunication das, Guid[] guids, bool storeInDb)
|
||||
{
|
||||
if (null == das) { return; }
|
||||
das.EventGuids = guids;
|
||||
if (!storeInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingEventGuids(das.RecordId);
|
||||
if (null == guids) { return; }
|
||||
foreach (var guid in guids)
|
||||
{
|
||||
Download.EventGuidInsert(das.RecordId, guid);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
108
DataPRO/IService/Classes/Download/DownloadRequest.cs
Normal file
108
DataPRO/IService/Classes/Download/DownloadRequest.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
|
||||
using DASFactoryDb.Download;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Download;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// This class describes what should be downloaded from the DAS to the PC.
|
||||
/// </summary>
|
||||
public class DownloadRequest : IDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Setting the DASChannelNumber property of this object to this constant value will
|
||||
/// download all channels from the DAS. Currently, this is the only option that is supported
|
||||
/// so DASChannelNumber MUST be equal to this value.
|
||||
/// </summary>
|
||||
public const byte ALL_CHANNELS = 0xFF;
|
||||
|
||||
/// <summary>
|
||||
/// From which event do we want to download data?
|
||||
/// </summary>
|
||||
public ushort EventNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Which channel? (set to ALL_CHANNELS for all)
|
||||
/// </summary>
|
||||
public byte DASChannelNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The first sample you want.
|
||||
/// </summary>
|
||||
public virtual ulong StartSample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The last sample you want.
|
||||
/// </summary>
|
||||
public virtual ulong EndSample { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is used for sub-sampling data, 0 (or 1) means don't sub-sample, 2 means
|
||||
/// give me every other sample and so on. The number of samples requested
|
||||
/// (EndSample-StartSample+1) must be an multiple of SamplesToSkip.
|
||||
/// </summary>
|
||||
public ulong SamplesToSkip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double StartRecordTimestampSec { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TriggerTimestampSec { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double StartRecordTimestampNanoSec { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double TriggerTimestampNanoSec { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool PTPMasterSync { get; set; }
|
||||
|
||||
public static void SetWhatToDownload(IDASCommunication das, IDownloadRequest request, bool bSetInDb)
|
||||
{
|
||||
if (null != request)
|
||||
{
|
||||
APILogger.Log($"WhatToDownload = Event: {request.EventNumber}, StartSample: {request.StartSample}, EndSample: {request.EndSample}");
|
||||
}
|
||||
das.WhatToDownload = request;
|
||||
if (!bSetInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingDownloadRequests(das.RecordId);
|
||||
if (null != request)
|
||||
{
|
||||
Download.DownloadRequestInsert(das.RecordId,
|
||||
request.EventNumber,
|
||||
request.DASChannelNumber,
|
||||
request.StartSample,
|
||||
request.EndSample,
|
||||
request.SamplesToSkip,
|
||||
request.StartRecordTimestampSec,
|
||||
request.TriggerTimestampSec,
|
||||
request.StartRecordTimestampNanoSec,
|
||||
request.TriggerTimestampNanoSec,
|
||||
request.PTPMasterSync);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
DataPRO/IService/Classes/Download/UARTDownloadRequest.cs
Normal file
68
DataPRO/IService/Classes/Download/UARTDownloadRequest.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using DASFactoryDb.Download;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Download;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class UARTDownloadRequest : IUARTDownloadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// From which event do we want to download data?
|
||||
/// </summary>
|
||||
public ushort EventNumber { get; set; }
|
||||
/// <summary>
|
||||
/// How much data is there?
|
||||
/// </summary>
|
||||
public ulong TotalByteCount { get; set; }
|
||||
/// <summary>
|
||||
/// Where in the data did the trigger occur?
|
||||
/// </summary>
|
||||
public ulong TriggerByteCount { get; set; }
|
||||
/// <summary>
|
||||
/// Where in the data did the fault occur?
|
||||
/// </summary>
|
||||
public ulong FaultByteCount { get; set; }
|
||||
/// <summary>
|
||||
/// When did the UART stream start?
|
||||
/// </summary>
|
||||
public ulong StartTimestamp { get; set; }
|
||||
/// <summary>
|
||||
/// When did the UART stream end?
|
||||
/// </summary>
|
||||
public ulong EndTimestamp { get; set; }
|
||||
/// <summary>
|
||||
/// What was the baud rate during recording?
|
||||
/// </summary>
|
||||
public int BaudRate { get; set; }
|
||||
|
||||
public static void SetWhatToDownload(IDASCommunication das, IUARTDownloadRequest request, bool bSetInDb)
|
||||
{
|
||||
if (!(das is IUARTDownload udas)) return;
|
||||
udas.WhatUARTToDownload = request;
|
||||
if (!bSetInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Download.ClearExistingUARTDownloadRequests(das.RecordId);
|
||||
if (null != request)
|
||||
{
|
||||
Download.UARTDownloadRequestInsert(das.RecordId,
|
||||
request.EventNumber,
|
||||
request.TotalByteCount,
|
||||
request.TriggerByteCount,
|
||||
request.FaultByteCount,
|
||||
request.StartTimestamp,
|
||||
request.EndTimestamp,
|
||||
request.BaudRate);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
186
DataPRO/IService/Classes/EID.Reader.cs
Normal file
186
DataPRO/IService/Classes/EID.Reader.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class EIDReader
|
||||
{
|
||||
/// <summary>
|
||||
/// returns true if the device supports QueryOneWireID
|
||||
/// false otherwise.
|
||||
/// this is a bit strange, since QueryOneWireID is a SLICE Command
|
||||
/// and only slice devices should support it, and only some slice
|
||||
/// devices at that, however the current code doesn't care so this is
|
||||
/// just a helper for
|
||||
/// 22296 No need to query for system ID when querying a TSR AIR device
|
||||
/// really a lot of devices probably belong in here, but I'm keeping the
|
||||
/// existing behavior for now...
|
||||
/// </summary>
|
||||
/// <param name="comm"></param>
|
||||
/// <returns>true if device supports QueryOneWireID, false otherwise</returns>
|
||||
public static bool SupportsQueryOneWireID(ICommunication comm)
|
||||
{
|
||||
switch (comm)
|
||||
{
|
||||
case EthernetTsrAir _:
|
||||
case WinUSBTsrAir _:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static EID[] Retrive_EIDs(ICommunication comm, byte DASChannelNumber, int idType)
|
||||
{
|
||||
if (!SupportsQueryOneWireID(comm)) { return null; }
|
||||
var idList = new List<EID>();
|
||||
try
|
||||
{
|
||||
var IDQuery = new QueryOneWireID(comm);
|
||||
IDQuery.StackChannel = DASChannelNumber;
|
||||
IDQuery.IdType = (QueryOneWireID.IdTypes)idType;
|
||||
IDQuery.SyncExecute();
|
||||
if (IDQuery.IDs.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < IDQuery.IDs.Count; i++)
|
||||
{
|
||||
idList.Add(new EID(HexEncoding.ToString(IDQuery.IDs[i])));
|
||||
}
|
||||
return idList.ToArray();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Failed to retrieve ids", comm.SerialNumber, ex);
|
||||
}
|
||||
// no id's
|
||||
return null;
|
||||
}
|
||||
|
||||
private static EID[] Retrive_EIDs(ICommunication comm, int moduleIndex)
|
||||
{
|
||||
if (!SupportsQueryOneWireID(comm)) { return null; }
|
||||
|
||||
var idList = new List<EID>();
|
||||
Command.TDAS.ReadSensorIDs rsi = new Command.TDAS.ReadSensorIDs(comm);
|
||||
rsi.ModuleIndex = moduleIndex;
|
||||
rsi.SyncExecute();
|
||||
if (rsi.IDs != null && rsi.IDs.Count > 0)
|
||||
{
|
||||
foreach (string id in rsi.IDs)
|
||||
{
|
||||
idList.Add(new EID(id));
|
||||
}
|
||||
|
||||
return idList.ToArray();
|
||||
}
|
||||
else { return null; }
|
||||
}
|
||||
public static IEID[] RetriveEIDs(ICommunication comm, byte DASChannelNumber, int idType)
|
||||
{
|
||||
//don't return empty set as calstation indexes it if it's not null :/
|
||||
if (!SupportsQueryOneWireID(comm)) { return null; }
|
||||
//I have to return null here rather than empty set as there's a consumer that automatically index 0 if it's not null
|
||||
//and it's in calstation code, so I want to avoid breaking that
|
||||
if (RunTestVariables.BypassEIDRead) { return null; }
|
||||
|
||||
for (int RetryCounter = 0; RetryCounter < 3; RetryCounter++)
|
||||
{
|
||||
var ids = Retrive_EIDs(comm, DASChannelNumber, idType);
|
||||
if (ids != null && ids.Length > 0)
|
||||
{
|
||||
bool bValid = true;
|
||||
foreach (var id in ids)
|
||||
{
|
||||
if (!id.IsValid())
|
||||
{
|
||||
bValid = false;
|
||||
string target = "<unknown>";
|
||||
if (comm is IDASCommunication)
|
||||
{
|
||||
target = (comm as IDASCommunication).ToString();
|
||||
}
|
||||
APILogger.LogString(string.Format("EIDReader.RetriveEIDs: Retry for {0} on channel {1}, ID({2})", target, DASChannelNumber, id.ID));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if we made it here, they're all valid
|
||||
if (bValid) { return ids; }
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
/// blank EID returned by some command queries (TDAS IDX for example)
|
||||
/// </summary>
|
||||
public const string BLANK_ID = "0000000000000000";
|
||||
/// <summary>
|
||||
/// returns true if the EID is blank
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns>true if is blank, false otherwise</returns>
|
||||
public static bool IsBlankID(string id)
|
||||
{
|
||||
return id.Equals(BLANK_ID);
|
||||
}
|
||||
public static EID[][] RetrieveEIDsG5(ICommunication comm)
|
||||
{
|
||||
if (RunTestVariables.BypassEIDRead)
|
||||
{
|
||||
return new EID[0][];
|
||||
}
|
||||
|
||||
var eids = new List<EID[]>();
|
||||
try
|
||||
{
|
||||
var idx = new Command.TDAS.RackIDX(comm);
|
||||
idx.SyncExecute();
|
||||
foreach (var channelIDs in idx.IDs)
|
||||
{
|
||||
var ids = new List<EID>();
|
||||
foreach (var channelID in channelIDs)
|
||||
{
|
||||
if (IsBlankID(channelID)) { ids.Add(new EID()); }
|
||||
else { ids.Add(new EID(channelID)); }
|
||||
}
|
||||
eids.Add(ids.ToArray());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("RetrieveEIDsG5 failed", ex);
|
||||
}
|
||||
return eids.ToArray();
|
||||
}
|
||||
public static EID[] RetriveEIDs(ICommunication comm, int moduleIndex)
|
||||
{
|
||||
if (!SupportsQueryOneWireID(comm)) { return null; }
|
||||
for (int RetryCounter = 0; RetryCounter < 3; RetryCounter++)
|
||||
{
|
||||
var ids = Retrive_EIDs(comm, moduleIndex);
|
||||
if (null != ids && ids.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < ids.Length; i++)
|
||||
{
|
||||
if (!ids[i].IsValid())
|
||||
{
|
||||
string target = "<unknown>";
|
||||
if (comm is IDASCommunication)
|
||||
{
|
||||
target = (comm as IDASCommunication).ToString();
|
||||
}
|
||||
APILogger.LogString(string.Format("EIDReader.RetreiveEIDS: ID invalid for {0} on module {1}, ID({2})", target, moduleIndex, ids[i].ID));
|
||||
break; ;
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
103
DataPRO/IService/Classes/EID.cs
Normal file
103
DataPRO/IService/Classes/EID.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A class to represent a sensor Electronic ID.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class EID : IEID, IComparable<EID>, IComparable<string>
|
||||
{
|
||||
static readonly byte[] CRCTable = { 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
|
||||
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
|
||||
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
|
||||
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
|
||||
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
|
||||
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
|
||||
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
|
||||
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
|
||||
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
|
||||
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
|
||||
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
|
||||
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
|
||||
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
|
||||
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
|
||||
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
|
||||
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
|
||||
|
||||
public string ID { get; set; }
|
||||
public byte[] Blob { get; set; }
|
||||
|
||||
public int CompareTo(EID eid)
|
||||
{
|
||||
return ID.ToUpper().CompareTo(eid.ID.ToUpper());
|
||||
}
|
||||
|
||||
public int CompareTo(string eidStr)
|
||||
{
|
||||
return ID.ToUpper().CompareTo(eidStr.ToUpper());
|
||||
}
|
||||
|
||||
public EID()
|
||||
{
|
||||
ID = "";
|
||||
Blob = null;
|
||||
}
|
||||
|
||||
public EID(string _id)
|
||||
{
|
||||
ID = _id;
|
||||
Blob = null;
|
||||
}
|
||||
|
||||
public EID(string _id, byte[] _blob)
|
||||
{
|
||||
ID = _id;
|
||||
Blob = _blob;
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
// it can't be empty
|
||||
if (string.IsNullOrEmpty(ID))
|
||||
return false;
|
||||
|
||||
// it must be 16 characters
|
||||
if (ID.Length != 16)
|
||||
return false;
|
||||
|
||||
// it can't be all 0's
|
||||
if (EIDReader.IsBlankID(ID)) { return false; }
|
||||
|
||||
// it must be in HEX
|
||||
if (!HexEncoding.InHexFormat(ID))
|
||||
return false;
|
||||
|
||||
// extract the CRC
|
||||
int garbage;
|
||||
var hex = HexEncoding.GetBytes(ID.Substring(0, 2), out garbage);
|
||||
var crc = hex[0];
|
||||
|
||||
// calculate the CRC
|
||||
hex = HexEncoding.GetBytes(ID.Substring(2), out garbage);
|
||||
var idCRC = ComputeCRC8(hex);
|
||||
|
||||
// is the CRC good?
|
||||
return idCRC == crc;
|
||||
}
|
||||
|
||||
private byte ComputeCRC8(byte[] input)
|
||||
{
|
||||
byte crc = 0;
|
||||
for (int idx = input.Length - 1; idx >= 0; idx--)
|
||||
{
|
||||
crc = CRCTable[crc ^ input[idx]];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
DataPRO/IService/Classes/Exceptions.cs
Normal file
46
DataPRO/IService/Classes/Exceptions.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// This exception gets thrown when you call a service and it's already busy.
|
||||
/// </summary>
|
||||
public class BusyException : Exception
|
||||
{
|
||||
public BusyException(string msg) : base(msg) { }
|
||||
}
|
||||
|
||||
public class TriggerShortedException : Exception
|
||||
{
|
||||
public TriggerShortedException(String msg) : base(msg) { }
|
||||
}
|
||||
public class StartShortedException : Exception
|
||||
{
|
||||
public StartShortedException(String msg) : base(msg) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to access a channel's diagnostic information
|
||||
/// when said information isn't available (which can happen, if diagnostics has
|
||||
/// not yet been run on this particular channel this session).
|
||||
/// </summary>
|
||||
public class NoDiagnosticsAvailable : ApplicationException
|
||||
{
|
||||
public NoDiagnosticsAvailable() { }
|
||||
public NoDiagnosticsAvailable(string msg) : base(msg) { }
|
||||
public NoDiagnosticsAvailable(string msg, Exception ex) : base(msg, ex) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Representation of an attempt to access a channel's diagnostic information
|
||||
/// that results in several different diagnostic results (which should never happen,
|
||||
/// but is theoretically supported by the list-y nature of the generic culling
|
||||
/// code).
|
||||
/// </summary>
|
||||
public class TooManyDiagnosticsAvailable : ApplicationException
|
||||
{
|
||||
public TooManyDiagnosticsAvailable() { }
|
||||
public TooManyDiagnosticsAvailable(string msg) : base(msg) { }
|
||||
public TooManyDiagnosticsAvailable(string msg, Exception ex) : base(msg, ex) { }
|
||||
}
|
||||
}
|
||||
25
DataPRO/IService/Classes/FlashEraseStatus.cs
Normal file
25
DataPRO/IService/Classes/FlashEraseStatus.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// While the unit is waiting for a flash erase to complete, an object of this type in the
|
||||
/// corresponding <see cref="IDASCommunication" /> can be updated to reflect the progress and
|
||||
/// any errors for the current flash erase.
|
||||
/// </summary>
|
||||
public class FlashEraseStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// The last error that occurred during flash erase. This could be
|
||||
/// DFConstantsAndEnums.CommandStatus .StatusNoError if everything is okay.
|
||||
/// </summary>
|
||||
public DFConstantsAndEnums.CommandStatus LastError { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How far along is the current flash erase?
|
||||
/// </summary>
|
||||
public float PercentComplete { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
4570
DataPRO/IService/Classes/GenericServices.cs
Normal file
4570
DataPRO/IService/Classes/GenericServices.cs
Normal file
File diff suppressed because it is too large
Load Diff
385
DataPRO/IService/Classes/InfoResult.cs
Normal file
385
DataPRO/IService/Classes/InfoResult.cs
Normal file
@@ -0,0 +1,385 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using DASFactoryDb;
|
||||
using DASFactoryDb.Config;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// An instance of InfoResult is populated and filled when a DASFactory object discovers a DAS.
|
||||
/// It contains information about the DAS hardware as well as the coinciding modules and channels.
|
||||
/// It also has some functions to help translate between different numbering systems used
|
||||
/// during DAS communications, such as Module numbers, Channel numbers and DASChannel numbers.
|
||||
/// </summary>
|
||||
public class InfoResult : IInfoResult
|
||||
{
|
||||
public string MACAddress { get; set; }
|
||||
/// <summary>
|
||||
/// Describes one module in this DAS.
|
||||
/// </summary>
|
||||
public class Module : IInfoResultModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Serial number of this module
|
||||
/// </summary>
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Firmware version in this module
|
||||
/// </summary>
|
||||
public string FirmwareVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// who does this module belong to?
|
||||
/// </summary>
|
||||
public InfoResult OwningInfoResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of this Module as it would be indexed in an array of Modules.
|
||||
/// </summary>
|
||||
public int ModuleArrayIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many channels are connected to this Module.
|
||||
/// </summary>
|
||||
public uint NumberOfChannels { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What sample rates does it support (in samples per second).
|
||||
/// </summary>
|
||||
public uint[] SupportedSampleRates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An associative list (Dictionary) of sample rates and corresponding
|
||||
/// Anti-Aliasing filter frequencies.
|
||||
/// </summary>
|
||||
public Dictionary<uint, float> SampleRate2AAFrequency { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many bytes of sample storage is available in this module? This is null
|
||||
/// if it's specified per DAS instead.
|
||||
/// </summary>
|
||||
public UInt64? MaxEventStorageSpaceInBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many bytes are stored for all channels at each sample interval? This is
|
||||
/// null if it's specified per DAS instead.
|
||||
/// </summary>
|
||||
public uint? NumberOfBytesPerSampleClock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many samples can you record in this module?
|
||||
/// </summary>
|
||||
public double MaxRecordingSamples { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.DateTime"/> of this module's last calibration.
|
||||
/// </summary>
|
||||
public DateTime? CalibrationDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if a TDAS rack is armed and doesn't respond to some queries.
|
||||
/// </summary>
|
||||
public bool RackIsUnreadable { get; set; }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// What type of module is this?
|
||||
/// </summary>
|
||||
public DFConstantsAndEnums.ModuleType TypeOfModule { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What recording modes does this Module support.
|
||||
/// </summary>
|
||||
public DFConstantsAndEnums.RecordingMode[] SupportedModes { get; set; }
|
||||
|
||||
public bool IsProgrammable { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An array of the modules in this DAS.
|
||||
/// </summary>
|
||||
public IInfoResultModule[] Modules { get; set; }
|
||||
|
||||
public List<Common.Classes.Hardware.ExternalTilt> ActiveExternalTilts { get; set; } = new List<Common.Classes.Hardware.ExternalTilt>();
|
||||
|
||||
[XmlIgnore]
|
||||
public IDASCommunication OwningDAS { get; set; }
|
||||
|
||||
public uint MaxNumberOfModules { get; set; }
|
||||
public InfoResult()
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// How many bytes of sample storage is available in this DAS? This is null if
|
||||
/// it's specified per module instead.
|
||||
/// </summary>
|
||||
public UInt64? MaxEventStorageSpaceInBytes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many bytes are stored for all channels at each sample interval? This is
|
||||
/// null if it's specified per module instead.
|
||||
/// </summary>
|
||||
public uint? NumberOfBytesPerSampleClock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FB15353 Is this device hardware configured for streaming only?
|
||||
/// null if device doesn't support a streaming-only configuration
|
||||
/// </summary>
|
||||
public bool? DeviceStreamingOnly { get; set; }
|
||||
|
||||
// temporary constant
|
||||
public int NumberOfBridgeChannels { get; set; } = 3;
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the battery.
|
||||
/// </summary>
|
||||
public IEID BatteryID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// TRUE if a battery is present in the hardware unit.
|
||||
/// </summary>
|
||||
public bool HasBattery
|
||||
{
|
||||
get
|
||||
{
|
||||
if (BatteryID == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(BatteryID.ID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (EIDReader.IsBlankID(BatteryID.ID)) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public byte MapDASChannelNumber2RealtimeChannelNumber(int channelNumber)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (Modules[0].TypeOfModule)
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.G5Digital:
|
||||
// This case is never hit because of the use of Modules.First(), but left for clarity.
|
||||
return Convert.ToByte(32);
|
||||
case DFConstantsAndEnums.ModuleType.G5Analog:
|
||||
return (byte)channelNumber;
|
||||
case DFConstantsAndEnums.ModuleType.ProDIM:
|
||||
return Convert.ToByte(channelNumber);
|
||||
//return MapDASChannelNumber2ModuleChannelNumber(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.ProSIM:
|
||||
return Convert.ToByte(channelNumber);
|
||||
//return MapDASChannelNumber2ModuleChannelNumber(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.SLICEPro_TOM:
|
||||
return Convert.ToByte(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.ProTOM:
|
||||
return Convert.ToByte(channelNumber);
|
||||
//return MapDASChannelNumber2ModuleChannelNumber(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.RibeyeLED:
|
||||
return Convert.ToByte(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.SliceARS:
|
||||
return Convert.ToByte(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.SliceBridge:
|
||||
return Convert.ToByte(channelNumber);
|
||||
case DFConstantsAndEnums.ModuleType.SLICEIEPE:
|
||||
return Convert.ToByte(channelNumber);
|
||||
default:
|
||||
return Convert.ToByte(channelNumber);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("MapDASChannelNumber2RealtimeChannelNumber failed", ex); }
|
||||
return Convert.ToByte(channelNumber);
|
||||
}
|
||||
/// <summary>
|
||||
/// Convert a DASChannel number (0..29) to a module array index (0..9).
|
||||
/// A DASChannel number is a channel's identifier global within this DAS.
|
||||
/// A Module array index is a Module identifier as it would be indexed in an array.
|
||||
/// </summary>
|
||||
/// <param name="channelNumber">The DAS channel number to convert</param>
|
||||
/// <returns>The module array index</returns>
|
||||
public byte MapDASChannelNumber2ModuleArrayIndex(int channelNumber)
|
||||
{
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
int numChannels = Convert.ToInt32(module.NumberOfChannels);
|
||||
if (channelNumber >= numChannels) { channelNumber -= numChannels; }
|
||||
else { return (byte)module.ModuleArrayIndex; }
|
||||
}
|
||||
return (byte)(Modules.Length - 1);
|
||||
//return (byte)(channelNumber / NumberOfBridgeChannels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a DAS channel number (0..29) to a module device id (1..10)
|
||||
/// A DASChannel number is a channel's identifier global within this DAS.
|
||||
/// A Module deviceID is an identifier for the corresponding channel that starts at 1 for the first Module.
|
||||
/// </summary>
|
||||
/// <param name="channelNumber">The DAS channel number to convert</param>
|
||||
/// <returns>The module device id</returns>
|
||||
public byte MapDASChannelNumber2ModuleDeviceID(int channelNumber)
|
||||
{
|
||||
return (byte)(channelNumber / NumberOfBridgeChannels + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a DAS channel number (0..29) to a module channel number (0..2)
|
||||
/// A DASChannel number is a channel's identifier global within this DAS.
|
||||
/// A moduleChannel number is the channel's identifier relative only to it's parent Module.
|
||||
/// </summary>
|
||||
/// <param name="channelNumber">The DAS channel number to convert</param>
|
||||
/// <returns>The channel number within the module</returns>
|
||||
public byte MapDASChannelNumber2ModuleChannelNumber(int channelNumber)
|
||||
{
|
||||
if (OwningDAS is EthernetTDAS)
|
||||
{
|
||||
var ch = Convert.ToUInt32(channelNumber);
|
||||
foreach (var m in Modules)
|
||||
{
|
||||
if (m.NumberOfChannels <= ch)
|
||||
{
|
||||
ch -= m.NumberOfChannels;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (byte)ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (byte)(channelNumber % NumberOfBridgeChannels);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a module array index (0..9) and a module channel number (0..2) to a DAS channel number (0..29)
|
||||
/// A Module array index is a Module identifier as it would be indexed in an array.
|
||||
/// A moduleChannel number is the channel's identifier relative only to it's parent Module.
|
||||
/// A DASChannel number is a channel's identifier global within this DAS.
|
||||
/// </summary>
|
||||
/// <param name="moduleArrayIdx">The module array index (0..9)</param>
|
||||
/// <param name="channelNumber">The module channel number (0..2)</param>
|
||||
/// <returns>The DAS channel number within the DAS (0..29)</returns>
|
||||
public byte MapModuleArrayIndexAndChannelNum2DASChannel(int moduleArrayIdx, int channelNumber)
|
||||
{
|
||||
uint channel = 0;
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
//30429 Invalidate/fail sooner than Arm step if DAS doesn't have streaming capability/channel (TSR AIR may or may not)
|
||||
if (module == null) { break; }
|
||||
if (module.ModuleArrayIndex < moduleArrayIdx) { channel += module.NumberOfChannels; }
|
||||
else if (module.ModuleArrayIndex > moduleArrayIdx) { break; }
|
||||
else
|
||||
{
|
||||
channel += Convert.ToUInt32(channelNumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (byte)(channel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.DateTime"/> returns the datetime of the DAS (or the oldest module's calibration)
|
||||
/// returns 1970-01-01 is considering invalid/NA
|
||||
/// </summary>
|
||||
private DateTime? _calibrationDate;
|
||||
public DateTime? CalibrationDate
|
||||
{
|
||||
get
|
||||
{
|
||||
var dCalDate = new DateTime(1970, 1, 1);
|
||||
if (null != _calibrationDate)
|
||||
{
|
||||
dCalDate = (DateTime)_calibrationDate;
|
||||
}
|
||||
if (null != Modules)
|
||||
{
|
||||
foreach (var module in Modules)
|
||||
{
|
||||
//30429 Invalidate/fail sooner than Arm step if DAS doesn't have streaming capability/channel (TSR AIR may or may not)
|
||||
if (module == null) { continue; }
|
||||
if (module.SerialNumber.ToLower().Contains("empty")) { continue; }
|
||||
if (null != module.CalibrationDate)
|
||||
{
|
||||
var mCalDate = (DateTime)module.CalibrationDate;
|
||||
if (mCalDate < dCalDate || dCalDate.Year == 1970) { dCalDate = mCalDate; }
|
||||
}
|
||||
}
|
||||
}
|
||||
return dCalDate;
|
||||
}
|
||||
set => _calibrationDate = value;
|
||||
}
|
||||
|
||||
public static void SetDASInfo(IDASCommunication das)
|
||||
{
|
||||
if (!DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
if (das.RecordId < 0) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
Config.DASInfoClear(das.RecordId);
|
||||
InsertDASInfo(das, das.DASInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
public static void SetDASInfo(IDASCommunication das, IInfoResult dasInfo, bool bSetInDb = true)
|
||||
{
|
||||
das.DASInfo = dasInfo;
|
||||
if (!bSetInDb || !DASFactoryDb.DbWrapper.Connected) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
if (das.RecordId < 0)
|
||||
{
|
||||
das.RecordId = DASFactoryDb.DbWrapper.GetDeviceId(das.SerialNumber);
|
||||
if (das.RecordId < 0)
|
||||
{
|
||||
var id = DASFactoryDb.DAS.DAS.InsertDASSimple(das.SerialNumber, das.FirmwareVersion,
|
||||
((ICommunication)das).Transport.ConnectString);
|
||||
das.RecordId = id;
|
||||
}
|
||||
}
|
||||
|
||||
Config.DASInfoClear(das.RecordId);
|
||||
InsertDASInfo(das, dasInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertDASInfo(IDASCommunication das, IInfoResult dasInfo)
|
||||
{
|
||||
if (!DbWrapper.Connected) { return; }
|
||||
if (null != dasInfo && das.RecordId > 0)
|
||||
{
|
||||
var batteryId = string.Empty;
|
||||
if (null != dasInfo.BatteryID)
|
||||
{
|
||||
batteryId = dasInfo.BatteryID.ID;
|
||||
}
|
||||
Config.DASInfoInsert(das.RecordId,
|
||||
dasInfo.MACAddress,
|
||||
das.RecordId,
|
||||
dasInfo.MaxNumberOfModules,
|
||||
dasInfo.MaxEventStorageSpaceInBytes,
|
||||
dasInfo.NumberOfBytesPerSampleClock,
|
||||
batteryId,
|
||||
dasInfo.CalibrationDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// allows a input range in mV to send to firmware based on a gain
|
||||
/// this is a right now just the middle between the given gain and the next gain, however
|
||||
/// we can control this a bit more in the future if we wish.
|
||||
/// we don't send directly the input range based on the gain because calibration factors could affect
|
||||
/// what range is actually achieved at each gain step
|
||||
/// but we want to make sure we don't change gain steps [so we can avoid certain gains]
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
public class FirmwareInputRangeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// input range to send to firmware for the given gain
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetFirmwareInputRangemV(object o)
|
||||
{
|
||||
if (o == null) return 0D;
|
||||
var mi = o.GetType().GetMember(o.ToString());
|
||||
if (mi.Length <= 0) return 0D;
|
||||
var attr = GetCustomAttribute(mi[0], typeof(FirmwareInputRangeAttribute)) as FirmwareInputRangeAttribute;
|
||||
return attr?._firmwareInputRangeAttribute ?? 0D;
|
||||
}
|
||||
|
||||
private readonly double _firmwareInputRangeAttribute;
|
||||
public FirmwareInputRangeAttribute(double firmwareInputRangemV)
|
||||
{
|
||||
_firmwareInputRangeAttribute = firmwareInputRangemV;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// This attribute is used to control whether a gain is available to unmodified gen 3 SPS
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// the gain should still be available for modified SPS
|
||||
/// this attribute is optional, it is assumed to be available unless explicitly marked as
|
||||
/// unavailable
|
||||
/// </summary>
|
||||
public class GainAvailableUnmodifiedAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// returns whether gain is available to unmodified SPS gen 3 or not
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsGainAvailableToUnmodified(object o)
|
||||
{
|
||||
if (o == null) return true;
|
||||
var mi = o.GetType().GetMember(o.ToString());
|
||||
if (mi.Length <= 0) return true;
|
||||
return !(GetCustomAttribute(mi[0], typeof(GainAvailableUnmodifiedAttribute)) is GainAvailableUnmodifiedAttribute attr) || attr._bAvailable;
|
||||
}
|
||||
|
||||
private readonly bool _bAvailable;
|
||||
public GainAvailableUnmodifiedAttribute(bool available)
|
||||
{
|
||||
_bAvailable = available;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// this attribute controls whether a gain is disabled or not
|
||||
/// this was done for
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// to prevent the higher range gains which were considered just not useful
|
||||
/// this attribute is optional, it is assume the gain is not disabled
|
||||
/// unless it's explicitly marked as disabled
|
||||
/// </summary>
|
||||
public class GainDisabledAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// returns whether the gain is disabled or not
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsGainDisabled(object o)
|
||||
{
|
||||
if (o == null) return false;
|
||||
var mi = o.GetType().GetMember(o.ToString());
|
||||
if (mi.Length <= 0) return false;
|
||||
return GetCustomAttribute(mi[0], typeof(GainDisabledAttribute)) is GainDisabledAttribute attr && attr._bDisabled;
|
||||
}
|
||||
|
||||
private readonly bool _bDisabled;
|
||||
public GainDisabledAttribute(bool disabled)
|
||||
{
|
||||
_bDisabled = disabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// this attribute allows us to associate a max input range in mV for a gain
|
||||
/// note that this can be computed using the gain itself and the input range
|
||||
/// but this allows us to more tightly control things (say by using 2450 instead of 2500 for full range or something similar)
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
public class MaxInputRangeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// returns the max input range in mV for gain
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetMaxInputRangemV(object o)
|
||||
{
|
||||
if (o == null) return 0D;
|
||||
var mi = o.GetType().GetMember(o.ToString());
|
||||
if (mi.Length <= 0) return 0D;
|
||||
return GetCustomAttribute(mi[0], typeof(MaxInputRangeAttribute)) is MaxInputRangeAttribute attr ? attr._maximumInputRangemV : 0D;
|
||||
}
|
||||
|
||||
private readonly double _maximumInputRangemV;
|
||||
public MaxInputRangeAttribute(double maxInputRangemV)
|
||||
{
|
||||
_maximumInputRangemV = maxInputRangemV;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// this attribute controls the minimum input range for a gain
|
||||
/// note that we could calculate this, but this allows us some flexibility
|
||||
/// in real life there are calibration and other factors that can affect what actually
|
||||
/// is achievable at a given gain step, so this minimum input could be a theoretical one
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
public class MinInputRangeAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// returns the minimum input range for a gain
|
||||
/// http://fogbugz/fogbugz/default.asp?10080
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public static double GetMinInputRangemV(object o)
|
||||
{
|
||||
if (o == null) return 0D;
|
||||
var mi = o.GetType().GetMember(o.ToString());
|
||||
if (mi.Length <= 0) return 0D;
|
||||
return GetCustomAttribute(mi[0], typeof(MinInputRangeAttribute)) is MinInputRangeAttribute attr ? attr._minimumInputRangemV : 0D;
|
||||
}
|
||||
|
||||
private readonly double _minimumInputRangemV;
|
||||
public MinInputRangeAttribute(double minInputRangemV)
|
||||
{
|
||||
_minimumInputRangemV = minInputRangemV;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
DataPRO/IService/Classes/ModuleDiagnosticResult.cs
Normal file
23
DataPRO/IService/Classes/ModuleDiagnosticResult.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// This class holds the results from one module's diagnostics.
|
||||
/// </summary>
|
||||
public class ModuleDiagnosticsResult : IModuleDiagnosticsResult
|
||||
{
|
||||
/// <summary>
|
||||
/// from which this diagnostics is returning.
|
||||
/// </summary>
|
||||
public float TemperatureLocation1Pre { get; set; }
|
||||
public float TemperatureLocation2Pre { get; set; }
|
||||
public float TemperatureLocation3Pre { get; set; }
|
||||
public float TemperatureLocation4Pre { get; set; }
|
||||
public float TemperatureLocation1Post { get; set; }
|
||||
public float TemperatureLocation2Post { get; set; }
|
||||
public float TemperatureLocation3Post { get; set; }
|
||||
public float TemperatureLocation4Post { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
20
DataPRO/IService/Classes/NewData.cs
Normal file
20
DataPRO/IService/Classes/NewData.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class NewDataData
|
||||
{
|
||||
public short[][][] datas { get; set; }
|
||||
public ulong[] SampleNumbers { get; set; }
|
||||
|
||||
public ulong[] TimeStamps { get; set; }
|
||||
|
||||
public ulong[] SequenceNumbers { get; set; }
|
||||
public NewDataData(short[][][] data, ulong[] sns, ulong[] timeStamps, ulong[] sequenceNumbers)
|
||||
{
|
||||
datas = data;
|
||||
SampleNumbers = sns;
|
||||
TimeStamps = timeStamps;
|
||||
SequenceNumbers = sequenceNumbers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Threading;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICEPowerProInputReader : SLICEBaseInputReader
|
||||
{
|
||||
private readonly ICommunication _comm;
|
||||
|
||||
public SLICEPowerProInputReader(ICommunication comm) : base(comm)
|
||||
{
|
||||
_comm = comm;
|
||||
}
|
||||
|
||||
public override double InputMilliVolts
|
||||
{
|
||||
get
|
||||
{
|
||||
var measure = new MeasurePowerProDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasurePowerProDiagnosticChannel.PowerProDiagnosticChannelList.InputVoltage_A;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement * 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
public override double TemperatureC
|
||||
{
|
||||
get
|
||||
{
|
||||
var measure = new MeasurePowerProDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasurePowerProDiagnosticChannel.PowerProDiagnosticChannelList.TemperatureC;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement;
|
||||
}
|
||||
}
|
||||
|
||||
public override double DirectBackupMilliVolts
|
||||
{
|
||||
get
|
||||
{
|
||||
var measure = new MeasurePowerProDiagnosticChannel(_comm);
|
||||
measure.Channel = MeasurePowerProDiagnosticChannel.PowerProDiagnosticChannelList.BatteryVoltage;
|
||||
measure.DeviceGroup = 0;
|
||||
measure.DeviceID = 0;
|
||||
measure.SyncExecute();
|
||||
return measure.Measurement * 1000.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2624
DataPRO/IService/Classes/Ribeye Service.cs
Normal file
2624
DataPRO/IService/Classes/Ribeye Service.cs
Normal file
File diff suppressed because it is too large
Load Diff
22
DataPRO/IService/Classes/SLICE/DASConfigurationEventArg.cs
Normal file
22
DataPRO/IService/Classes/SLICE/DASConfigurationEventArg.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// this class handles the data passed to consumers during a DASConfigurationEvent
|
||||
/// 17872 Use DASConfig XMLs on disk when performing an emergency download with DAS that have blank filestore(s)
|
||||
/// </summary>
|
||||
public class DASConfigurationArg : IDASConfigurationArg
|
||||
{
|
||||
public IDASCommunication DAS { get; private set; }
|
||||
public bool BlankConfigurationRead { get; private set; }
|
||||
public bool ConfigurationFailedValidation { get; private set; }
|
||||
|
||||
public DASConfigurationArg(IDASCommunication das, bool blankRead, bool failedValidation)
|
||||
{
|
||||
DAS = das;
|
||||
BlankConfigurationRead = blankRead;
|
||||
ConfigurationFailedValidation = failedValidation;
|
||||
}
|
||||
}
|
||||
}
|
||||
898
DataPRO/IService/Classes/SLICE/PowerPRO.cs
Normal file
898
DataPRO/IService/Classes/SLICE/PowerPRO.cs
Normal file
@@ -0,0 +1,898 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using DTS.Common.DASResource;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using Arm = DTS.DASLib.Command.SLICE.Arm;
|
||||
using Disarm = DTS.DASLib.Command.SLICE.Disarm;
|
||||
using EnableFaultChecking = DTS.DASLib.Command.SLICE.EnableFaultChecking;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using System.Text;
|
||||
using DTS.DASLib.Service.Classes.SLICE;
|
||||
using System.Net.NetworkInformation;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.Communication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.StatusAndProgressBar;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.DASLib.Command.SLICE.DownloadCommands;
|
||||
using DTS.DASLib.Command.SLICEDB;
|
||||
using DTS.Common.Constant.DASSpecific;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DisableFaultChecking = DTS.DASLib.Command.SLICE.DisableFaultChecking;
|
||||
using DTS.Common;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class PowerPro<T> : PowerPro_Base<T>, //IDASReconfigure,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions
|
||||
where T : IConnection, new()
|
||||
{
|
||||
protected override void AsyncConfigure(object configAsyncInfo)
|
||||
{
|
||||
var info = (SliceConfigServiceAsyncInfo)configAsyncInfo;
|
||||
|
||||
if (ConfigData != null && ConfigData.Modules.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
var saa = new SetArmAttribute(this);
|
||||
saa.SetValue(AttributeTypes.ArmAndEventAttributes.SampleRate, ConfigData.Modules[0].SampleRateHz, true);
|
||||
saa.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("failed to configure", SerialNumber, ex);
|
||||
info.Error(ex.Message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
base.AsyncConfigure(configAsyncInfo);
|
||||
}
|
||||
public override string ConvertInputVoltage2BatteryCharging(double inputVoltage)
|
||||
{
|
||||
bool isCharging;
|
||||
var SwitchQuery = new QuerySwitchImmediate(this)
|
||||
{
|
||||
DeviceID = 0,
|
||||
Switch = (byte)Switches.PowerProSwitches.ChargePower
|
||||
};
|
||||
try
|
||||
{
|
||||
SwitchQuery.SyncExecute();
|
||||
if (1 == SwitchQuery.Setting)
|
||||
{
|
||||
isCharging = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isCharging = false;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
isCharging = false;
|
||||
}
|
||||
|
||||
// If we are charging
|
||||
if (isCharging)
|
||||
{
|
||||
return Resources.Charging;
|
||||
}
|
||||
// If we aren't charging and input is valid
|
||||
else if (inputVoltage > MinimumValidInputVoltage && inputVoltage < MaximumValidInputVoltage)
|
||||
{
|
||||
return Resources.NotCharging;
|
||||
}
|
||||
// If we're off input voltage and not charging
|
||||
else
|
||||
{
|
||||
return Resources.Discharging;
|
||||
}
|
||||
}
|
||||
public override bool? ChargingEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
/// <summary>
|
||||
/// returns true if the devices is an ethernet distributor
|
||||
/// for now that is SLICEDb, SLICE ECM, SLICE6DB
|
||||
/// these are devices that we talk through, but not to for device communication
|
||||
/// a rack we communicate with the modules by talking to the rack, so it's not a distributor
|
||||
/// </summary>
|
||||
/// <returns>returns true if the devices is an ethernet distributor</returns>
|
||||
public override bool IsEthernetDistributor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public override bool IsSlice6Distributor()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override bool IsBattery()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public override bool IsTSRAIR()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public bool IsSlice6Air()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public bool IsSlice6AirTc()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override bool IsScheduleEventCountSupported()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void IConfigurationActions.SetFirstUseDate(DateTime firstUseDate, ServiceCallback callback,
|
||||
object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
info.Error("Not supported");
|
||||
}
|
||||
/// <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>
|
||||
public void QueryDownloadedStatus(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
/// <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);
|
||||
}
|
||||
public void VerifyConfig(bool DoStrictCheck, ErrorCallback failedChallengeFunc)
|
||||
{
|
||||
if (!DoStrictCheck) return;
|
||||
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines)) return;
|
||||
var query = new InitializeHardwareLines(this)
|
||||
{
|
||||
CheckStartForShort = true,
|
||||
CheckTriggerForShort = true
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
query.SyncExecute();
|
||||
|
||||
if (query.StartRecordShorted && !IgnoreShortedStart)
|
||||
{
|
||||
//Start Shorted
|
||||
throw new StartShortedException(string.Format(Strings.StartRecordShorted, SerialNumber));
|
||||
}
|
||||
if (query.TriggerInputShorted && !IgnoreShortedTrigger)
|
||||
{
|
||||
//Trigger Shorted
|
||||
throw new TriggerShortedException(string.Format(Strings.TriggerShorted, SerialNumber));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InitializeHardwareLines.Log(ex, query);
|
||||
}
|
||||
}
|
||||
void IArmActions.ReArm(ServiceCallback callback, object userData, bool autoArm, bool arm, bool repeatEnable)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
info.Error("NotSupported");
|
||||
}
|
||||
public void PreparedArmNow(ServiceCallback callback, object userData, Guid eventGuid, int
|
||||
armNowTimeout, bool testingMode,
|
||||
int maxNumberEvents, bool SysMode)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MeasurePowerProAllDiagnosticChannel))
|
||||
{
|
||||
var mppadc = new MeasurePowerProAllDiagnosticChannel(this);
|
||||
mppadc.SyncExecute(); // Just Log it for now
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to Measure All Diagnostic Channel", ex); }
|
||||
|
||||
var saa = new SetArmAttribute(this);
|
||||
var postTriggerSamples = Convert.ToUInt64(ConfigData.Modules[0].PostTriggerSeconds *
|
||||
ConfigData.Modules[0].SampleRateHz);
|
||||
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, postTriggerSamples, true);
|
||||
saa.SyncExecute();
|
||||
|
||||
saa = new SetArmAttribute(this);
|
||||
var preTriggerSamples = 0UL;
|
||||
if (ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBuffer ||
|
||||
ConfigData.Modules[0].RecordingMode == DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART)
|
||||
{
|
||||
preTriggerSamples =
|
||||
Convert.ToUInt64(Math.Abs(ConfigData.Modules[0].PreTriggerSeconds *
|
||||
ConfigData.Modules[0].SampleRateHz));
|
||||
}
|
||||
saa.SetValue(AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, preTriggerSamples, true);
|
||||
saa.SyncExecute();
|
||||
|
||||
SetArmMode(ConfigData.Modules[0].RecordingMode);
|
||||
|
||||
try
|
||||
{
|
||||
var arm = new Arm(this);
|
||||
arm.SyncExecute();
|
||||
//17812 DataPRO does not issue EnableFaultChecking when running with POWER PRO and a single DAS
|
||||
//UI code was setting this for non ethernet distributors
|
||||
DASArmStatus.IsArmed = true;
|
||||
SetDASArmStatus();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
info.Success(); //TEMP until PowerPro Event line is not shorted
|
||||
return;
|
||||
}
|
||||
|
||||
info.Success();
|
||||
}
|
||||
|
||||
/// <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 PowerProAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform diagnostics based on the property ChannelDiagnostics and stuff the
|
||||
/// result in ChannelDiagnosticsResults
|
||||
/// </summary>
|
||||
/// <param name="callback">The function to call with information</param>
|
||||
/// <param name="userData">Whatever you want to pass along</param>
|
||||
public void DiagnosAndGetResults(int EventNumber,
|
||||
PrePostResults WhichResult,
|
||||
ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
DiagnosticsHasBeenRun = true;
|
||||
BaseInput = new BaseInputValues();
|
||||
GetBaseInputs(true);
|
||||
ClearChannelDiagnosticsResults(false);
|
||||
info.Success();
|
||||
}
|
||||
public override double MaximumValidInputVoltage { get; set; } = 26D;
|
||||
public void PerformArmChecks(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("PowerPro.PerformArmChecks", new WaitCallback(AsyncPerformArmChecks), info);
|
||||
}
|
||||
|
||||
private void AsyncPerformArmChecks(object o)
|
||||
{
|
||||
var info = o as PowerProAsyncInfo;
|
||||
var dasResults = new ArmCheckResults();
|
||||
info.Progress(25);
|
||||
if (null != ArmCheckActions)
|
||||
{
|
||||
GetBaseInputs(true);
|
||||
if (ArmCheckActions.PerformInputVoltageCheck || ArmCheckActions.PerformBatteryVoltageCheck)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MeasurePowerProAllDiagnosticChannel))
|
||||
{
|
||||
var mppadc = new MeasurePowerProAllDiagnosticChannel(this);
|
||||
mppadc.SyncExecute(); // Just Log it for now
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to Measure All Diagnostic Channel", ex); }
|
||||
}
|
||||
if (ArmCheckActions.PerformBatteryVoltageCheck)
|
||||
{
|
||||
//if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
|
||||
//{
|
||||
try
|
||||
{
|
||||
dasResults.BatteryVoltage = new double?[1];
|
||||
dasResults.BatteryVoltage[0] = BaseInput.BatteryMilliVolts / 1000D;
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to get Battery voltage", ex); }
|
||||
//}
|
||||
}
|
||||
info.Progress(33);
|
||||
if (ArmCheckActions.PerformInputVoltageCheck)
|
||||
{
|
||||
//if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics))
|
||||
//{
|
||||
try
|
||||
{
|
||||
dasResults.InputVoltage = BaseInput.InputMilliVolts / 1000D;
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Failed to get Input voltage", ex); }
|
||||
//}
|
||||
}
|
||||
info.Progress(66);
|
||||
if (ArmCheckActions.PerformSquibResistanceCheck)
|
||||
{
|
||||
// No Squibs in PowerPro
|
||||
}
|
||||
if (ArmCheckActions.PerformEventLineCheck)
|
||||
{
|
||||
((ITriggerCheckActions)this).DoTriggerCheckSync();
|
||||
}
|
||||
if (ArmCheckActions.PerformSensorIdCheck)
|
||||
{
|
||||
//not needed
|
||||
}
|
||||
if (ArmCheckActions.PerformTemperatureCheck)
|
||||
{
|
||||
//// Temperature
|
||||
//dasResults.TemperaturesPre = new float[] { float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN, float.NaN };
|
||||
|
||||
//var measure = new MeasureS6DBDiagnosticChannel(this);
|
||||
|
||||
////External sensor 1
|
||||
//measure.Channel = MeasureS6DBDiagnosticChannel.S6DBDiagnosticChannelList.DiagEnv_2_Temperature;
|
||||
//measure.SyncExecute();
|
||||
//dasResults.TemperaturesPre[0] = measure.Measurement;
|
||||
|
||||
////External sensor 2
|
||||
//measure.Channel = MeasureS6DBDiagnosticChannel.S6DBDiagnosticChannelList.DiagEnv_3_Temperature;
|
||||
//measure.SyncExecute();
|
||||
//dasResults.TemperaturesPre[1] = measure.Measurement;
|
||||
|
||||
////External sensor 3
|
||||
//measure.Channel = MeasureS6DBDiagnosticChannel.S6DBDiagnosticChannelList.DiagEnv_4_Temperature;
|
||||
//measure.SyncExecute();
|
||||
//dasResults.TemperaturesPre[2] = measure.Measurement;
|
||||
|
||||
////External sensor 4
|
||||
//measure.Channel = MeasureS6DBDiagnosticChannel.S6DBDiagnosticChannelList.DiagEnv_5_Temperature;
|
||||
//measure.SyncExecute();
|
||||
//dasResults.TemperaturesPre[3] = measure.Measurement;
|
||||
}
|
||||
}
|
||||
info.Progress(100);
|
||||
dasResults.SensorIds = null;
|
||||
dasResults.TiltSensorDataPre = null;
|
||||
dasResults.SquibResistances = null;
|
||||
ArmCheckResults = dasResults;
|
||||
info.Success();
|
||||
}
|
||||
|
||||
public void CheckAlreadyLevelTriggered(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("PowerPro.CheckAlreadyLevelTriggered", AsyncCheckAlreadyLevelTriggered, info);
|
||||
}
|
||||
private void AsyncCheckAlreadyLevelTriggered(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as PowerProAsyncInfo;
|
||||
Debug.Assert(info != null, "info != null");
|
||||
try
|
||||
{
|
||||
foreach (var m in ConfigData.Modules)
|
||||
{
|
||||
foreach (var ch in m.Channels)
|
||||
{
|
||||
if (!(ch is AnalogInputDASChannel analog)) continue;
|
||||
analog.AlreadyLevelTriggered = false;
|
||||
analog.MeasuredEULevelTriggerCheck = double.NaN;
|
||||
}
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
public void DoTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
//this was supposed to be async, why is it executing synchronously? I dont' know
|
||||
//but I'm preserving it as is [dtm] 2019-05-23
|
||||
PowerProAsyncInfo info = null;
|
||||
if (null != callback)
|
||||
{
|
||||
info = new PowerProAsyncInfo(callback, userData);
|
||||
}
|
||||
DoTriggerCheckSync();
|
||||
info?.Success();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// do the synchronous version of trigger check
|
||||
/// </summary>
|
||||
public void DoTriggerCheckSync()
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
|
||||
{
|
||||
var query = new InitializeHardwareLines(this) { LogCommands = true, CheckStartForShort = true, CheckTriggerForShort = true };
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
query.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//IHL can throw an exception if the trigger is shorted, we don't want this
|
||||
//but if it's anything else go and rethrow the exception
|
||||
if (!ex.Message.ToLower().Contains("shorted"))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//var oldStatus = DASArmStatus;
|
||||
var status = new ArmStatus
|
||||
{
|
||||
IsTriggered = query.TriggerInputShorted,
|
||||
//IsArmed = query.TriggerInputShorted || query.StartRecordShorted
|
||||
IsStartShorted = query.StartRecordShorted
|
||||
};
|
||||
|
||||
//10601 Trigger Check can miss the pulse generated by HW
|
||||
//we have to latch the trigger status for the S6DB ... since it does one shot pulse
|
||||
//if (null != oldStatus)
|
||||
//{
|
||||
// status.IsArmed = status.IsArmed || oldStatus.IsArmed;
|
||||
// status.IsTriggered = status.IsTriggered || oldStatus.IsTriggered;
|
||||
// status.IsStartShorted = status.IsStartShorted || oldStatus.IsStartShorted;
|
||||
//}
|
||||
|
||||
status.IsTriggerShorted = status.IsTriggered;
|
||||
//status.IsStartShorted = status.IsArmed;
|
||||
status.IsStartShorted = status.IsStartShorted;
|
||||
SetDASArmStatus(status, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InitializeHardwareLines.Log(ex, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ITriggerCheckActions.PostStartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
private class EventDiagnosticsAsyncPacket
|
||||
{
|
||||
public PowerProAsyncInfo Info { get; set; }
|
||||
public int EventNumber { get; set; }
|
||||
public PrePostResults WhichResult { get; set; }
|
||||
}
|
||||
/// <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>
|
||||
public void GetEventDiagnosticsResults(int EventNumber, PrePostResults WhichResult,
|
||||
ServiceCallback callback, object userData)
|
||||
{
|
||||
var packet = new EventDiagnosticsAsyncPacket();
|
||||
packet.Info = new PowerProAsyncInfo(callback, userData);
|
||||
packet.EventNumber = EventNumber;
|
||||
packet.WhichResult = WhichResult;
|
||||
|
||||
packet.Info.Success();
|
||||
}
|
||||
public void PerformVoltageCheckTAOnly(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("PowerPro.PerformVoltageCheckTAOnly", AsyncPerformVoltageCheckTAOnly, info);
|
||||
}
|
||||
private void AsyncPerformVoltageCheckTAOnly(object o)
|
||||
{
|
||||
var info = o as PowerProAsyncInfo;
|
||||
info?.Success();
|
||||
}
|
||||
private const double SDB_ERR_VOLTAGE_REPORTING = 100000.0D;
|
||||
/// <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)
|
||||
//{
|
||||
// var info = new PowerProAsyncInfo(callback, userData);
|
||||
// var status = new ArmStatus { IsArmed = false };
|
||||
// try
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MeasurePowerProAllDiagnosticChannel))
|
||||
// {
|
||||
// var mppadc = new MeasurePowerProAllDiagnosticChannel(this);
|
||||
// mppadc.SyncExecute(); // Just Log it for now
|
||||
// }
|
||||
// }
|
||||
// catch (Exception ex) { APILogger.Log("Failed to Measure All Diagnostic Channel", ex); }
|
||||
// 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.StatusDisplayBattery = statusDisplayBattery;
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// APILogger.Log("Failed to get input mv", ex);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// SetDASArmStatus(status, true);
|
||||
// }
|
||||
// info.Success();
|
||||
//}
|
||||
void IConfigurationActions.CheckSafetyState(bool bArmed, ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new PowerProAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
|
||||
|
||||
//}
|
||||
/// <summary>
|
||||
/// this is a duplicate class of SLICEDb.SDBAsyncInfo, we might want to just use that one, but it is marked private there
|
||||
/// </summary>
|
||||
private class PowerProAsyncInfo
|
||||
{
|
||||
public ServiceCallback Callback { get; set; }
|
||||
public object UserData { get; set; }
|
||||
public object FunctionData { get; set; }
|
||||
|
||||
public PowerProAsyncInfo(ServiceCallback callback, object userData)
|
||||
{
|
||||
Callback = callback;
|
||||
UserData = userData;
|
||||
}
|
||||
|
||||
public void Error(string msg, Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cbData = new ServiceCallbackData();
|
||||
cbData.Status = ServiceCallbackData.CallbackStatus.Failure;
|
||||
cbData.ErrorMessage = msg;
|
||||
cbData.ErrorException = ex;
|
||||
cbData.UserData = UserData;
|
||||
Callback(cbData);
|
||||
}
|
||||
catch (Exception eex)
|
||||
{
|
||||
APILogger.Log("MessageBox", "PowerPRO ERROR", eex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Error(string msg)
|
||||
{
|
||||
Error(msg, null);
|
||||
}
|
||||
|
||||
public void Progress(int value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.ProgressReport;
|
||||
progressData.ProgressValue = value;
|
||||
progressData.UserData = UserData;
|
||||
Callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", "PowerPRO ERROR", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Success()
|
||||
{
|
||||
try
|
||||
{
|
||||
var success = new ServiceCallbackData();
|
||||
success.Status = ServiceCallbackData.CallbackStatus.Success;
|
||||
success.UserData = UserData;
|
||||
Callback(success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", "PowerPRO 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", "PowerPRO ERROR", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class PowerPro_Base<T> : SLICE2_Base<T> where T : IConnection, new()
|
||||
{
|
||||
protected override bool AdjustInputRange(AnalogInputDASChannel analog)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// returns true if device supports trigger inversion, false otherwise
|
||||
/// <inheritdoc cref="IDASCommunication"/>
|
||||
/// </summary>
|
||||
/// <returns>true if device supports trigger inversion, false otherwise</returns>
|
||||
public override bool SupportsTriggerInversion() => HardwareConstants.SupportsTriggerInversion(GetHardwareType(), ProtocolVersion);
|
||||
/// <summary>
|
||||
/// returns true if device supports start inversion, false otherwise
|
||||
/// <inheritdoc cref="IDASCommunication"/>
|
||||
/// </summary>
|
||||
/// <returns>true if device supports start inversion, false otherwise</returns>
|
||||
public override bool SupportsStartInversion() => HardwareConstants.SupportsStartInversion(GetHardwareType(), ProtocolVersion);
|
||||
|
||||
|
||||
public override bool CheckAAF(float rate) { return true; }
|
||||
public override bool SupportsTimeSynchronization
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public override double[] GetNominalRanges(SensorConstants.BridgeType bridgeType)
|
||||
{
|
||||
switch (bridgeType)
|
||||
{
|
||||
case SensorConstants.BridgeType.IEPE:
|
||||
return WinUSBSlice.StaticDASIEPEInfo.NominalRanges;
|
||||
default:
|
||||
return WinUSBSlice.StaticDASBridgeInfo.NominalRanges;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> PowerPro_MinimumProtocols =
|
||||
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
||||
|
||||
public override void InitMinProto()
|
||||
{
|
||||
// SLICE 6.0 DB Protocol Limitations
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryMSP430Firmware] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDefaultMIF] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
|
||||
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = PowerPRO.DIAGNOS_SHUNT_DAC;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageInsertion] = PowerPRO.DIAGNOS_SHUNT_DAC;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryEthernetMacTable] = PowerPRO.MIN_PROTOCOL_QUERYMACTABLE;
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MeasurePowerProAllDiagnosticChannel] = PowerPRO.MIN_PROTOCOL_MEASUREPOWERPROALLDIAGNOSTICCHANNEL;
|
||||
|
||||
PowerPro_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics] = PowerPRO.MIN_PROTOCOL_VER;
|
||||
|
||||
MinimumProtocols = PowerPro_MinimumProtocols;
|
||||
}
|
||||
protected override Slice<T>.ConfigAttributes GetConfigAttributes(ICommunication com)
|
||||
{
|
||||
return new SLICE6ConfigAttributes(com);
|
||||
}
|
||||
/// <summary>
|
||||
/// SLICE6 config attributes, mostly inherits from SLICE.ConfigAttributes with some functionality removed
|
||||
/// </summary>
|
||||
protected class SLICE6ConfigAttributes : Slice<T>.ConfigAttributes
|
||||
{
|
||||
public SLICE6ConfigAttributes(ICommunication _com)
|
||||
: base(_com)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// QueryEventData also is customized for SLICE6, it needs to perform SLICE6 specific data marshalling
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override QueryEventDataBase GetQueryEventData()
|
||||
{
|
||||
return new QueryEventData_SLICE6(this, QueryEventData_SLICE6.Default_IO_Timeout);
|
||||
}
|
||||
/// <summary>
|
||||
/// we can probably simplify and take common items (slice6+slice1) out of this function, but for now
|
||||
/// it's mostly a copy of SLICE1.AsyncConfigure
|
||||
/// </summary>
|
||||
/// <param name="configAsyncInfo"></param>
|
||||
protected override void AsyncConfigure(object configAsyncInfo)
|
||||
{
|
||||
var info = (SliceConfigServiceAsyncInfo)configAsyncInfo;
|
||||
|
||||
ConfigureHasBeenRun = true;
|
||||
if (info.DiscardDiagnostics) { DiagnosticsHasBeenRun = false; }
|
||||
info.Progress(100);
|
||||
info.Success();
|
||||
}
|
||||
|
||||
#region Voltage Check
|
||||
public void PerformVoltageCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("PowerPro.PerformVoltageCheck", AsyncPerformVoltageCheck, info);
|
||||
}
|
||||
|
||||
private void AsyncPerformVoltageCheck(object o)
|
||||
{
|
||||
var info = o as SliceServiceAsyncInfo;
|
||||
try
|
||||
{
|
||||
GetBaseInputs(true);
|
||||
info?.Success();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
info?.Error(ex.Message);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// hardcoded constants right now ... maybe these belong in attributes in the firmware!
|
||||
/// </summary>
|
||||
protected override uint MaxAAFilterRateHz { get { return PowerPRO.MaxAAFilterRateHz; } }
|
||||
protected override uint MaxSampleRateHz { get { return 400000; } }
|
||||
}
|
||||
}
|
||||
86
DataPRO/IService/Classes/SLICE/S6DBConnectedDevice.cs
Normal file
86
DataPRO/IService/Classes/SLICE/S6DBConnectedDevice.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System.Net.NetworkInformation;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.Interface.Communication;
|
||||
|
||||
namespace DTS.DASLib.Service.Classes.SLICE
|
||||
{
|
||||
/// <summary>
|
||||
/// describes a device connected to a S6DB as determined by
|
||||
/// QAUTIL_QUERY_MAC_IP_TABLE
|
||||
/// part of
|
||||
/// 10582 Implement auto-discover and monitor DAS status.
|
||||
/// </summary>
|
||||
public class S6DBConnectedDevice : IDASConnectedDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// the device type of the connected device
|
||||
/// </summary>
|
||||
public HardwareTypes DeviceType { get; } = HardwareTypes.SLICE6_Base;
|
||||
|
||||
/// <summary>
|
||||
/// the port the device is on only positive values are valid
|
||||
/// 0 based
|
||||
/// </summary>
|
||||
public int Port { get; private set; } = -1;
|
||||
/// <summary>
|
||||
/// the position on the chain or port
|
||||
/// only positive values are valid
|
||||
/// 0 based
|
||||
/// </summary>
|
||||
public int SpotOnPort { get; private set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// MAC address
|
||||
/// </summary>
|
||||
public PhysicalAddress PhysicalAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// IP address reported by device
|
||||
/// default value empty string
|
||||
/// </summary>
|
||||
public string IPAddress { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// serial number of device
|
||||
/// default value empty string
|
||||
/// </summary>
|
||||
public string SerialNumber { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// location of device
|
||||
/// default value empty string
|
||||
/// </summary>
|
||||
public string Location { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// version of device
|
||||
/// default value empty string
|
||||
/// </summary>
|
||||
public string Version { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// constructs new connected device record
|
||||
/// </summary>
|
||||
/// <param name="port">port, 0 based</param>
|
||||
/// <param name="spotOnPort">position on port/chain 0 based</param>
|
||||
/// <param name="physicalAddress">mac address</param>
|
||||
/// <param name="ipAddress">ip address</param>
|
||||
/// <param name="serialNumber">serial number of connected device</param>
|
||||
/// <param name="location">location</param>
|
||||
/// <param name="version">version</param>
|
||||
public S6DBConnectedDevice(int port, int spotOnPort, PhysicalAddress physicalAddress, string ipAddress,
|
||||
string serialNumber, string location, string version)
|
||||
{
|
||||
Port = port;
|
||||
SpotOnPort = spotOnPort;
|
||||
PhysicalAddress = physicalAddress;
|
||||
IPAddress = ipAddress;
|
||||
SerialNumber = serialNumber;
|
||||
Location = location;
|
||||
Version = version;
|
||||
if (SerialNumber.StartsWith("S6A"))
|
||||
{
|
||||
DeviceType = HardwareTypes.SLICE6_AIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
642
DataPRO/IService/Classes/SLICE/SLICE1_5.cs
Normal file
642
DataPRO/IService/Classes/SLICE/SLICE1_5.cs
Normal file
@@ -0,0 +1,642 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DTS.Common;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.WINUSBConnection;
|
||||
using DTS.DASLib.Command.SLICE.DownloadCommands;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.Constant.DASSpecific;
|
||||
using DTS.Common.Utilities.LTLogging;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICE1_5<T> : SLICE2_Base<T>, IConfigurationActions where T : IConnection, new()
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
if (SerialNumber.StartsWith("SG5"))
|
||||
{
|
||||
return HardwareTypes.SLICE1_G5Stack;
|
||||
}
|
||||
if (SerialNumber.Contains("BA0"))
|
||||
{
|
||||
return HardwareTypes.SLICE1_5_Micro_Base;
|
||||
}
|
||||
return HardwareTypes.SLICE1_5_Nano_Base;
|
||||
}
|
||||
public override int[] GetStackChannelConfigTypes() => new int[] { 0 };
|
||||
|
||||
/// <summary>
|
||||
/// 14269 Implement SLICE PRO and Base+ RTC
|
||||
/// my records indicate SLICE1.5 has always supported this feature ...
|
||||
/// </summary>
|
||||
public override bool SupportsTimeSynchronization => true;
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// gets the expected excitation in mV for a given channel
|
||||
/// returns 0 if excitation could not be retrieved, otherwise excitation in mV
|
||||
/// </summary>
|
||||
/// <param name="moduleIndex"></param>
|
||||
/// <param name="channelOnModule"></param>
|
||||
/// <returns></returns>
|
||||
protected override double GetExpectedExcitationMV(int moduleIndex, int channelOnModule)
|
||||
{
|
||||
if (ConfigData?.Modules == null || ConfigData.Modules.Length <= moduleIndex)
|
||||
{
|
||||
APILogger.Log("unable to get excitation, no ConfigData to base excitation on");
|
||||
return 0D;
|
||||
}
|
||||
if (!(ConfigData.Modules[moduleIndex].Channels[channelOnModule] is AnalogInputDASChannel aic))
|
||||
{
|
||||
//only have excitation to consider on analog channels
|
||||
APILogger.Log("unable to get excitation, channel has no excitation (is not analog)");
|
||||
return 0D;
|
||||
}
|
||||
var excitation = Test.Module.Channel.Sensor.GetExcitationVoltageMagnitudeFromEnum(aic.Excitation) * 1000D;
|
||||
try
|
||||
{
|
||||
var qsa = new QuerySystemAttribute_Bridge(this);
|
||||
|
||||
switch (channelOnModule)
|
||||
{
|
||||
case 0:
|
||||
qsa.Key = AttributeTypes.SystemAttributes_Bridge.FactoryCalibratedExcitationAVolts;
|
||||
break;
|
||||
case 1:
|
||||
qsa.Key = AttributeTypes.SystemAttributes_Bridge.FactoryCalibratedExcitationBVolts;
|
||||
break;
|
||||
default:
|
||||
qsa.Key = AttributeTypes.SystemAttributes_Bridge.FactoryCalibratedExcitationCVolts;
|
||||
break;
|
||||
}
|
||||
//note device 0 is the base, the first module starts at 1, so we have to start at an offset of 1
|
||||
qsa.DeviceID = Convert.ToByte(1 + moduleIndex);
|
||||
qsa.SyncExecute();
|
||||
var bridgeExcitation = Convert.ToDouble(qsa.Value) * 1000D;//convert from V to mV
|
||||
var delta = Math.Abs(excitation - bridgeExcitation);
|
||||
if (delta < 500)
|
||||
{
|
||||
excitation = bridgeExcitation;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
return excitation;
|
||||
}
|
||||
public static StaticInformation StaticDASBridge1_5Info = new StaticInformation(new[]
|
||||
{//1,2,4,8,10,16,20,32,40,64,80,128,160,320,640,1280
|
||||
2400D/1.0,
|
||||
2400D/2.0,
|
||||
2400D/4.0,
|
||||
2400D/8.0,
|
||||
2400D/10.0,
|
||||
2400D/16.0,
|
||||
2400D/20.0,
|
||||
2400D/32.0,
|
||||
2400D/40.0,
|
||||
2400D/64.0,
|
||||
2400D/80.0,
|
||||
2400D/128.0,
|
||||
2400D/160.0,
|
||||
2400D/320.0,
|
||||
2400D/640.0,
|
||||
2400D/1280.0
|
||||
});
|
||||
|
||||
protected override float GetLevelTriggerThreshold(AnalogInputDASChannel analog, IDiagnosticResult diagnostics,
|
||||
double thresholdeu, double mvPerEu)
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
if (analog.SensitivityMilliVoltsPerEU < 0 && !analog.RemoveOffset)
|
||||
{
|
||||
var threshold = Convert.ToSingle(thresholdeu * mvPerEu
|
||||
-
|
||||
diagnostics.GetExpectedDataZeroLevelADC(analog.ZeroMethod) *
|
||||
diagnostics.ScalefactorMilliVoltsPerADC);
|
||||
|
||||
try
|
||||
{
|
||||
var s =
|
||||
$"{now.ToShortDateString()} {now.ToShortTimeString()}\r\n{SerialNumber}:{analog.Number}:{analog.SerialNumber} : thresholdEU ({thresholdeu}) * MvPerEU ({mvPerEu}) - DataZeroLevelADC ({diagnostics.GetExpectedDataZeroLevelADC(analog.ZeroMethod)}) * ScaleFactorMvPerADC ({diagnostics.ScalefactorMilliVoltsPerADC})={threshold}; SensitivityMv={analog.SensitivityMilliVoltsPerEU}\r\n";
|
||||
LevelTriggerLogging.LevelTriggerLog(s);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
return threshold;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var threshold = Convert.ToSingle(thresholdeu * mvPerEu
|
||||
+
|
||||
diagnostics.GetExpectedDataZeroLevelADC(analog.ZeroMethod) *
|
||||
diagnostics.ScalefactorMilliVoltsPerADC);
|
||||
try
|
||||
{
|
||||
var s =
|
||||
$"{now.ToShortDateString()} {now.ToShortTimeString()}\r\n{SerialNumber}:{analog.Number}:{analog.SerialNumber} : thresholdEU ({thresholdeu}) * MvPerEU ({mvPerEu}) + DataZeroLevelADC ({diagnostics.GetExpectedDataZeroLevelADC(analog.ZeroMethod)}) * ScaleFactorMvPerADC ({diagnostics.ScalefactorMilliVoltsPerADC})={threshold}; SensitivityMv={analog.SensitivityMilliVoltsPerEU}\r\n";
|
||||
LevelTriggerLogging.LevelTriggerLog(s);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
return threshold;
|
||||
}
|
||||
}
|
||||
|
||||
private const double IEPE_GAIN_DIVIDER = 4.9D;
|
||||
|
||||
//0.2040816327F, 2.0408163265F
|
||||
public static StaticInformation StaticDASIEPE1_5Info = new StaticInformation(new[]
|
||||
{
|
||||
2400D / (1.0D / IEPE_GAIN_DIVIDER),
|
||||
2400D / (10.0D / IEPE_GAIN_DIVIDER),
|
||||
});
|
||||
|
||||
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> _slice15MinimumProtocols = new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
||||
|
||||
public override bool RequireDiagnosticRateMatchSampleRate() { return false; }
|
||||
|
||||
public override void InitMinProto()
|
||||
{
|
||||
// SLICE 1.5 Protocol Limitations
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryMSP430Firmware] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashCardInfo] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
//SLICE2_MinimumProtocols.Add(ReqProtoVer.Commands.VoltageInsertion, 133);
|
||||
//SLICE2_MinimumProtocols.Add(ReqProtoVer.Commands.SetDefaultMIF, 140);
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.StackFirmwareUpdate, 137);
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PhysicalStartAddress] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelTypeConfiguration, 134);
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration, 134);
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels, 136);
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.DiagnosticTwoVoltExcitation, 138);
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.ExcitationLevel, 133);
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashClear] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
//SLICE2_MinimumProtocols.Add(DFConstantsAndEnums.ProtocolLimitedCommands.DiagnosticsMode, 133);
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE1_5.MIN_PROTOCOL_VER;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_TimeLeftInArm] = SLICE1_5.QUERY_ARM_AND_TRIGGER_STATUS_TIME_LEFT_IN_ARM;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRecDelayInSecond] = SLICE1_5.START_REC_DELAY_IN_SECOND;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MeasureInternalOffset] = SLICE1_5.MEASURE_INTERNAL_OFFSET;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE1_5.IGNORE_SHORTED_START_EVENT;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = SLICE1_5.START_REALTIME_STREAM;
|
||||
_slice15MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.GenerateEvent] = 9;
|
||||
MinimumProtocols = _slice15MinimumProtocols;
|
||||
|
||||
}
|
||||
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
|
||||
{
|
||||
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
|
||||
configModule.Channels = new AnalogInputDASChannel[infoModule.NumberOfChannels];
|
||||
|
||||
for (var i = 0; i < infoModule.NumberOfChannels; i++)
|
||||
{
|
||||
var channel = new AnalogInputDASChannel(configModule, i);
|
||||
if (infoModule.TypeOfModule == DFConstantsAndEnums.ModuleType.SLICEIEPE)
|
||||
{
|
||||
channel.IEPEChannel = true;
|
||||
channel.SupportedBridges = new[] { SensorConstants.BridgeType.IEPE };
|
||||
}
|
||||
else
|
||||
{
|
||||
channel.IEPEChannel = false;
|
||||
channel.SupportedBridges = new[] {SensorConstants.BridgeType.FullBridge,
|
||||
SensorConstants.BridgeType.HalfBridge};
|
||||
}
|
||||
configModule.Channels[i] = channel;
|
||||
}
|
||||
return configModule;
|
||||
}
|
||||
|
||||
protected override void PerformVoltageInsertionCheck(IDiagnosticActions[] channelActions, SliceServiceAsyncInfo info, ref IDiagnosticResult[] results)
|
||||
{
|
||||
// first count how many we need to do it on
|
||||
var numToMeasure = channelActions.Count(a => a.PerformVoltageInsertCheck);
|
||||
if (numToMeasure == 0)
|
||||
return;
|
||||
|
||||
//slice 1 bridges can not handle voltage insertion ...
|
||||
|
||||
for (var idx = 0; idx < channelActions.Length; idx++)
|
||||
{
|
||||
if (channelActions[idx].PerformVoltageInsertCheck)
|
||||
{
|
||||
results[idx].MeasuredGain = null;
|
||||
results[idx].TargetGain = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measure the internal offset on the channels that have it flagged
|
||||
/// </summary>
|
||||
/// <param name="channelActions">An array of actions. One entry per channel</param>
|
||||
/// <param name="info">Our async data</param>
|
||||
/// <param name="results">An array of results. One entry per channel</param>
|
||||
/// <param name="bFinalOffset"></param>
|
||||
protected override void MeasureInternalOffset(IDiagnosticActions[] channelActions, SliceServiceAsyncInfo info, ref IDiagnosticResult[] results, bool bFinalOffset)
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MeasureInternalOffset))
|
||||
{
|
||||
#region New internal offset measure
|
||||
// first count how many we need to do it on
|
||||
var numToMeasure = channelActions.Count(a => a.MeasureInternalOffset);
|
||||
if (numToMeasure == 0)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var measuredChannelBiasADC = new short[ChannelDiagnostics.Length];
|
||||
for (var idx = 0; idx < channelActions.Length; idx++)
|
||||
{
|
||||
if (!ChannelDiagnostics[idx].MeasureInternalOffset) continue;
|
||||
var qsab = new QuerySystemAttribute_Bridge(this)
|
||||
{
|
||||
// Get Module number from DAS Channel Number
|
||||
DeviceID = Convert.ToByte(1 + ChannelDiagnostics[idx].DASChannelNumber / 3),
|
||||
// Get Key offset from DAS Channel Number
|
||||
Key = AttributeTypes.SystemAttributes_Bridge.BIAS_ADC_A + (byte)(ChannelDiagnostics[idx].DASChannelNumber % 3)
|
||||
};
|
||||
qsab.SyncExecute();
|
||||
|
||||
if ((ushort)qsab.Value == 0)
|
||||
{
|
||||
// If value comes back as zero our base supports the bridge
|
||||
// attribute but the bridge does not, or has not been calibrated
|
||||
measuredChannelBiasADC[idx] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// convert from ushort to short
|
||||
measuredChannelBiasADC[idx] = Convert.ToInt16((ushort)qsab.Value - Math.Pow(2, 15));
|
||||
}
|
||||
}
|
||||
for (var idx = 0; idx < results.Length; idx++)
|
||||
{
|
||||
info.NewData(new ServiceCallbackData.DiagnosticNewData()
|
||||
{
|
||||
Result = measuredChannelBiasADC[idx],
|
||||
DasChannelNumber = results[idx].DASChannelNumber,
|
||||
Action = ServiceCallbackData.DiagnosticNewData.Actions.MeasureInternalOffset
|
||||
});
|
||||
|
||||
//attempt to resolve the removed adc by using the before and after info
|
||||
try
|
||||
{
|
||||
if (bFinalOffset)
|
||||
{
|
||||
if (null != results[idx] && channelActions[idx].RemoveOffset)
|
||||
{
|
||||
results[idx].RemovedInternalOffsetADC =
|
||||
Convert.ToInt32((double)results[idx].MeasuredInternalOffsetMilliVolts / results[idx].ScalefactorMilliVoltsPerADC -
|
||||
measuredChannelBiasADC[idx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
results[idx].RemovedInternalOffsetADC = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
results[idx].MeasuredInternalOffsetMilliVolts = measuredChannelBiasADC[idx] * results[idx].ScalefactorMilliVoltsPerADC;
|
||||
results[idx].ZeroMVInADC = Convert.ToInt16(measuredChannelBiasADC[idx]);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(
|
||||
$"Error Retrieving Internal Offset on {SerialNumber} channel {results[idx].DASChannelNumber}", ex);
|
||||
results[idx].RemovedInternalOffsetADC = 0;
|
||||
results[idx].MeasuredInternalOffsetMilliVolts = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Error Retrieving Internal Offset", ex);
|
||||
foreach (var dr in results)
|
||||
{
|
||||
dr.RemovedInternalOffsetADC = 0;
|
||||
dr.MeasuredInternalOffsetMilliVolts = 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
else
|
||||
{
|
||||
//Command not supported
|
||||
foreach (var dr in results)
|
||||
{
|
||||
dr.RemovedInternalOffsetADC = 0;
|
||||
dr.MeasuredInternalOffsetMilliVolts = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert gain code to value based on Slice 1 conversion table
|
||||
/// </summary>
|
||||
/// <param name="gainCode"></param>
|
||||
/// <returns></returns>
|
||||
protected override double GainCodeToGainValue(ushort gainCode)
|
||||
{
|
||||
//Run the same code as Slice 1.0, not base:GainCodeToGainValue which is SLICE 2
|
||||
|
||||
var gainValueString = ((GainCodes)gainCode).ToString();
|
||||
if (!double.TryParse(gainValueString.TrimStart('G'), out var gainValue))
|
||||
{
|
||||
gainValue = 1.0D;
|
||||
}
|
||||
|
||||
return gainValue;
|
||||
}
|
||||
|
||||
public override double[] GetNominalRanges(SensorConstants.BridgeType bridgeType)
|
||||
{
|
||||
switch (bridgeType)
|
||||
{
|
||||
case SensorConstants.BridgeType.IEPE:
|
||||
return WinUSBSlice.StaticDASIEPEInfo.NominalRanges;
|
||||
default:
|
||||
return WinUSBSlice.StaticDASBridgeInfo.NominalRanges;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CheckAAF(float rate) { return true; }
|
||||
|
||||
/// <summary>
|
||||
/// hardcoded constants right now ... maybe these belong in attributes in the firmware!
|
||||
/// </summary>
|
||||
protected override uint MaxAAFilterRateHz => SLICE1_5.MaxAAFilterRateHz;
|
||||
|
||||
protected override uint MaxSampleRateHz => 500000;
|
||||
|
||||
public override long MaxMemory()
|
||||
{
|
||||
if (null == DASInfo || 0 == DASInfo.NumberOfBytesPerSampleClock) { return 0; }
|
||||
|
||||
if (null == DASInfo.MaxEventStorageSpaceInBytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (long)(DASInfo.MaxEventStorageSpaceInBytes / DASInfo.NumberOfBytesPerSampleClock);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// calculates the max sample rate
|
||||
/// these are not exact max sample rates, but convenient close enough limits
|
||||
/// drop 100k every module after 3 (starting at 500k)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override uint MaxSampleRate(int numberOfConfiguredChannels)
|
||||
{
|
||||
switch (DASInfo.Modules.Length)
|
||||
{
|
||||
case 1:
|
||||
return MaxSampleRateHz;
|
||||
case 2:
|
||||
return 400000;
|
||||
case 3:
|
||||
return 300000;
|
||||
case 4:
|
||||
default:
|
||||
return 200000;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint MaxAAFilterRate()
|
||||
{
|
||||
return MaxAAFilterRateHz;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// QueryEventData also is customized for SLICE 1.5, it needs to perform SLICE 1.5 specific data marshalling
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override QueryEventDataBase GetQueryEventData()
|
||||
{
|
||||
return new QueryEventData_SLICE1_5(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// this meaty class handles skipping parts of the download not needed (start of page to desired start sample)
|
||||
/// [also note we'll need to do the same thing with the end sample too if we want to use the ECC properly,
|
||||
/// but ECC isn't even implemented yet ...]
|
||||
/// </summary>
|
||||
public class QueryEventData_SLICE1_5 : QueryEventDataBase
|
||||
{
|
||||
public override UInt64 FirstSample
|
||||
{
|
||||
get => base.FirstSample;
|
||||
set => base.FirstSample = value;
|
||||
}
|
||||
|
||||
public override UInt64 LastSample
|
||||
{
|
||||
get => base.LastSample;
|
||||
set => base.LastSample = value;
|
||||
}
|
||||
public QueryEventData_SLICE1_5(DTS.Common.Interface.DASFactory.ICommunication sock)
|
||||
: base(sock) { LogCommands = false; }
|
||||
|
||||
public QueryEventData_SLICE1_5(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)
|
||||
: base(sock, timeoutMillisec) { LogCommands = false; }
|
||||
|
||||
private ulong GetRequestedStartSport()
|
||||
{
|
||||
var slice15Usb = recorder as SLICE1_5<WINUSBConnection>;
|
||||
if (recorder is SLICE1_5<EthernetConnection> slice15Ethernet)
|
||||
{
|
||||
return ((WhatToDownloadSlice2)slice15Ethernet.WhatToDownload).RequestedStartSport;
|
||||
}
|
||||
if (null != slice15Usb)
|
||||
{
|
||||
return ((WhatToDownloadSlice2)slice15Usb.WhatToDownload).RequestedStartSport;
|
||||
}
|
||||
throw new NotSupportedException("SLICE1_5::GetRequestedStartSport not supported for " + recorder.ConnectString);
|
||||
}
|
||||
private void PushLeftOverData(ushort[] daters)
|
||||
{
|
||||
var slice15Usb = recorder as SLICE1_5<WINUSBConnection>;
|
||||
var slice15Ethernet = recorder as SLICE1_5<EthernetConnection>;
|
||||
if (null != slice15Usb) { slice15Usb.PushLeftOverData(daters); }
|
||||
else
|
||||
{
|
||||
slice15Ethernet?.PushLeftOverData(daters);
|
||||
}
|
||||
}
|
||||
protected override CommandReceiveAction WholePackagePost()
|
||||
{
|
||||
// now send the data to the user
|
||||
var stat = CommandStatus.Success;
|
||||
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
|
||||
{
|
||||
var s = (int)response.Status;
|
||||
APILogger.LogString("QueryEventData.WholePackagePost: reporting failure, status==" + CommandPacketBase.StatusLabels[s] + " (0x" + s.ToString("X") + ")");
|
||||
stat = CommandStatus.Failure;
|
||||
}
|
||||
|
||||
var cbReport = new QueryEventDataReport(stat, UserCallbackData);
|
||||
cbReport.Data = new short[_channelsDownloaded][];
|
||||
|
||||
for (var i = 0; i < _channelsDownloaded; i++)
|
||||
GetChannelData(i, out cbReport.Data[i]);
|
||||
|
||||
//we have processed some data, but there may be some left over (since data isn't channel sample aligned ...)
|
||||
//figure out what we used and what's left over
|
||||
//now we have two situations, one, we have already skimmed beyond all the data we need
|
||||
//or two, we are somewhere in between, we need to skip a few samples
|
||||
|
||||
var requestedStartSpot = GetRequestedStartSport();
|
||||
|
||||
if ((FirstSample + (ulong)_data.Length) < requestedStartSpot)
|
||||
{
|
||||
//push no data, we don't want it!
|
||||
}
|
||||
else if (FirstSample > requestedStartSpot)
|
||||
{//we want everything in here ...
|
||||
var samplesProcessed = Convert.ToInt32(Math.Truncate(_data.Length / (double)ChannelsDownloaded));
|
||||
var leftover = new ushort[_data.Length - (samplesProcessed * ChannelsDownloaded)];
|
||||
for (var i = 0; i < leftover.Length; i++)
|
||||
{
|
||||
leftover[i] = _data[i + samplesProcessed * ChannelsDownloaded];
|
||||
}
|
||||
PushLeftOverData(leftover);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we need to calculate samples only from the start of the data we are interested in
|
||||
var offset = Convert.ToInt32(requestedStartSpot - FirstSample);
|
||||
var samplesProcessed = Convert.ToInt32(Math.Truncate((_data.Length - (double)offset) / ChannelsDownloaded));
|
||||
var leftover = new ushort[(_data.Length - offset) - (samplesProcessed * ChannelsDownloaded)];
|
||||
for (var i = 0; i < leftover.Length; i++)
|
||||
{
|
||||
leftover[i] = _data[i + offset + samplesProcessed * ChannelsDownloaded];
|
||||
}
|
||||
PushLeftOverData(leftover);
|
||||
}
|
||||
|
||||
return UserCallback(cbReport);
|
||||
}
|
||||
|
||||
protected virtual ushort[] PopLeftOverData()
|
||||
{
|
||||
var slice15Usb = recorder as SLICE1_5<WINUSBConnection>;
|
||||
var slice15Ethernet = recorder as SLICE1_5<EthernetConnection>;
|
||||
if (null != slice15Usb)
|
||||
{
|
||||
return slice15Usb.PopLeftOverData();
|
||||
}
|
||||
if (null != slice15Ethernet)
|
||||
{
|
||||
return slice15Ethernet.PopLeftOverData();
|
||||
}
|
||||
throw new NotSupportedException("SLICE1_5::PopLeftOverData not supported for " + recorder.ConnectString);
|
||||
}
|
||||
protected override CommandReceiveAction WholePackage()
|
||||
{
|
||||
if (response.Status != DFConstantsAndEnums.CommandStatus.StatusNoError)
|
||||
{
|
||||
return CommandReceiveAction.StopReceiving;
|
||||
}
|
||||
|
||||
//we are going to process the data shortly, but before we do we'll need to
|
||||
//pre-pend any left over data we have to the new incoming data
|
||||
//since we already count the samples downloaded for samples in the left over stuff
|
||||
//we don't need to recount it, just the new incoming samples
|
||||
_samplesDownloaded = (ulong)(response.Parameter.Length) / 2;
|
||||
var leftover = PopLeftOverData();
|
||||
_data = new ushort[_samplesDownloaded + (ulong)leftover.Length];
|
||||
leftover.CopyTo(_data, 0);
|
||||
for (var i = 0; (ulong)i < _samplesDownloaded; i++)
|
||||
{
|
||||
response.GetParameter(2 * i, out _data[i + leftover.Length]);
|
||||
}
|
||||
return CommandReceiveAction.StopReceiving;
|
||||
}
|
||||
|
||||
public override void GetChannelData(int channel, out short[] signedADC)
|
||||
{
|
||||
if (channel < 0 || channel > _channelsDownloaded)
|
||||
{
|
||||
throw new ApplicationException("QueryEventData.GetChannelData: Data requested on a channel that wasn't downloaded.");
|
||||
}
|
||||
|
||||
//first short circuit if we know we are still completely skipping data
|
||||
if (((ulong)_data.Length + FirstSample) < GetRequestedStartSport())//(slice2.WhatToDownload as WhatToDownloadSlice2).RequestedStartSport)
|
||||
{
|
||||
signedADC = new short[0];//nothing to see here (we are completely before the start of our requested data)
|
||||
return;
|
||||
}
|
||||
|
||||
//now we have two situations, one, we have already skimmed beyond all the data we need
|
||||
//or two, we are somewhere in between, we need to skip a few samples
|
||||
var offset = 0;
|
||||
if (GetRequestedStartSport() > FirstSample)
|
||||
{
|
||||
offset = Convert.ToInt32(GetRequestedStartSport() - FirstSample);
|
||||
}
|
||||
|
||||
// Data order for a 9 channel stack
|
||||
// 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 etc.
|
||||
ushort val;
|
||||
var rv = new List<short>(1024);
|
||||
|
||||
System.Diagnostics.Trace.Assert(_data.Length > offset, @"data length is less than offset");
|
||||
|
||||
var completeSamples = Convert.ToInt32(Math.Truncate((_data.Length - offset) / (double)ChannelsDownloaded));
|
||||
|
||||
for (var i = 0; i < completeSamples; i++)
|
||||
{
|
||||
val = _data[i * ChannelsDownloaded + channel + offset];
|
||||
rv.Add((short)((((val & 0x00FF) << 8) | ((val >> 8) & 0x00FF)) + 0x8000));
|
||||
}
|
||||
signedADC = rv.ToArray();
|
||||
}
|
||||
// this function isn't used by SLICEWare, but it is used by the FirmwareTestUtility
|
||||
// SW uses the GetChannelData above
|
||||
public override void GetRawIndexedData(int index, out ushort[] data)
|
||||
{
|
||||
data = new ushort[_samplesDownloaded];
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = _data[i + index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5714
DataPRO/IService/Classes/SLICE/SLICE2.cs
Normal file
5714
DataPRO/IService/Classes/SLICE/SLICE2.cs
Normal file
File diff suppressed because it is too large
Load Diff
1135
DataPRO/IService/Classes/SLICE/SLICE6.cs
Normal file
1135
DataPRO/IService/Classes/SLICE/SLICE6.cs
Normal file
File diff suppressed because it is too large
Load Diff
1654
DataPRO/IService/Classes/SLICE/SLICE6AIR.cs
Normal file
1654
DataPRO/IService/Classes/SLICE/SLICE6AIR.cs
Normal file
File diff suppressed because it is too large
Load Diff
281
DataPRO/IService/Classes/SLICE/SLICE6AIRBR.cs
Normal file
281
DataPRO/IService/Classes/SLICE/SLICE6AIRBR.cs
Normal file
@@ -0,0 +1,281 @@
|
||||
using DTS.Common.Constant.DASSpecific;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICE6AIRBR<T> : SLICE6_Base<T>, IAlignUDPToPPSAware where T : IConnection, new()
|
||||
{
|
||||
public bool AlignUDPToPPS { get; set; }
|
||||
public override bool SupportsRemoveLeapSeconds => true;
|
||||
public override bool SupportsADCSamplesPerPacket => true;
|
||||
protected override bool RequiresNon0QualificationSamples => true;
|
||||
protected override byte[] GetRTChannelIndices(RealTimeAsyncPacket packet)
|
||||
{
|
||||
return new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||
}
|
||||
public override void SetIsStreamingSupported(bool supported)
|
||||
{
|
||||
IsStreamingSupported = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// the order of this DAS among multiple das
|
||||
/// </summary>
|
||||
public int DASIndex { get; set; } = -1;
|
||||
|
||||
public override void InitMinProto()
|
||||
{
|
||||
// SLICE 6.0 Protocol Limitations
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmRepeatEnable] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDefaultMIF] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackSensors] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.TestCommunication] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackLowPowerMode] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MaxEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FlashClear] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.DiangosShuntDAC] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageInsertion] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPTimestamp] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRecDelayInSecond] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTiltSensorADCPre] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.GenerateEvent] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPSyncStatus] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetDSPFilterSettings] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPDomainID] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ActiveRAM] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordAndStreamSubSample] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RemoveLeapSeconds] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.RecordOnBoot] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents] = SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.UDPAlignOnPPS] = SLICE6AIRBR.UDPALIGNONPPS_PROTOCOL;
|
||||
SLICE6AIR_BR_MinimumProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ADCSamplesPerPacket] = SLICE6AIRBR.ADC_SAMPLES_PER_PACKET_VER;
|
||||
MinimumProtocols = SLICE6AIR_BR_MinimumProtocols;
|
||||
}
|
||||
|
||||
#region protocol settings/overrides
|
||||
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICE6AIR_BR_MinimumProtocols =
|
||||
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
||||
|
||||
protected override int MIN_PROTOCOL_TMATS_INTERVAL => SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
private uint maxSampleRateHz = 0;
|
||||
protected override uint MaxSampleRateHz
|
||||
{
|
||||
get
|
||||
{
|
||||
if (0 == maxSampleRateHz)
|
||||
{
|
||||
try
|
||||
{
|
||||
var qsa = new QuerySystemAttributeSLICE6(this)
|
||||
{
|
||||
Key = AttributeTypes.SystemAttributesSLICE6.MaximumSampleRate
|
||||
};
|
||||
qsa.SyncExecute();
|
||||
maxSampleRateHz = (uint)qsa.Value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Error getting S6A-BR max sample rate, returning 50K");
|
||||
APILogger.LogException(ex);
|
||||
return 50000;
|
||||
}
|
||||
}
|
||||
return maxSampleRateHz;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
|
||||
{
|
||||
//per LP: can stream, no IEPE
|
||||
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
|
||||
configModule.Channels = new DASChannel[infoModule.NumberOfChannels];
|
||||
|
||||
for (var i = 0; i < infoModule.NumberOfChannels; i++)
|
||||
{
|
||||
if (DFConstantsAndEnums.ModuleType.StreamOut == configModule.ModuleType())
|
||||
{
|
||||
var streamOutChannel = new StreamOutputDASChannel(configModule, i);
|
||||
configModule.Channels[i] = streamOutChannel;
|
||||
}
|
||||
else
|
||||
{
|
||||
var channel = new AnalogInputDASChannel(configModule, i);
|
||||
|
||||
channel.SupportedBridges = new SensorConstants.BridgeType[]
|
||||
{
|
||||
SensorConstants.BridgeType.FullBridge,
|
||||
SensorConstants.BridgeType.HalfBridge,
|
||||
};
|
||||
configModule.Channels[i] = channel;
|
||||
}
|
||||
}
|
||||
|
||||
return configModule;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// we can probably simplify and take common items (slice6+slice1) out of this function, but for now
|
||||
/// it's mostly a copy of SLICE1.AsyncConfigure
|
||||
/// </summary>
|
||||
/// <param name="configAsyncInfo"></param>
|
||||
protected override void AsyncConfigure(object configAsyncInfo)
|
||||
{
|
||||
var info = configAsyncInfo as SliceConfigServiceAsyncInfo;
|
||||
SetUDPAlignOnPPS();
|
||||
SetRemoveSeconds();
|
||||
if ((info.StreamADCPerPacket != null) && info.StreamADCPerPacket.ContainsKey(this))
|
||||
{
|
||||
SetADCSamplesPerPacket(info.StreamADCPerPacket[this]);
|
||||
}
|
||||
|
||||
//12638 DAS does not record data in recorder mode during calibration ~ 40% of time.
|
||||
//for SLICE6 we call reseteventlist here, prior to configuring and NOT before arming
|
||||
ResetEventListPriorToConfigure();
|
||||
|
||||
int progressValue = 0;
|
||||
bool bReleased = true;
|
||||
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.ProgramStackChannels))
|
||||
{
|
||||
ReconfigureAccordingToConfig();
|
||||
}
|
||||
|
||||
PresetSampleRate();
|
||||
|
||||
SetVoltageRequirements();
|
||||
|
||||
SetPolarity();
|
||||
|
||||
SetArmDisableShortCheck();
|
||||
|
||||
try
|
||||
{
|
||||
Lock();
|
||||
bReleased = false;
|
||||
// loop thru the modules (slices) and configure the non-UART channels
|
||||
var numChannels = DASInfo.Modules.Sum(mod => mod.NumberOfChannels);
|
||||
var numStreamingChannels = DASInfo.Modules.Sum(mod => DFConstantsAndEnums.ModuleType.StreamOut == mod.TypeOfModule ? mod.NumberOfChannels : 0);
|
||||
var rangeArray = new float[numChannels];
|
||||
//var IsHalfBridgeArray = new bool[numChannels];
|
||||
var bridgeModeArray = new byte[numChannels];
|
||||
var BridgeResistanceArray = new ushort[numChannels];
|
||||
var IsACCoupledArray = new bool[numChannels];
|
||||
//18294 Implement Bridge AC / DC coupling(fw update dependent)
|
||||
var bridgeACCouplingArray = new bool[numChannels];
|
||||
// level trigger values
|
||||
var enableLowerLevelTriggerThreshold = new bool[numChannels];
|
||||
var enableUpperLevelTriggerThreshold = new bool[numChannels];
|
||||
var lowerLevelTriggerThreshold = new float[numChannels];
|
||||
var upperLevelTriggerThreshold = new float[numChannels];
|
||||
var qualificationSamples = new int[numChannels];
|
||||
|
||||
var diagnosticChannels = new List<byte>();
|
||||
|
||||
var bModified = false;
|
||||
CommonConfigureWork(diagnosticChannels, qualificationSamples, ref bReleased,
|
||||
info, bridgeModeArray, IsACCoupledArray, BridgeResistanceArray,
|
||||
ref bModified, rangeArray, enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold,
|
||||
enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold, bridgeACCouplingArray);
|
||||
if (bReleased) { return; }
|
||||
// report progress
|
||||
progressValue = 5;
|
||||
info.Progress(progressValue);
|
||||
|
||||
StoreConfigAttributes(info, rangeArray, ref bReleased, ref progressValue, bridgeModeArray,
|
||||
IsACCoupledArray, BridgeResistanceArray, enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold,
|
||||
enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold, qualificationSamples, numChannels,
|
||||
out var config, bridgeACCouplingArray, 0, numStreamingChannels);
|
||||
|
||||
progressValue = 20;
|
||||
info.Progress(progressValue);
|
||||
|
||||
RemainingConfigWork(ref progressValue, info, diagnosticChannels, config, ref bReleased, null, null, null);
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
info.Progress(100);
|
||||
info.Success();
|
||||
}
|
||||
/// <summary>
|
||||
/// returns true if the device is known to be streaming
|
||||
/// does not query device, just returns a flag if it has been set
|
||||
/// </summary>
|
||||
public override bool GetIsStreaming()
|
||||
{
|
||||
if (null == DASArmStatus) { return false; }
|
||||
//18852 Cannot use Stop streaming / (Dis)Auto Arm button if one or more DAS is idle
|
||||
//can't rely on just having received invalid mode, QATS will still have a status of realtime
|
||||
//when streaming, so we'll use either for now.
|
||||
return DASArmStatus.ReceivedInvalidModeDuringSetup || DASArmStatus.IsInRealtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
693
DataPRO/IService/Classes/SLICE/SLICE6AIRTC.cs
Normal file
693
DataPRO/IService/Classes/SLICE/SLICE6AIRTC.cs
Normal file
@@ -0,0 +1,693 @@
|
||||
using DTS.Common.Classes.DASFactory;
|
||||
using DTS.Common.Constant.DASSpecific;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Interface.DASFactory.Download;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Utils;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command.SLICE.RealtimeCommands;
|
||||
using DTS.DASLib.Service.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
#pragma warning disable S101 // Types should be named in PascalCase
|
||||
public class SLICE6AIRTC<T> : SLICE6_Base<T>, IAlignUDPToPPSAware, IDASReconfigure, ITCDiagnosticResults, IUARTDownloadActions,
|
||||
IUARTDownload where T : IConnection, new()
|
||||
#pragma warning restore S101 // Types should be named in PascalCase
|
||||
{
|
||||
public IUARTDownloadRequest WhatUARTToDownload { get; set; }
|
||||
public void SetWhatUARTToDownload(IUARTDownloadRequest request, bool bSetInDb = true)
|
||||
{
|
||||
UARTDownloadRequest.SetWhatToDownload(this, request, bSetInDb);
|
||||
}
|
||||
public uint BaudRate { get; private set; }
|
||||
public uint DataBits { get; private set; }
|
||||
public StopBits StopBits { get; private set; }
|
||||
public Parity Parity { get; private set; }
|
||||
public Handshake FlowControl { get; private set; }
|
||||
public UartDataFormat DataFormat { get; private set; }
|
||||
public void UARTDownload(ServiceCallback callback, object userData)
|
||||
{
|
||||
var state = new SliceUARTDownloadState(callback, userData, null);
|
||||
state.Error("Not supported");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve UART info about available events to download
|
||||
/// </summary>
|
||||
/// <param name="callback">The function to call with information</param>
|
||||
/// <param name="userData">Whatever you want to pass along</param>
|
||||
void IUARTDownloadActions.QueryUARTDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
|
||||
{
|
||||
var info = new QueryDownloadAsyncInfo(callback, userData, eventIndex);
|
||||
LaunchAsyncWorker("Slice.QueryUARTDownload", AsyncQueryUARTDownload, info);
|
||||
}
|
||||
|
||||
protected virtual void AsyncQueryUARTDownload(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is QueryDownloadAsyncInfo info)) { return; }
|
||||
if (!IsCommandSupported(ProtocolLimitedCommands.QueryUARTDownload))
|
||||
{
|
||||
info.Error("Query UART download is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
void IUARTDownloadActions.GetUARTSettings(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("Slice.GetUARTSettings", AsyncGetUARTSettings, info);
|
||||
}
|
||||
|
||||
protected virtual void AsyncGetUARTSettings(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
if (!IsCommandSupported(ProtocolLimitedCommands.GetUARTSettings))
|
||||
{
|
||||
info.Error("Get UART settings is not supported");
|
||||
return;
|
||||
}
|
||||
var bLocked = false;
|
||||
|
||||
try
|
||||
{
|
||||
Lock();
|
||||
bLocked = true;
|
||||
|
||||
try
|
||||
{
|
||||
var qsaUARTSettings = new QuerySystemAttributeSLICE6AIR(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
qsaUARTSettings.Key = AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings;
|
||||
qsaUARTSettings.SyncExecute();
|
||||
//we made it, set results
|
||||
var uartSettings = (uint[])qsaUARTSettings.Value;
|
||||
|
||||
BaudRate = uartSettings[0];
|
||||
DataBits = uartSettings[1];
|
||||
StopBits = (StopBits)uartSettings[2];
|
||||
Parity = (Parity)uartSettings[3];
|
||||
FlowControl = (Handshake)uartSettings[4];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem getting UART settings", ex);
|
||||
}
|
||||
|
||||
bLocked = false;
|
||||
Release();
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
bLocked = false;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Cancel();
|
||||
}
|
||||
catch (CommandException ce)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
Release();
|
||||
bLocked = false;
|
||||
}
|
||||
|
||||
straightFailures++;
|
||||
if (straightFailures > PERMITTED_FAILURES)
|
||||
{
|
||||
APILogger.Log("GetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
|
||||
info.Error(ce.Message, ce);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Success();
|
||||
APILogger.Log("GetUARTSettings error", ce);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
bLocked = false;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IUARTDownloadActions.SetUARTSettings(ServiceCallback callback, object userData, uint baudRate, uint dataBits, uint stopBits, uint parity, uint flowControl)
|
||||
{
|
||||
var info = new SetUARTSettingsAsyncInfo(callback, userData, baudRate, dataBits, stopBits, parity, flowControl);
|
||||
LaunchAsyncWorker("Slice.SetUARTSettings", AsyncSetUARTSettings, info);
|
||||
}
|
||||
|
||||
protected virtual void AsyncSetUARTSettings(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SetUARTSettingsAsyncInfo info)) { return; }
|
||||
if (!IsCommandSupported(ProtocolLimitedCommands.SetUARTSettings))
|
||||
{
|
||||
info.Error("Set UART settings is not supported");
|
||||
return;
|
||||
}
|
||||
var bLocked = false;
|
||||
|
||||
try
|
||||
{
|
||||
Lock();
|
||||
bLocked = true;
|
||||
var value = new uint[] { info.BaudRate, info.DataBits, info.StopBits, info.Parity, info.FlowControl };
|
||||
try
|
||||
{
|
||||
var ssaUARTSettings =
|
||||
new SetSystemAttributeSLICE6AIR(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaUARTSettings.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.S6A_GpsCanUARTSettings,
|
||||
value, true);
|
||||
ssaUARTSettings.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem setting UART settings", ex);
|
||||
}
|
||||
|
||||
bLocked = false;
|
||||
Release();
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
bLocked = false;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Cancel();
|
||||
}
|
||||
catch (CommandException ce)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
Release();
|
||||
bLocked = false;
|
||||
}
|
||||
|
||||
straightFailures++;
|
||||
if (straightFailures > PERMITTED_FAILURES)
|
||||
{
|
||||
APILogger.Log("SetUARTSettings error - has failed ", straightFailures, " times, giving up", ce);
|
||||
info.Error(ce.Message, ce);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Success();
|
||||
APILogger.Log("SetUARTSettings error", ce);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
bLocked = false;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (bLocked)
|
||||
{
|
||||
Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
public ITCDiagnosticResult[] TCDiagnosticResults { get; private set; } = new ITCDiagnosticResult[0];
|
||||
public void ClearTCDiagnosticResults()
|
||||
{
|
||||
TCDiagnosticResults = new ITCDiagnosticResult[0];
|
||||
}
|
||||
public void SetTCDiagnosticResults(ITCDiagnosticResult[] results)
|
||||
{
|
||||
TCDiagnosticResults = results;
|
||||
}
|
||||
private void InitializeTCDiagnostics()
|
||||
{
|
||||
TCDiagnosticResults = new TCDiagnosticResult[24];
|
||||
for (var i = 0; i < TCDiagnosticResults.Length; i++)
|
||||
{
|
||||
TCDiagnosticResults[i] = new TCDiagnosticResult()
|
||||
{
|
||||
ChannelIndex = i,
|
||||
ChannelName = GetChannelName(i),
|
||||
Status = Common.Interface.Sensors.AnalogDiagnostics.DiagnosticStatus.Untested,
|
||||
CurrentReading = null
|
||||
};
|
||||
}
|
||||
}
|
||||
protected override void AsyncDiagnosAndGetResults(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
InitializeTCDiagnostics();
|
||||
_ = MeasureOffsets(info);
|
||||
_ = MeasureShunts(info);
|
||||
base.AsyncDiagnosAndGetResults(asyncInfo);
|
||||
}
|
||||
private bool MeasureShunts(SliceServiceAsyncInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
var queryChannelShuntResults = new QueryChannelShuntResults(this);
|
||||
queryChannelShuntResults.DeviceID = 0; // send to base
|
||||
byte[] shuntChannelList = new byte[TCDiagnosticResults.Length];
|
||||
int channelCounter = 0;
|
||||
for (int idx = 0; idx < TCDiagnosticResults.Length; idx++)
|
||||
{
|
||||
shuntChannelList[channelCounter] = (byte)TCDiagnosticResults[idx].ChannelIndex;
|
||||
channelCounter++;
|
||||
}
|
||||
queryChannelShuntResults.StackChannelList = shuntChannelList;
|
||||
queryChannelShuntResults.SyncExecute();
|
||||
for( var idx = 0; idx < TCDiagnosticResults.Length; idx++)
|
||||
{
|
||||
var actual = queryChannelShuntResults.ActualDeflectionMV[idx];
|
||||
if (Utils.IsZero(actual))
|
||||
{
|
||||
TCDiagnosticResults[idx].ConnectionStatus = ConnectionStatuses.ModuleNotConnected;
|
||||
}
|
||||
else if (Utils.AlmostEqual(actual, 100))
|
||||
{
|
||||
TCDiagnosticResults[idx].ConnectionStatus = ConnectionStatuses.Connected;
|
||||
}
|
||||
else { TCDiagnosticResults[idx].ConnectionStatus = ConnectionStatuses.NotConnected; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch( Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
info.Error($"Failed to check connections [{SerialNumber}] - {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private bool MeasureOffsets(SliceServiceAsyncInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
var measureOffset = new RetrieveSampleAverage(this);
|
||||
measureOffset.DeviceID = 0; // send to base
|
||||
measureOffset.Samples = 4000;
|
||||
if (measureOffset.Samples < 1) { measureOffset.Samples = 1; }
|
||||
measureOffset.SyncExecute();
|
||||
for( var i = 0; i < TCDiagnosticResults.Length; i++)
|
||||
{
|
||||
var result = TCDiagnosticResults[i];
|
||||
result.CurrentReading = measureOffset.GetChannelData(result.ChannelIndex) * .1D;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
info.Error($"Failed to retrieve average temperatures [{SerialNumber}] - {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private string GetChannelName(int index)
|
||||
{
|
||||
if (null == ((IDASCommunication)this).ConfigData) { return string.Empty; }
|
||||
var config = ((IDASCommunication)this).ConfigData;
|
||||
if (config.Modules == null || 0 == config.Modules.Length) { return string.Empty; }
|
||||
var match = Array.Find(config.Modules[0].Channels, x => x.Number == index);
|
||||
if (null == match) { return string.Empty; }
|
||||
return string.IsNullOrWhiteSpace(match.UserChannelName) ? match.IsoChannelName : match.UserChannelName;
|
||||
}
|
||||
|
||||
private const int MAX_TMATS_FILE_LENGTH = 32000;
|
||||
public override bool IsSlice6AirTc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public override int GetMaxFileLengthTMATS()
|
||||
{
|
||||
return MAX_TMATS_FILE_LENGTH;
|
||||
}
|
||||
public bool AlignUDPToPPS { get; set; }
|
||||
public override bool SupportsRemoveLeapSeconds => true;
|
||||
public override bool SupportsADCSamplesPerPacket => true;
|
||||
protected override bool RequiresNon0QualificationSamples => true;
|
||||
protected override byte[] GetRTChannelIndices(RealTimeAsyncPacket packet)
|
||||
{
|
||||
switch(_maxModuleCount)
|
||||
{
|
||||
case 0:
|
||||
return new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
|
||||
case 1:
|
||||
return new byte[] { 0, 1, 2, 3, 4, 5 ,6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
|
||||
case 2:
|
||||
default:
|
||||
return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
|
||||
|
||||
}
|
||||
}
|
||||
protected override IGetRealtimeSamples GetRealtimeSamplesClass(DTS.Common.Interface.DASFactory.ICommunication iCommunication, bool bPolling = false)
|
||||
{
|
||||
if (IsCommandSupported(ProtocolLimitedCommands.StartRealtimeStream) && !bPolling)
|
||||
{
|
||||
return new RealtimeStreamingNextSamples(iCommunication) { SignedData = true };
|
||||
}
|
||||
return base.GetRealtimeSamplesClass(this, bPolling);
|
||||
}
|
||||
public override void SetIsStreamingSupported(bool supported = false)
|
||||
{
|
||||
IsStreamingSupported = true;
|
||||
}
|
||||
///// <summary>
|
||||
///// the order of this DAS among multiple das
|
||||
///// </summary>
|
||||
//public int DASIndex { get; set; } = -1;
|
||||
|
||||
public override void InitMinProto()
|
||||
{
|
||||
// SLICE 6.0 Protocol Limitations
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AutoArm] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AutoArmRepeatEnable] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SetDefaultMIF] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.FileData] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.StackSensors] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.BaseSystemTime] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.TestCommunication] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.StackLowPowerMode] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SetRealtimeSampleRate] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SLICE2_OneWireID] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.HardwareRevision] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.HardwareConfiguration] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.EventFaultFlags] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.EventArmAttempts] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.QueryActualSampleRateImmediate] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.InitHardwareInputLines] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.VoltageSysAttributes] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AttributeStoreBlocks] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.MaxEvents] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AutoArmDiagnosticDelay] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.StackChannelAutoArmDiagLevel] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.FlashClear] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.MultipleSamplesRealtime] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.BaseCalibrationDate] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.IgnoreShortedStartEvent] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.ResetAttributeStore] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.PTPTimestamp] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.StartRealtimeStream] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.UDPRealtimeStream] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.GenerateEvent] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.PTPSyncStatus] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SetClockSyncConfig] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SetDSPFilterSettings] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.PTPDomainID] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.RemoveLeapSeconds] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.UDPAlignOnPPS] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.ADCSamplesPerPacket] = SLICE6AIRTC.ADC_SAMPLES_PER_PACKET_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.GetUARTSettings] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.SetUARTSettings] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AutoArmUDPSetting] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
SLICE6AIR_TC_MinimumProtocols[ProtocolLimitedCommands.AutoArmRecordDelay] = SLICE6AIRTC.MIN_PROTOCOL_VER;
|
||||
|
||||
MinimumProtocols = SLICE6AIR_TC_MinimumProtocols;
|
||||
}
|
||||
protected class S6ATCConfigAttributes : SLICE6ConfigAttributes
|
||||
{
|
||||
public override void ConfigureCoupling(bool[] IsACCoupledArray)
|
||||
{
|
||||
//not supported in S6ATC - so NOOP
|
||||
}
|
||||
public override void ConfigureBridge(byte[] bridgeModeArray)
|
||||
{
|
||||
//not supported in S6A-TC - so NOOP
|
||||
}
|
||||
public override void ConfigureBridgeResistance(ushort[] BridgeResistanceArray)
|
||||
{
|
||||
//not supported in S6A-TC - so NOOP
|
||||
}
|
||||
|
||||
public S6ATCConfigAttributes(ICommunication _com) : base(_com) { }
|
||||
}
|
||||
|
||||
protected override ConfigAttributes GetConfigAttributes(ICommunication com)
|
||||
{
|
||||
return new S6ATCConfigAttributes(this);
|
||||
}
|
||||
#region protocol settings/overrides
|
||||
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICE6AIR_TC_MinimumProtocols =
|
||||
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
||||
|
||||
protected override int MIN_PROTOCOL_TMATS_INTERVAL => SLICE6AIRBR.MIN_PROTOCOL_VER;
|
||||
|
||||
private uint maxSampleRateHz = 0;
|
||||
protected override uint MaxSampleRateHz
|
||||
{
|
||||
get
|
||||
{
|
||||
if (0 == maxSampleRateHz)
|
||||
{
|
||||
try
|
||||
{
|
||||
var qsa = new QuerySystemAttributeSLICE6(this)
|
||||
{
|
||||
Key = AttributeTypes.SystemAttributesSLICE6.MaximumSampleRate
|
||||
};
|
||||
qsa.SyncExecute();
|
||||
maxSampleRateHz = (uint)qsa.Value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("Error getting S6A-BR max sample rate, returning 50K");
|
||||
APILogger.LogException(ex);
|
||||
return 50000;
|
||||
}
|
||||
}
|
||||
return maxSampleRateHz;
|
||||
}
|
||||
}
|
||||
void IDASReconfigure.SetMaxModuleCount(int count)
|
||||
{
|
||||
SetMaxModuleCount(count, false);
|
||||
_maxModuleCount = count;
|
||||
}
|
||||
private int _maxModuleCount = -1;
|
||||
/// <summary>
|
||||
/// gets the physical max number of modules.
|
||||
/// this value is cached
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int IDASReconfigure.GetMaxModuleCount()
|
||||
{
|
||||
_maxModuleCount = GetMaxModuleCount(_maxModuleCount);
|
||||
return _maxModuleCount;
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected override DASModule MakeConfigModuleFromInfoModule(InfoResult.Module infoModule)
|
||||
{
|
||||
var configModule = new DASModule(infoModule.ModuleArrayIndex, this);
|
||||
configModule.Channels = new DASChannel[infoModule.NumberOfChannels];
|
||||
|
||||
for (var i = 0; i < infoModule.NumberOfChannels; i++)
|
||||
{
|
||||
if (ModuleType.StreamOut == configModule.ModuleType())
|
||||
{
|
||||
var streamOutChannel = new StreamOutputDASChannel(configModule, i);
|
||||
configModule.Channels[i] = streamOutChannel;
|
||||
}
|
||||
else if ( ModuleType.UART == configModule.ModuleType())
|
||||
{
|
||||
configModule.Channels[i] = new UARTInputDASChannel(configModule, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
var channel = new AnalogInputDASChannel(configModule, i);
|
||||
|
||||
channel.SupportedBridges = new SensorConstants.BridgeType[]
|
||||
{
|
||||
SensorConstants.BridgeType.FullBridge,
|
||||
SensorConstants.BridgeType.HalfBridge,
|
||||
};
|
||||
configModule.Channels[i] = channel;
|
||||
}
|
||||
}
|
||||
|
||||
return configModule;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// we can probably simplify and take common items (slice6+slice1) out of this function, but for now
|
||||
/// it's mostly a copy of SLICE1.AsyncConfigure
|
||||
/// </summary>
|
||||
/// <param name="configAsyncInfo"></param>
|
||||
protected override void AsyncConfigure(object configAsyncInfo)
|
||||
{
|
||||
var info = configAsyncInfo as SliceConfigServiceAsyncInfo;
|
||||
SetUDPAlignOnPPS();
|
||||
SetRemoveSeconds();
|
||||
SetADCSamplesPerPacket(info.StreamADCPerPacket[this]);
|
||||
|
||||
//12638 DAS does not record data in recorder mode during calibration ~ 40% of time.
|
||||
//for SLICE6 we call reseteventlist here, prior to configuring and NOT before arming
|
||||
ResetEventListPriorToConfigure();
|
||||
|
||||
int progressValue = 0;
|
||||
bool bReleased = true;
|
||||
|
||||
if (IsCommandSupported(ProtocolLimitedCommands.ProgramStackChannels))
|
||||
{
|
||||
ReconfigureAccordingToConfig();
|
||||
}
|
||||
|
||||
PresetSampleRate();
|
||||
|
||||
SetVoltageRequirements();
|
||||
|
||||
SetPolarity();
|
||||
|
||||
SetArmDisableShortCheck();
|
||||
|
||||
try
|
||||
{
|
||||
Lock();
|
||||
bReleased = false;
|
||||
// loop thru the modules (slices) and configure the non-UART channels
|
||||
var numChannels = DASInfo.Modules.Sum(mod => mod.NumberOfChannels);
|
||||
var numStreamingChannels = DASInfo.Modules.Sum(mod => ModuleType.StreamOut == mod.TypeOfModule ? mod.NumberOfChannels : 0);
|
||||
var numUart = DASInfo.Modules.Sum(mod => ModuleType.UART == mod.TypeOfModule ? mod.NumberOfChannels : 0);
|
||||
var rangeArray = new float[numChannels];
|
||||
var bridgeModeArray = new byte[numChannels];
|
||||
var BridgeResistanceArray = new ushort[numChannels];
|
||||
var IsACCoupledArray = new bool[numChannels];
|
||||
//18294 Implement Bridge AC / DC coupling(fw update dependent)
|
||||
var bridgeACCouplingArray = new bool[numChannels];
|
||||
// level trigger values
|
||||
var enableLowerLevelTriggerThreshold = new bool[numChannels];
|
||||
var enableUpperLevelTriggerThreshold = new bool[numChannels];
|
||||
var lowerLevelTriggerThreshold = new float[numChannels];
|
||||
var upperLevelTriggerThreshold = new float[numChannels];
|
||||
var qualificationSamples = new int[numChannels];
|
||||
|
||||
var diagnosticChannels = new List<byte>();
|
||||
|
||||
var bModified = false;
|
||||
CommonConfigureWork(diagnosticChannels, qualificationSamples, ref bReleased,
|
||||
info, bridgeModeArray, IsACCoupledArray, BridgeResistanceArray,
|
||||
ref bModified, rangeArray, enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold,
|
||||
enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold, bridgeACCouplingArray);
|
||||
if (bReleased) { return; }
|
||||
// report progress
|
||||
progressValue = 5;
|
||||
info.Progress(progressValue);
|
||||
|
||||
StoreConfigAttributes(info, rangeArray, ref bReleased, ref progressValue, bridgeModeArray,
|
||||
IsACCoupledArray, BridgeResistanceArray, enableLowerLevelTriggerThreshold, lowerLevelTriggerThreshold,
|
||||
enableUpperLevelTriggerThreshold, upperLevelTriggerThreshold, qualificationSamples, numChannels,
|
||||
out var config, bridgeACCouplingArray, numUart, numStreamingChannels);
|
||||
|
||||
progressValue = 20;
|
||||
info.Progress(progressValue);
|
||||
|
||||
RemainingConfigWork(ref progressValue, info, diagnosticChannels, config, ref bReleased, null, null, null);
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!bReleased)
|
||||
{
|
||||
bReleased = true;
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
info.Progress(100);
|
||||
info.Success();
|
||||
}
|
||||
/// <summary>
|
||||
/// returns true if the device is known to be streaming
|
||||
/// does not query device, just returns a flag if it has been set
|
||||
/// </summary>
|
||||
public override bool GetIsStreaming()
|
||||
{
|
||||
if (null == DASArmStatus) { return false; }
|
||||
//18852 Cannot use Stop streaming / (Dis)Auto Arm button if one or more DAS is idle
|
||||
//can't rely on just having received invalid mode, QATS will still have a status of realtime
|
||||
//when streaming, so we'll use either for now.
|
||||
return DASArmStatus.ReceivedInvalidModeDuringSetup || DASArmStatus.IsInRealtime;
|
||||
}
|
||||
public override int[] GetStackChannelConfigTypes()
|
||||
{
|
||||
try
|
||||
{
|
||||
var queryChannelTypes = new QueryArmAttribute(this) { Key = AttributeTypes.ArmAndEventAttributes.StackChannelConfigType };
|
||||
queryChannelTypes.SyncExecute();
|
||||
|
||||
var list = new List<int>();
|
||||
if (queryChannelTypes.Value is byte[] bytes)
|
||||
{
|
||||
foreach (var channelType in bytes)
|
||||
{
|
||||
list.Add(channelType);
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
return new int[] { 0 };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2218
DataPRO/IService/Classes/SLICE/SLICE6DB.cs
Normal file
2218
DataPRO/IService/Classes/SLICE/SLICE6DB.cs
Normal file
File diff suppressed because it is too large
Load Diff
41
DataPRO/IService/Classes/SLICE/SLICE6DB3.cs
Normal file
41
DataPRO/IService/Classes/SLICE/SLICE6DB3.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// SLICE6DB3 is a limited version of SLICE6DB, it notably does not have ie1588/ptp support
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class SLICE6DB3<T> : SLICE6DB<T>
|
||||
where T : IConnection,
|
||||
new()
|
||||
{
|
||||
|
||||
|
||||
#region IClockSyncActions
|
||||
public override void SetClockSyncConfig(ServiceCallback callback, object userData, ClockSyncProfile profile)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData) { functionData = profile };
|
||||
info.Success();
|
||||
}
|
||||
|
||||
public override void GetClockSyncStatus(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
public override void SetPTPDomainID(ServiceCallback callback, object userData, byte domainID)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData) { functionData = domainID };
|
||||
info.Success();
|
||||
}
|
||||
|
||||
public override void GetPTPDomainID(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
95
DataPRO/IService/Classes/SLICE/SLICEPRODB.cs
Normal file
95
DataPRO/IService/Classes/SLICE/SLICEPRODB.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.Communication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.DASLib.Service.Interfaces;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class SLICEPRODB<T> : SLICE6DB<T>,
|
||||
IDownloadActions
|
||||
where T : IConnection,
|
||||
new()
|
||||
{
|
||||
/// <summary>
|
||||
/// populates the connected devices field
|
||||
/// </summary>
|
||||
public override void QueryConnectedDevices()
|
||||
{
|
||||
//no functionality for this with SLICEPRO DB
|
||||
var connectedDevices = new List<IDASConnectedDevice>();
|
||||
((ICommunication)this).DASInfo.SetConnectedDevices(connectedDevices.ToArray());
|
||||
}
|
||||
|
||||
public override bool IsSlice6Distributor()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool IsBattery()
|
||||
{
|
||||
//um maybe?
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void AsyncQueryConfiguration(object configAsyncInfo)
|
||||
{
|
||||
var info = (SliceServiceAsyncInfo)configAsyncInfo;
|
||||
|
||||
InitMinProto(); _haveInited = true;
|
||||
ConfigData = MakeDefaultConfigFromInfo();
|
||||
info.Success();
|
||||
}
|
||||
|
||||
protected override bool SupportsTemperatureCheck => true;
|
||||
protected override bool SupportsTiltCheck => true;
|
||||
protected override bool SupportsClockSyncCheck => true;
|
||||
public override bool SupportsTimeSynchronization => false;
|
||||
|
||||
private const int MIN_PROTOCOL_VER = 1;
|
||||
|
||||
private readonly Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte> SLICEPRODB_MinProtocols =
|
||||
new Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>();
|
||||
|
||||
public override void InitMinProto()
|
||||
{
|
||||
// SLICE 6 DB Protocol Limitations
|
||||
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseSystemTime] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SLICE2_OneWireID] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.HardwareConfiguration] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventFaultFlags] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EventArmAttempts] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryActualSampleRateImmediate] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.VoltageSysAttributes] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryArmAndTriggerStatus_VoltageReadings] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.BaseCalibrationDate] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.IgnoreShortedStartEvent] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.ResetAttributeStore] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.MeasureBaseDiagnosticChannel] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InSliceTemperatureCPre] = byte.MaxValue;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.FileData] = MIN_PROTOCOL_VER;
|
||||
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.PTPSyncStatus] = byte.MaxValue;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.SetClockSyncConfig] = byte.MaxValue;
|
||||
|
||||
// SLICE_DB Protocol Limitations
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.Arm] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.EnableFaultChecking] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.OnOverride] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.OMAP_GPIO] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryBatteryVoltage] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream] = MIN_PROTOCOL_VER;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryEthernetMacTable] = byte.MaxValue;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTempLogFile] = byte.MaxValue;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryTiltSensorData] = byte.MaxValue;
|
||||
SLICEPRODB_MinProtocols[DFConstantsAndEnums.ProtocolLimitedCommands.QueryExternalTiltInfo] = byte.MaxValue;
|
||||
MinimumProtocols = SLICEPRODB_MinProtocols;
|
||||
}
|
||||
}
|
||||
}
|
||||
854
DataPRO/IService/Classes/SLICE/SLICERecorder.cs
Normal file
854
DataPRO/IService/Classes/SLICE/SLICERecorder.cs
Normal file
@@ -0,0 +1,854 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Service;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Utilities;
|
||||
using DTS.Common.Utils;
|
||||
using DTS.DASLib.Command.SLICE.DownloadCommands;
|
||||
using DTS.DASLib.Command.SLICE.RealtimeCommands;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service.FirmwareUtility
|
||||
{
|
||||
#region SLICE Recorder class
|
||||
public class SLICERecorder
|
||||
{
|
||||
private ICommunication unit;
|
||||
public delegate void SetAttributeMethod(object val);
|
||||
|
||||
public SLICERecorder(DTS.Common.Interface.DASFactory.ICommunication _unit)
|
||||
{
|
||||
unit = _unit;
|
||||
}
|
||||
|
||||
public ushort EventNumber { get; set; }
|
||||
|
||||
public void QueryFirmwareVersion(out string firmwareversion)
|
||||
{
|
||||
var fvq = new QueryFirmwareVersion(unit);
|
||||
fvq.SyncExecute();
|
||||
firmwareversion = fvq.Version;
|
||||
}
|
||||
|
||||
public void QuerySerialNumber(out string serialnumber)
|
||||
{
|
||||
var snq = new QuerySerialNumber(unit);
|
||||
snq.SyncExecute();
|
||||
serialnumber = snq.SerialNumber;
|
||||
}
|
||||
|
||||
public void RunFlashSelfTest(UInt32 BlocksToTest, out double[] BlockTimingMicroSeconds)
|
||||
{
|
||||
const UInt32 skip = 4;
|
||||
const UInt32 FirstSector = 827392 + skip;
|
||||
|
||||
// Have the recorder run the test
|
||||
var fstest = new SelfTestFlash(unit);
|
||||
fstest.BlocksToTest = BlocksToTest;
|
||||
fstest.SyncExecute();
|
||||
|
||||
// Pick up the results, skipping skip
|
||||
BlocksToTest -= skip;
|
||||
BlockTimingMicroSeconds = new double[BlocksToTest - 1];
|
||||
|
||||
ulong[] ticks = new ulong[BlocksToTest];
|
||||
var flashread = new ReadArbitraryFlash(unit);
|
||||
|
||||
for (UInt32 CurrentSector = 0; CurrentSector < BlocksToTest; CurrentSector++)
|
||||
{
|
||||
flashread.Address = (CurrentSector + FirstSector) * 512;
|
||||
flashread.Length = 16;
|
||||
|
||||
flashread.SyncExecute();
|
||||
byte[] u64 = new byte[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
u64[i] = flashread.Data[2 * i + 1];
|
||||
}
|
||||
ByteConvertor.Convert(u64, 0, out ticks[(int)CurrentSector]);
|
||||
}
|
||||
|
||||
for (UInt32 CurrentSector = 0; CurrentSector < BlocksToTest - 1; CurrentSector++)
|
||||
{
|
||||
BlockTimingMicroSeconds[(int)CurrentSector] = (ticks[(int)CurrentSector + 1] - ticks[(int)CurrentSector]) / 10.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void QuerySystemAttributes(out Dictionary<AttributeTypes.SystemAttributes, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QuerySystemAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributes, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributes)key;
|
||||
var query = new QuerySystemAttribute(unit);
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttribute(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QuerySystemAttributes_SLICE6DB(out Dictionary<AttributeTypes.SystemAttributesSLICE6DB, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QuerySystemAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributesSLICE6DB, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributesSLICE6DB)key;
|
||||
var query = new QuerySystemAttributeSLICE6DB(unit);
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttributeSLICE6DB(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QuerySystemAttributes_SLICE6AIR(out Dictionary<AttributeTypes.SystemAttributesSLICE6AIR, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QuerySystemAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributesSLICE6AIR, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributesSLICE6AIR)key;
|
||||
var query = new QuerySystemAttributeSLICE6AIR(unit);
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttributeSLICE6AIR(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QuerySystemAttributes_SLICE6(out Dictionary<AttributeTypes.SystemAttributesSLICE6, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QuerySystemAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributesSLICE6, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributesSLICE6)key;
|
||||
var query = new QuerySystemAttributeSLICE6(unit);
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttributeSLICE6(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QuerySystemAttributes_SLICE2(out Dictionary<AttributeTypes.SystemAttributesSLICE2, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QuerySystemAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributesSLICE2, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributesSLICE2)key;
|
||||
var query = new QuerySystemAttributeSLICE2(unit);
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttributeSLICE2(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryBridgeAttributes_SLICE2(byte bridgeID, out Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE2, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = System.Enum.GetValues(typeof(AttributeTypes.SystemAttributes_Bridge_SLICE2));
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE2, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributes_Bridge_SLICE2)key;
|
||||
var query = new QuerySystemAttribute_Slice2Bridge(unit);
|
||||
query.DeviceID = bridgeID;
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttribute_Bridge_SLICE2(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryBridgeAttributes_TOM(byte bridgeID, out Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE_TOM, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = System.Enum.GetValues(typeof(AttributeTypes.SystemAttributes_Bridge_SLICE_TOM));
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE_TOM, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributes_Bridge_SLICE_TOM)key;
|
||||
var query = new QuerySystemAttribute_Slice_TOM(unit);
|
||||
query.DeviceID = bridgeID;
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttributes_Bridge_SLICE_TOM(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryBridgeAttributes(byte bridgeID, out Dictionary<AttributeTypes.SystemAttributes_Bridge, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = System.Enum.GetValues(typeof(AttributeTypes.SystemAttributes_Bridge));
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributes_Bridge, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributes_Bridge)key;
|
||||
var query = new QuerySystemAttribute_Bridge(unit);
|
||||
query.DeviceID = bridgeID;
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttribute_Bridge(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public delegate object UpdateAttribute(object value, bool overwrite);
|
||||
|
||||
public void SetSystemAttribute(AttributeTypes.SystemAttributes key, object value, bool ShouldOverwrite)
|
||||
{
|
||||
var set = new SetSystemAttribute(unit);
|
||||
set.SetValue(key, value, ShouldOverwrite);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void SetUserAttribute(AttributeTypes.SliceUserAttributes key, object value, bool ShouldOverwrite)
|
||||
{
|
||||
var set = new SetUserAttribute(unit);
|
||||
set.SetValue(key, value, ShouldOverwrite);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void QueryUserAttributes(out Dictionary<AttributeTypes.SliceUserAttributes, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QueryUserAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SliceUserAttributes, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SliceUserAttributes)key;
|
||||
var query = new QueryUserAttribute(unit);
|
||||
query.Key = (AttributeTypes.SliceUserAttributes)key;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetUserAttribute(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryArmAttributes(out Dictionary<AttributeTypes.ArmAndEventAttributes, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = new QueryArmAttributeKeys(unit);
|
||||
getKeys.SyncExecute();
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.ArmAndEventAttributes, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.ArmAndEventAttributes)key;
|
||||
var query = new QueryArmAttribute(unit);
|
||||
query.Key = (AttributeTypes.ArmAndEventAttributes)key;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetArmAttribute(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, object value, bool ShouldOverwrite)
|
||||
{
|
||||
var set = new SetArmAttribute(unit);
|
||||
set.SetValue(key, value, ShouldOverwrite);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void QueryEventAttributes(ushort EventNumber, out Dictionary<AttributeTypes.ArmAndEventAttributes, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
ushort TotalEvents;
|
||||
attributes = new Dictionary<AttributeTypes.ArmAndEventAttributes, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
keys = new List<int>();
|
||||
|
||||
GetTotalEventsStored(out TotalEvents);
|
||||
if (0 == TotalEvents) return;
|
||||
|
||||
var getKeys = new QueryEventAttributeKeys(unit);
|
||||
getKeys.EventNumber = EventNumber;
|
||||
getKeys.SyncExecute();
|
||||
|
||||
foreach (ushort key in getKeys.Keys)
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.ArmAndEventAttributes)key;
|
||||
var query = new QueryEventAttribute(unit);
|
||||
query.EventNumber = EventNumber;
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetEventAttribute(unit);
|
||||
attrSet.EventNumber = EventNumber;
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEventAttribute(ushort EventNumber, AttributeTypes.ArmAndEventAttributes key, object value, bool ShouldOverwrite)
|
||||
{
|
||||
var set = new SetEventAttribute(unit);
|
||||
set.EventNumber = EventNumber;
|
||||
set.SetValue(key, value, ShouldOverwrite);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void SetAntiAliasFilterImmediately(float cutoffFrequencyHz)
|
||||
{
|
||||
var aafilterSet = new SetAAFilterImmediate(unit);
|
||||
aafilterSet.FrequencyHz = cutoffFrequencyHz;
|
||||
aafilterSet.SyncExecute();
|
||||
}
|
||||
|
||||
public void ResetEventList()
|
||||
{
|
||||
var reset = new ResetEventList(unit);
|
||||
reset.SyncExecute();
|
||||
}
|
||||
|
||||
public void Arm()
|
||||
{
|
||||
var arm = new Arm(unit);
|
||||
arm.SyncExecute();
|
||||
}
|
||||
|
||||
public void Disarm()
|
||||
{
|
||||
var disarm = new Disarm(unit);
|
||||
disarm.SyncExecute();
|
||||
}
|
||||
|
||||
public void GetSingleSample(out short[] adc, out int channels)
|
||||
{
|
||||
var ss = new RetrieveSingleSample(unit);
|
||||
ss.SyncExecute();
|
||||
channels = ss.Channels;
|
||||
adc = new short[channels];
|
||||
for (int i = 0; i < channels; i++)
|
||||
{
|
||||
adc[i] = ss.GetChannelData(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetTotalEventsStored(out ushort TotalEvents)
|
||||
{
|
||||
var eventCountQuery = new QuerySystemAttribute(unit);
|
||||
eventCountQuery.Key = AttributeTypes.SystemAttributes.TotalEventsStored;
|
||||
eventCountQuery.SyncExecute();
|
||||
|
||||
TotalEvents = (ushort)eventCountQuery.Value;
|
||||
}
|
||||
|
||||
public void GetTotalChannelsByEvent(ushort EventNumberFromZero, out byte TotalChannels)
|
||||
{
|
||||
ushort TotalEvents;
|
||||
GetTotalEventsStored(out TotalEvents);
|
||||
if (TotalEvents <= EventNumberFromZero)
|
||||
{
|
||||
TotalChannels = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var totalChannelsQuery = new QueryEventAttribute(unit);
|
||||
totalChannelsQuery.EventNumber = EventNumberFromZero;
|
||||
totalChannelsQuery.Key = AttributeTypes.ArmAndEventAttributes.TotalChannels;
|
||||
totalChannelsQuery.SyncExecute();
|
||||
TotalChannels = (byte)totalChannelsQuery.Value;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public bool IsEventAlreadyStored(ushort EventNumberFromZero)
|
||||
{
|
||||
ushort TotalEvents;
|
||||
GetTotalEventsStored(out TotalEvents);
|
||||
return (TotalEvents > EventNumberFromZero);
|
||||
}
|
||||
|
||||
public bool IsChannelValidForEvent(ushort EventNumberFromZero, byte ChannelNumberFromZero)
|
||||
{
|
||||
byte TotalChannels;
|
||||
GetTotalChannelsByEvent(EventNumberFromZero, out TotalChannels);
|
||||
return (ChannelNumberFromZero <= TotalChannels);
|
||||
}
|
||||
|
||||
public void QueryEventDescription(ushort EventNumberFromZero, out string EventDescription)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
EventDescription = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the EventDescription event attribute
|
||||
var descriptionQuery = new QueryEventAttribute(unit);
|
||||
descriptionQuery.EventNumber = EventNumberFromZero;
|
||||
descriptionQuery.Key = AttributeTypes.ArmAndEventAttributes.Description;
|
||||
descriptionQuery.SyncExecute();
|
||||
|
||||
if (null == descriptionQuery.Value)
|
||||
{
|
||||
EventDescription = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
EventDescription = (string)descriptionQuery.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryEventID(ushort EventNumberFromZero, out string EventID)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
EventID = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the EventDescription event attribute
|
||||
var idQuery = new QueryEventAttribute(unit);
|
||||
idQuery.EventNumber = EventNumberFromZero;
|
||||
idQuery.Key = AttributeTypes.ArmAndEventAttributes.Name;
|
||||
idQuery.SyncExecute();
|
||||
|
||||
if (null == idQuery.Value)
|
||||
{
|
||||
EventID = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
EventID = (string)idQuery.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void QueryEventSampleRate(ushort EventNumberFromZero, out UInt32 SampleRate)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
SampleRate = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the EventDescription event attribute
|
||||
var sampleRateQuery = new QueryEventAttribute(unit);
|
||||
sampleRateQuery.EventNumber = EventNumberFromZero;
|
||||
sampleRateQuery.Key = AttributeTypes.ArmAndEventAttributes.SampleRate;
|
||||
sampleRateQuery.SyncExecute();
|
||||
|
||||
if (null == sampleRateQuery.Value)
|
||||
{
|
||||
SampleRate = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SampleRate = (UInt32)sampleRateQuery.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetPreTriggerSamplesByEvent(ushort EventNumberFromZero, out ulong PreTriggerSamples)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
PreTriggerSamples = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the TotalSamples event attribute
|
||||
var preTriggerSamplesQuery = new QueryEventAttribute(unit);
|
||||
preTriggerSamplesQuery.EventNumber = EventNumberFromZero;
|
||||
preTriggerSamplesQuery.Key = AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested;
|
||||
preTriggerSamplesQuery.SyncExecute();
|
||||
|
||||
if (null == preTriggerSamplesQuery.Value)
|
||||
{
|
||||
PreTriggerSamples = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PreTriggerSamples = (ulong)preTriggerSamplesQuery.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetPostTriggerSamplesByEvent(ushort EventNumberFromZero, out ulong PostTriggerSamples)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
PostTriggerSamples = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the TotalSamples event attribute
|
||||
var postTriggerSamplesQuery = new QueryEventAttribute(unit);
|
||||
postTriggerSamplesQuery.EventNumber = EventNumberFromZero;
|
||||
postTriggerSamplesQuery.Key = AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested;
|
||||
postTriggerSamplesQuery.SyncExecute();
|
||||
|
||||
if (null == postTriggerSamplesQuery.Value)
|
||||
{
|
||||
PostTriggerSamples = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PostTriggerSamples = (ulong)postTriggerSamplesQuery.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetTotalSamplesByEvent(ushort EventNumberFromZero, out ulong TotalSamples)
|
||||
{
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
TotalSamples = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Query the TotalSamples event attribute
|
||||
var totalSamplesQuery = new QueryEventAttribute(unit);
|
||||
totalSamplesQuery.EventNumber = EventNumberFromZero;
|
||||
totalSamplesQuery.Key = AttributeTypes.ArmAndEventAttributes.TotalSamplesRecorded;
|
||||
try
|
||||
{
|
||||
totalSamplesQuery.SyncExecute();
|
||||
TotalSamples = (ulong)totalSamplesQuery.Value;
|
||||
}
|
||||
|
||||
// Store the value in the out param, but take care because it may not
|
||||
// have been stored in the event's attribute store
|
||||
catch
|
||||
{
|
||||
TotalSamples = 0;
|
||||
}
|
||||
|
||||
// If the param is 0, fake it by summing pre and post trigger samples
|
||||
// requested for the event
|
||||
if (0 == TotalSamples)
|
||||
{
|
||||
ulong PreTriggerSamples, PostTriggerSamples;
|
||||
GetPreTriggerSamplesByEvent(EventNumberFromZero, out PreTriggerSamples);
|
||||
GetPostTriggerSamplesByEvent(EventNumberFromZero, out PostTriggerSamples);
|
||||
|
||||
TotalSamples = PreTriggerSamples + PostTriggerSamples;
|
||||
}
|
||||
}
|
||||
|
||||
public void GetEventDataByChannel(ushort EventNumberFromZero, byte ChannelNumberFromZero, out short[] adc)
|
||||
{
|
||||
// Make sure the channel is valid for the event requested
|
||||
if (false == IsChannelValidForEvent(EventNumberFromZero, ChannelNumberFromZero))
|
||||
{
|
||||
adc = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Grab all the event data for the event
|
||||
List<short[]> adc_all;
|
||||
GetEventDataByEvent(EventNumberFromZero, out adc_all);
|
||||
|
||||
if (null == adc_all)
|
||||
{
|
||||
adc = null;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
adc = new short[adc_all[0].Length];
|
||||
}
|
||||
|
||||
// Copy out the requested channel
|
||||
Buffer.BlockCopy(adc_all[ChannelNumberFromZero], 0, adc, 0, 2 * adc_all[ChannelNumberFromZero].Length);
|
||||
}
|
||||
|
||||
public void GetEventDataByEvent(ushort EventNumberFromZero, out List<short[]> adc)
|
||||
{
|
||||
// Figure out how many samples are stored and then ...
|
||||
ulong TotalSamples;
|
||||
GetTotalSamplesByEvent(EventNumberFromZero, out TotalSamples);
|
||||
|
||||
// Grab them all
|
||||
GetEventSampleRangeByEvent(EventNumberFromZero, out adc, 0, TotalSamples - 1);
|
||||
}
|
||||
|
||||
public QueryEventDataBase GetQueryEventData(DTS.Common.Interface.DASFactory.ICommunication unit)
|
||||
{
|
||||
return new QueryEventDataBase(unit, QueryEventDataBase.Default_IO_Timeout);
|
||||
//need to do something else if unit is slice2 ...
|
||||
}
|
||||
public void GetEventSampleRangeByEvent(ushort EventNumberFromZero, out List<short[]> adc,
|
||||
ulong FirstSample, ulong LastSample)
|
||||
{
|
||||
if (FirstSample > LastSample)
|
||||
{
|
||||
adc = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the event is valid
|
||||
if (false == IsEventAlreadyStored(EventNumberFromZero))
|
||||
{
|
||||
adc = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out how many samples are stored
|
||||
ulong TotalSamples;
|
||||
GetTotalSamplesByEvent(EventNumberFromZero, out TotalSamples);
|
||||
|
||||
// Make sure the samples requested are in the available window
|
||||
ulong SamplesToGet = LastSample - FirstSample + 1;
|
||||
if (FirstSample + SamplesToGet > TotalSamples)
|
||||
{
|
||||
adc = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out how many channels were stored
|
||||
byte channels;
|
||||
GetTotalChannelsByEvent(EventNumberFromZero, out channels);
|
||||
|
||||
// Grab the data
|
||||
//var dataQuery = new QueryEventData(unit);
|
||||
var dataQuery = GetQueryEventData(unit);
|
||||
dataQuery.EventNumber = EventNumberFromZero;
|
||||
dataQuery.LastSample = LastSample;
|
||||
dataQuery.ChannelsDownloaded = channels;
|
||||
|
||||
ulong SamplesGotten = 0;
|
||||
adc = null;
|
||||
while (SamplesGotten < SamplesToGet)
|
||||
{
|
||||
dataQuery.FirstSample = SamplesGotten;
|
||||
dataQuery.SyncExecute();
|
||||
ulong SamplesThisTime = 0;
|
||||
if (null == adc)
|
||||
{
|
||||
adc = new List<short[]>(dataQuery.ChannelsDownloaded);
|
||||
for (int i = 0; i < adc.Capacity; i++)
|
||||
{
|
||||
adc.Add(new short[SamplesToGet]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < dataQuery.ChannelsDownloaded; i++)
|
||||
{
|
||||
short[] tmp;
|
||||
dataQuery.GetChannelData(i, out tmp);
|
||||
SamplesThisTime = (ulong)tmp.Length;
|
||||
Buffer.BlockCopy(tmp, 0, adc[i], (int)(2 * SamplesGotten),
|
||||
tmp.Length > (int)(SamplesToGet - SamplesGotten) ? (int)(2 * (SamplesToGet - SamplesGotten)) : 2 * tmp.Length);
|
||||
}
|
||||
|
||||
SamplesGotten += SamplesThisTime;
|
||||
}
|
||||
}
|
||||
|
||||
#region private members
|
||||
// empty
|
||||
#endregion
|
||||
|
||||
public void QueryBridgeAttributes_SLICE2_GEN3(byte bridgeID, out Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE2_GEN3, object> attributes, out List<SetAttributeMethod> setmethods, out List<int> keys)
|
||||
{
|
||||
var getKeys = System.Enum.GetValues(typeof(AttributeTypes.SystemAttributes_Bridge_SLICE2_GEN3));
|
||||
keys = new List<int>();
|
||||
attributes = new Dictionary<AttributeTypes.SystemAttributes_Bridge_SLICE2_GEN3, object>();
|
||||
setmethods = new List<SetAttributeMethod>();
|
||||
|
||||
foreach (ushort key in getKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
var CurrentAttribute = (AttributeTypes.SystemAttributes_Bridge_SLICE2_GEN3)key;
|
||||
var query = new QuerySystemAttribute_Slice2Bridge_GEN3(unit);
|
||||
query.DeviceID = bridgeID;
|
||||
query.Key = CurrentAttribute;
|
||||
query.SyncExecute();
|
||||
attributes.Add(CurrentAttribute, query.Value);
|
||||
keys.Add(key);
|
||||
setmethods.Add(delegate (object val)
|
||||
{
|
||||
var attrSet = new SetSystemAttribute_Slice2Bridge_GEN3(unit);
|
||||
attrSet.SetValue(CurrentAttribute, val, true);
|
||||
attrSet.SyncExecute();
|
||||
});
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
public enum SLICEPRO_Generation
|
||||
{
|
||||
SLICEPRO_GEN2 = 0, // baseType = 0
|
||||
SLICEPRO_GEN3 = 1, // baseType = 0
|
||||
SLICEPRO_REVC = 2 // baseType = 0,3,4 reserve for board 204revC
|
||||
}
|
||||
|
||||
public SLICEPRO_Generation GetSLICEProHardwareVersion(DTS.Common.Interface.DASFactory.ICommunication comm)
|
||||
{
|
||||
byte hardwareVersion = (byte)SLICEPRO_Generation.SLICEPRO_GEN2;
|
||||
if (comm.IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.HardwareRevision))
|
||||
{
|
||||
QuerySystemAttributeSLICE2 qsas2 = new QuerySystemAttributeSLICE2(comm, 1000);
|
||||
qsas2.DeviceGroup = 0;
|
||||
qsas2.DeviceID = 0;
|
||||
qsas2.Key = AttributeTypes.SystemAttributesSLICE2.BaseHardwareRevision;
|
||||
qsas2.SyncExecute();
|
||||
hardwareVersion = (byte)qsas2.Value;
|
||||
}
|
||||
return (SLICEPRO_Generation)hardwareVersion;
|
||||
}
|
||||
|
||||
public enum SLICEPRO_BaseType
|
||||
{
|
||||
SLICEPRO_BASE_SIM = 0,
|
||||
SLICE_NANO_PHRDR = 1,
|
||||
SLICE_BASE_PLUS = 2,
|
||||
SLICEPRO_DIM = 3,
|
||||
SLICEPRO_TOM = 4,
|
||||
// reserve 5 for Trigger Distributor Module which has no com to PC.
|
||||
SLICE6 = 6,
|
||||
SLICE6DB = 7,
|
||||
SLICE6AIR = 8,
|
||||
POWER_PRO = 9,
|
||||
TSRAIR = 10,
|
||||
SLICE6DB_3 = 11,
|
||||
}
|
||||
|
||||
// type
|
||||
public SLICEPRO_BaseType GetSLICEProBaseType(DTS.Common.Interface.DASFactory.ICommunication comm)
|
||||
{
|
||||
byte baseType = (byte)SLICEPRO_BaseType.SLICEPRO_BASE_SIM;
|
||||
|
||||
QuerySystemAttributeSLICE2 qsa = new QuerySystemAttributeSLICE2(comm, 2000);
|
||||
qsa.Key = AttributeTypes.SystemAttributesSLICE2.BaseType;
|
||||
qsa.SyncExecute();
|
||||
baseType = Convert.ToByte(qsa.Value);
|
||||
|
||||
return (SLICEPRO_BaseType)baseType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
2012
DataPRO/IService/Classes/SLICE/SliceDB.cs
Normal file
2012
DataPRO/IService/Classes/SLICE/SliceDB.cs
Normal file
File diff suppressed because it is too large
Load Diff
2476
DataPRO/IService/Classes/SLICE/TSRAIR.cs
Normal file
2476
DataPRO/IService/Classes/SLICE/TSRAIR.cs
Normal file
File diff suppressed because it is too large
Load Diff
2076
DataPRO/IService/Classes/SLICEService/SLICE Service.Arming.cs
Normal file
2076
DataPRO/IService/Classes/SLICEService/SLICE Service.Arming.cs
Normal file
File diff suppressed because it is too large
Load Diff
3697
DataPRO/IService/Classes/SLICEService/SLICE Service.Calibration.cs
Normal file
3697
DataPRO/IService/Classes/SLICEService/SLICE Service.Calibration.cs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2579
DataPRO/IService/Classes/SLICEService/SLICE Service.Configuration.cs
Normal file
2579
DataPRO/IService/Classes/SLICEService/SLICE Service.Configuration.cs
Normal file
File diff suppressed because it is too large
Load Diff
1344
DataPRO/IService/Classes/SLICEService/SLICE Service.Download.cs
Normal file
1344
DataPRO/IService/Classes/SLICEService/SLICE Service.Download.cs
Normal file
File diff suppressed because it is too large
Load Diff
807
DataPRO/IService/Classes/SLICEService/SLICE Service.Public.cs
Normal file
807
DataPRO/IService/Classes/SLICEService/SLICE Service.Public.cs
Normal file
@@ -0,0 +1,807 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.WINUSBConnection;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
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.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.SLICE.RealtimeCommands;
|
||||
using System.Linq;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class Slice<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
public virtual HardwareTypes GetHardwareType()
|
||||
{
|
||||
if (SerialNumber.Contains("BA5"))
|
||||
{
|
||||
return HardwareTypes.SLICE_NANO_Base;
|
||||
}
|
||||
if (SerialNumber.Contains("BA0"))
|
||||
{
|
||||
return HardwareTypes.SLICE_Micro_Base;
|
||||
}
|
||||
if (SerialNumber.StartsWith("SG5"))
|
||||
{
|
||||
return HardwareTypes.SLICE1_G5Stack;
|
||||
}
|
||||
return HardwareTypes.SLICE_Base;
|
||||
}
|
||||
public virtual int[] GetStackChannelConfigTypes()
|
||||
{
|
||||
return new int[] { 0 };
|
||||
}
|
||||
public float InputLowVoltage { get; set; } = 7;
|
||||
|
||||
public float InputMediumVoltage { get; set; } = 11;
|
||||
|
||||
public float InputHighVoltage { get; set; } = 15;
|
||||
|
||||
public float BatteryLowVoltage { get; set; } = 8;
|
||||
|
||||
public float BatteryMediumVoltage { get; set; } = 8.5F;
|
||||
|
||||
public float BatteryHighVoltage { get; set; } = 9;
|
||||
|
||||
public double MinimumValidInputVoltage { get; set; } = 4;
|
||||
|
||||
public virtual double MaximumValidInputVoltage { get; set; } = 19;
|
||||
|
||||
public double MinimumValidBatteryVoltage { get; set; } = 4;
|
||||
|
||||
public double MaximumValidBatteryVoltage { get; set; } = 9;
|
||||
|
||||
#region Configuration
|
||||
|
||||
// our public configure member
|
||||
public IConfigurationData ConfigData { get; set; }
|
||||
|
||||
//FB 25526 moved from SLICE6AIR class so can be used by subtypes
|
||||
/// <summary>
|
||||
/// returns true if the device is using a stream mode (either S6A streaming or record and stream)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ShouldWriteStreamInfo()
|
||||
{
|
||||
if (Array.Exists(ConfigData.Modules, m => RecordingModeExtensions.IsAStreamMode(m.RecordingMode))) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Diagnostics
|
||||
|
||||
// our public diagnostics member
|
||||
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 IBaseInputValues BaseInput { get; set; }
|
||||
|
||||
public IArmCheckActions ArmCheckActions { get; set; }
|
||||
public IArmCheckResults ArmCheckResults { get; set; }
|
||||
public IOptimizationValues OptimizationValues { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Trigger check
|
||||
|
||||
// our public trigger check member
|
||||
public ITriggerCheckResult TriggerResult { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Real time
|
||||
|
||||
// our public real time member
|
||||
public List<int> RealtimeDASChannels { get; set; }
|
||||
|
||||
public List<double> TiltAxisData { get; set; }
|
||||
#endregion
|
||||
|
||||
#region FlashErase
|
||||
|
||||
public FlashEraseStatus DASFlashEraseStatus { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Arming
|
||||
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 virtual 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)
|
||||
{
|
||||
//before we mark it as realtime, check for qats, if we have
|
||||
//qats it's armed, not realtime
|
||||
try
|
||||
{
|
||||
var qats = new QueryArmAndTriggerStatus(this);
|
||||
qats.SyncExecute();
|
||||
if (qats.IsArmed)
|
||||
{
|
||||
SetInArm(WriteToDb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//don't bother logging.
|
||||
}
|
||||
|
||||
if (ExitRealtimeIfPossible)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exitRT = new EndRealtimeMode(this);
|
||||
exitRT.SyncExecute();
|
||||
//presumably we succeeded?
|
||||
//should we turn off power too? I'm not sure, uncomment the following lines to turn off power...
|
||||
//var info = new SliceServiceAsyncInfo((ServiceCallbackData data) => { }, this);
|
||||
//AsyncEnterLowPowerMode(info);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
if (null == DASArmStatus)
|
||||
{
|
||||
var armStatus = new ArmStatus()
|
||||
{
|
||||
IsInRealtime = true
|
||||
};
|
||||
ArmStatus.SetArmStatus(this, armStatus, WriteToDb);
|
||||
}
|
||||
else
|
||||
{
|
||||
DASArmStatus.IsInRealtime = true;
|
||||
if (WriteToDb)
|
||||
{
|
||||
SetDASArmStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
public IArmStatusData DASArmStatus { get; set; }
|
||||
public void SetDASArmStatus(IArmStatusData status, bool bSetInDb)
|
||||
{
|
||||
ArmStatus.SetArmStatus(this, status, bSetInDb);
|
||||
}
|
||||
public void SetDASArmStatus()
|
||||
{
|
||||
//FB 26817
|
||||
if (DASArmStatus.IsArmed)
|
||||
{
|
||||
DASArmStatus.MaxEventsPossible = GetTSRAIRMaxEventsPossible();
|
||||
}
|
||||
ArmStatus.SetArmStatus(this, DASArmStatus, true);
|
||||
}
|
||||
|
||||
//FB 26817 Only for TSR AIR Query MaxEventsPossible after Arm to get the supported max events
|
||||
private ushort? GetTSRAIRMaxEventsPossible()
|
||||
{
|
||||
if (this is WinUSBTsrAir || this is EthernetTsrAir)
|
||||
{
|
||||
try
|
||||
{
|
||||
//per WIKI before querying we should set to 0 first to calculate?
|
||||
var setMaxEventsPossible = new SetSystemAttribute(this);
|
||||
setMaxEventsPossible.DeviceID = 0;
|
||||
setMaxEventsPossible.SetValue(AttributeTypes.SystemAttributes.MaxEventsPossible, new[] { (ushort)0, (ushort)0 }, true);
|
||||
setMaxEventsPossible.SyncExecute();
|
||||
|
||||
var getMaxEventsPossible = new QuerySystemAttribute(this);
|
||||
getMaxEventsPossible.DeviceID = 0;
|
||||
getMaxEventsPossible.Key = AttributeTypes.SystemAttributes.MaxEventsPossible;
|
||||
getMaxEventsPossible.SyncExecute();
|
||||
ushort maxEventPossible = ((ushort[])getMaxEventsPossible.Value)[1];
|
||||
return maxEventPossible;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public DFConstantsAndEnums.CommandStatus AutoArmStatus { get; set; } = DFConstantsAndEnums.CommandStatus.StatusNoError;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clock Sync
|
||||
public IDictionary<InputClockSource, bool> DASClockSyncStatus { get; set; } = null;
|
||||
public bool ClockSyncInUTC { get; set; } = false;
|
||||
public ClockSyncProfile DASClockSyncProfile { get; set; }
|
||||
public byte PTPDomainID { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Downloading
|
||||
|
||||
public virtual IDownloadRequest WhatToDownload { get; set; }
|
||||
public void SetWhatToDownload(IDownloadRequest request, bool bSetInDb = true)
|
||||
{
|
||||
DownloadRequest.SetWhatToDownload(this, request, bSetInDb);
|
||||
}
|
||||
public IDownloadReport EventInfo { get; set; }
|
||||
public void SetEventInfo(IDownloadReport eventInfo, bool bSetInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventInfo(this, eventInfo, bSetInDb);
|
||||
}
|
||||
public bool[] EventDownloadedStatus { get; set; }
|
||||
public void SetEventDownloadStatus(bool[] status, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventDownloadStatus(this, status, storeInDb);
|
||||
}
|
||||
public Guid[] EventGuids { get; set; }
|
||||
public void SetEventGuids(Guid[] guids, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventGuids(this, guids, storeInDb);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
public byte[] ArmAttempts { get; set; }
|
||||
public void SetEventArmAttemps(byte[] armAttempts, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventArmAttempts(this, armAttempts, storeInDb);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Information
|
||||
public virtual bool SupportsTriggerInversion() { return true; }
|
||||
public virtual bool SupportsStartInversion() { return true; }
|
||||
public bool InvertTrigger { get; set; }
|
||||
public bool InvertStart { get; set; }
|
||||
|
||||
public bool IgnoreShortedStart { get; set; }
|
||||
public bool IgnoreShortedTrigger { get; set; }
|
||||
|
||||
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 static StaticInformation StaticDASBridgeInfo = new StaticInformation(new double[]
|
||||
{//1,2,4,8,10,16,20,32,40,64,80,128,160,320,640,1280
|
||||
2400D/1.0,
|
||||
2400D/2.0,
|
||||
2400D/4.0,
|
||||
2400D/8.0,
|
||||
2400D/10.0,
|
||||
2400D/16.0,
|
||||
2400D/20.0,
|
||||
2400D/32.0,
|
||||
2400D/40.0,
|
||||
2400D/64.0,
|
||||
2400D/80.0,
|
||||
2400D/128.0,
|
||||
2400D/160.0,
|
||||
2400D/320.0,
|
||||
2400D/640.0,
|
||||
2400D/1280.0
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// the breakpoints for IEPE ranges possible on S6
|
||||
/// FB15462 split off S6 IEPE gain selection from S6A
|
||||
/// </summary>
|
||||
public static StaticInformation StaticDASS6EIEPEInfo = new StaticInformation(new double[]
|
||||
{//1,2,4,8,10,16,20,32,40,64,80,128,160,320,640,1280
|
||||
2400D/(1.0/6),
|
||||
2400D/(2.0/6),
|
||||
2400D/(4.0/6),
|
||||
2400D/(8.0/6),
|
||||
2400D/(10.0/6),
|
||||
2400D/(16.0/6),
|
||||
2400D/(20.0/6),
|
||||
2400D/(32.0/6),
|
||||
2400D/(40.0/6),
|
||||
2400D/(64.0/6),
|
||||
2400D/(80.0/6),
|
||||
2400D/(128.0/6),
|
||||
2400D/(160.0/6),
|
||||
2400D/(320.0/6),
|
||||
2400D/(640.0/6),
|
||||
2400D/(1280.0/6)
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// the breakpoints for IEPE ranges possible on S6A
|
||||
/// 14558 IEPE gain selection limited to gain 1 and 10 in DataPRO for SLICE6 AIR
|
||||
/// 15462 Limit SLICE 6 AIR gains as they are not functional with IEPE accel
|
||||
/// </summary>
|
||||
public static StaticInformation StaticDASS6AEIEPEInfo = new StaticInformation(new double[]
|
||||
{//1,2,4,8,10,16,20,32,40,64,80,128,160,320,640,1280
|
||||
2400D/(1.0/6), //G1
|
||||
2400D/(2.0/6), //G2
|
||||
2400D/(4.0/6), //G3
|
||||
2400D/(8.0/6), //G4
|
||||
2400D/(10.0/6),//G5 - 1440
|
||||
2400D/(16.0/6),//G6 - 900
|
||||
2400D/(20.0/6),//G7 - 720
|
||||
2400D/(32.0/6),//G8 - 450
|
||||
2400D/(40.0/6),//G9 - 360
|
||||
2400D/(64.0/6),//G10 - 225
|
||||
2400D/(80.0/6),//G11 - 180
|
||||
2400D/(128.0/6),//G12 - 112.5
|
||||
2400D/(160.0/6),//G13 - 90
|
||||
2400D/(320.0/6),//G14 - 45
|
||||
2400D/(640.0/6),//G15 - 22.5
|
||||
2400D/(1280.0/6)//G16 - 11.25
|
||||
});
|
||||
|
||||
public enum GainCodesSLICE6IEPE //Used by Slice PRO Gen3
|
||||
{
|
||||
[MaxInputRange(14400D)]
|
||||
[MinInputRange(7200D)]
|
||||
[FirmwareInputRange(10800D)]
|
||||
G1,
|
||||
|
||||
[MaxInputRange(7200D)]
|
||||
[MinInputRange(3600D)]
|
||||
[FirmwareInputRange(5400D)]
|
||||
G2,
|
||||
|
||||
[MaxInputRange(3600D)]
|
||||
[MinInputRange(1800D)]
|
||||
[FirmwareInputRange(2700)]
|
||||
G3,
|
||||
|
||||
[MaxInputRange(1800D)]
|
||||
[MinInputRange(1440)]
|
||||
[FirmwareInputRange(1620)]
|
||||
G4,
|
||||
|
||||
[MaxInputRange(1440D)]
|
||||
[MinInputRange(900D)]
|
||||
[FirmwareInputRange(1170D)]
|
||||
G5,
|
||||
|
||||
[MaxInputRange(900D)]
|
||||
[MinInputRange(720D)]
|
||||
[FirmwareInputRange(810D)]
|
||||
G6,
|
||||
|
||||
[MaxInputRange(720D)]
|
||||
[MinInputRange(450D)]
|
||||
[FirmwareInputRange(585)]
|
||||
G7,
|
||||
|
||||
[GainDisabled(true)]
|
||||
[MaxInputRange(450D)]
|
||||
[MinInputRange(360D)]
|
||||
[FirmwareInputRange(405)]
|
||||
G8,
|
||||
|
||||
[MaxInputRange(360D)]
|
||||
[MinInputRange(225D)]
|
||||
[FirmwareInputRange(292.5)]
|
||||
G9,
|
||||
|
||||
[GainDisabled(true)]
|
||||
[MaxInputRange(225D)]
|
||||
[MinInputRange(180D)]
|
||||
[FirmwareInputRange(202.5)]
|
||||
G10,
|
||||
|
||||
[MaxInputRange(180)]
|
||||
[MinInputRange(112.5)]
|
||||
[FirmwareInputRange(146.25)]
|
||||
G11,
|
||||
|
||||
[GainDisabled(true)]
|
||||
[MaxInputRange(112.5)]
|
||||
[MinInputRange(90)]
|
||||
[FirmwareInputRange(101.25)]
|
||||
G12,
|
||||
|
||||
[MaxInputRange(90)]
|
||||
[MinInputRange(45)]
|
||||
[FirmwareInputRange(67.5)]
|
||||
G13,
|
||||
|
||||
[MaxInputRange(45)]
|
||||
[MinInputRange(22.5)]
|
||||
[FirmwareInputRange(33.75)]
|
||||
G14,
|
||||
|
||||
[GainDisabled(true)]
|
||||
[MaxInputRange(22.5)]
|
||||
[MinInputRange(11.25)]
|
||||
[FirmwareInputRange(16.875)]
|
||||
G15,
|
||||
|
||||
[GainDisabled(true)]
|
||||
[MaxInputRange(11.25)]
|
||||
[MinInputRange(0)]
|
||||
[FirmwareInputRange(5.625)]
|
||||
G16
|
||||
};
|
||||
//0.2040816327F, 2.0408163265F
|
||||
public static StaticInformation StaticDASIEPEInfo = new StaticInformation(new double[]
|
||||
{
|
||||
2400D/.2040816327D,
|
||||
2400D/2.0408163265D
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Firmware Utility
|
||||
public string FWUtilSerialNumber { get; set; }
|
||||
public Dictionary<ushort, object> SystemAttributes { get; set; }
|
||||
public Dictionary<ushort, object> UserAttributes { get; set; }
|
||||
public Dictionary<ushort, object> ArmAttributes { get; set; }
|
||||
public Dictionary<ushort, object> EventAttributes { get; set; }
|
||||
public ushort EventAttributeEventNumber { get; set; }
|
||||
#endregion
|
||||
|
||||
//I'm guessing hiding was not intended, this member hides an inherited member (from ICommunication)
|
||||
//public string SerialNumber { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sn = SerialNumber;
|
||||
if (!string.IsNullOrEmpty(sn))
|
||||
return sn;
|
||||
return "Unknown DAS";
|
||||
}
|
||||
|
||||
public virtual int NumberOfConfiguredChannels()
|
||||
{
|
||||
if (ConfigData == null)
|
||||
return 0;
|
||||
return ConfigData.NumberOfConfiguredChannels();
|
||||
}
|
||||
|
||||
public virtual int NumberOfChannels()
|
||||
{
|
||||
if (ConfigData == null)
|
||||
return 0;
|
||||
return ConfigData.NumberOfChannels();
|
||||
}
|
||||
|
||||
public virtual int NumberOfDownloadChannels()
|
||||
{
|
||||
if (ConfigData == null)
|
||||
return 0;
|
||||
return ConfigData.NumberOfDownloadChannels();
|
||||
}
|
||||
|
||||
public int CompareTo(IDASCommunication das)
|
||||
{
|
||||
if (das == null || string.IsNullOrEmpty(das.SerialNumber) || string.IsNullOrEmpty(SerialNumber))
|
||||
return 0;
|
||||
return SerialNumber.CompareTo(das.SerialNumber);
|
||||
}
|
||||
|
||||
public virtual bool DiagnosticsHasBeenRun { get; set; }
|
||||
private bool _configureHasBeenRun = false;
|
||||
public virtual bool ConfigureHasBeenRun
|
||||
{
|
||||
get => _configureHasBeenRun;
|
||||
set
|
||||
{
|
||||
if (!value && null != ConfigData) { ConfigData.ClearSetup = true; }
|
||||
_configureHasBeenRun = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Sub classes used for identification
|
||||
|
||||
public class WinUSBSlice : Slice<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = true;
|
||||
}
|
||||
}
|
||||
public class CDCUSBSlice : SLICE2<WINUSBConnection>
|
||||
{
|
||||
public CDCUSBSlice()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class WinUSBSlice1_5 : SLICE1_5<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice1_5()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class WinUSBSlice6 : SLICE6<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice6()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class WinUSBSlice6Air : SLICE6AIR<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice6Air()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class WinUSBSlice6AirBridge : SLICE6AIRBR<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice6AirBridge()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class WinUSBTsrAir : TSRAIR<WINUSBConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
if (UNKNOWN_REVISION == _hardwareRevision) QueryHardwareRevision();
|
||||
switch (_hardwareRevision)
|
||||
{
|
||||
case (int)TSR_AIR_HW_REVISION.DIR:
|
||||
return HardwareTypes.DIR;
|
||||
case (int)TSR_AIR_HW_REVISION.DKR:
|
||||
return HardwareTypes.DKR;
|
||||
default:
|
||||
return HardwareTypes.UNDEFINED;
|
||||
}
|
||||
}
|
||||
public WinUSBTsrAir()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
// no network time sync
|
||||
TSRAIR_MinimumProtocols.Remove(DFConstantsAndEnums.ProtocolLimitedCommands.PTPSyncStatus);
|
||||
TSRAIR_MinimumProtocols.Remove(DFConstantsAndEnums.ProtocolLimitedCommands.PTPTimestamp);
|
||||
_haveInited = true;
|
||||
}
|
||||
}
|
||||
public class WinUSBSlice6AirThermocoupler : SLICE6AIRTC<WINUSBConnection>
|
||||
{
|
||||
public WinUSBSlice6AirThermocoupler()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice : Slice<EthernetConnection>
|
||||
{
|
||||
public EthernetSlice()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = true;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice2 : SLICE2<EthernetConnection>
|
||||
{
|
||||
public EthernetSlice2()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice6 : SLICE6<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.SLICE6_Base;
|
||||
}
|
||||
public EthernetSlice6()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
((EthernetConnection)Transport).RequiresKeepAliveReset = true;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice6Air : SLICE6AIR<EthernetConnection>
|
||||
{
|
||||
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return IsEthernetRecorder ? HardwareTypes.S6A_EthernetRecorder : HardwareTypes.SLICE6_AIR;
|
||||
}
|
||||
public EthernetSlice6Air()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
((EthernetConnection)Transport).RequiresKeepAliveReset = true;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice6AirBridge : SLICE6AIRBR<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.SLICE6_AIR_BR;
|
||||
}
|
||||
public EthernetSlice6AirBridge()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
((EthernetConnection)Transport).RequiresKeepAliveReset = true;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice6DB : SLICE6DB<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
switch (S6DBMode)
|
||||
{
|
||||
case S6DBModes.INDUMMY:
|
||||
return HardwareTypes.SLICE6DB_InDummy;
|
||||
//case S6DBModes.AIR:
|
||||
// return HardwareTypes.SLICE6DB_AIR;
|
||||
default:
|
||||
return HardwareTypes.SLICE6DB;
|
||||
}
|
||||
}
|
||||
public EthernetSlice6DB()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class EthernetPowerPro : PowerPro<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.PowerPro;
|
||||
}
|
||||
public EthernetPowerPro()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class EthernetTsrAir : TSRAIR<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
if (UNKNOWN_REVISION == _hardwareRevision) QueryHardwareRevision();
|
||||
switch (_hardwareRevision)
|
||||
{
|
||||
case (int)TSR_AIR_HW_REVISION.REV_A:
|
||||
return HardwareTypes.TSR_AIR;
|
||||
case (int)TSR_AIR_HW_REVISION.REV_B:
|
||||
return HardwareTypes.TSR_AIR_RevB;
|
||||
default:
|
||||
return HardwareTypes.UNDEFINED;
|
||||
}
|
||||
}
|
||||
public EthernetTsrAir()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
((EthernetConnection)Transport).RequiresKeepAliveReset = true;
|
||||
}
|
||||
}
|
||||
public class EthernetSlice6DB3 : SLICE6DB<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.SLICE6DB3;
|
||||
}
|
||||
public EthernetSlice6DB3()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
public class EthernetSlicePRODB : SLICEPRODB<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.SLICE_Pro_Distributor;
|
||||
}
|
||||
public EthernetSlicePRODB()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class EthernetSlice1_5 : SLICE1_5<EthernetConnection>
|
||||
{
|
||||
public EthernetSlice1_5()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class EthernetSliceDB : SliceDB<EthernetConnection>
|
||||
{
|
||||
public bool SupportsDiagnostics => IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.Diagnostics);
|
||||
|
||||
public EthernetSliceDB()
|
||||
{
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SerialNumber))
|
||||
{
|
||||
return SerialNumber;
|
||||
}
|
||||
else return base.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class EthernetSlice6AirThermocoupler : SLICE6AIRTC<EthernetConnection>
|
||||
{
|
||||
public override HardwareTypes GetHardwareType()
|
||||
{
|
||||
return HardwareTypes.SLICE6_AIR_TC;
|
||||
}
|
||||
public EthernetSlice6AirThermocoupler()
|
||||
{
|
||||
_bSupportsMultipleSampleRealtime = false;
|
||||
((EthernetConnection)Transport).RequiresKeepAliveReset = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
923
DataPRO/IService/Classes/SLICEService/SLICE Service.Realtime.cs
Normal file
923
DataPRO/IService/Classes/SLICEService/SLICE Service.Realtime.cs
Normal file
@@ -0,0 +1,923 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.DASLib.Command.SLICE.RealtimeCommands;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using System.Threading.Tasks;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Classes.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class Slice<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
#region Real time
|
||||
public virtual bool ControlsDAQ() { return true; }
|
||||
|
||||
public virtual bool SupportsRealtime()
|
||||
{
|
||||
return !IsTOM();
|
||||
}
|
||||
|
||||
public virtual bool SupportsMultipleEvents() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents); }
|
||||
public virtual bool SupportsMultipleConfigurations() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MultipleConfigurations); }
|
||||
public virtual bool SupportsAutoArm() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm); }
|
||||
public virtual bool SupportsLevelTrigger() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger); }
|
||||
public bool SupportsHardwareInputCheck() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines); }
|
||||
protected bool _bSupportsMultipleSampleRealtime = true;
|
||||
public bool SupportsMultipleSampleRealtime() { return _bSupportsMultipleSampleRealtime; }
|
||||
|
||||
|
||||
protected class RealTimeAsyncPacket
|
||||
{
|
||||
public SliceServiceAsyncInfo Info { get; set; }
|
||||
public Timer Timer { get; set; }
|
||||
public int SamplesPerSecond { get; set; }
|
||||
public int MillisecBetweenSamples { get; set; }
|
||||
public bool AllowMultipleSampleRealtime { get; set; }
|
||||
public ManualResetEvent StopEvent { get; set; }
|
||||
public byte[] Channels { get; set; }
|
||||
public double AAF { get; set; }
|
||||
public int minCallbackUpdateTimeMs { get; set; }
|
||||
public bool UseUDPStreaming { get; set; } = false;
|
||||
public int StreamPortOffset { get; set; }
|
||||
public string HostIPAddress { get; set; } = IPAddress.Any.ToString();
|
||||
}
|
||||
|
||||
protected class RealTimeTiltAsyncPacket
|
||||
{
|
||||
public SliceServiceAsyncInfo Info { get; set; }
|
||||
public double[] TiltInDegrees { get; set; }
|
||||
public ManualResetEvent StopEvent { get; set; }
|
||||
}
|
||||
|
||||
// FB15313: Add UDP streaming options
|
||||
protected class RealTimeUDPStreamProfileAsyncPacket
|
||||
{
|
||||
public SliceServiceAsyncInfo Info { get; set; }
|
||||
public UDPStreamProfile Profile { get; set; }
|
||||
public string UDPAddress { get; set; }
|
||||
public ushort TimeDataChannelId { get; set; }
|
||||
public uint[] TMNSConfig { get; set; }
|
||||
public ushort DataChannelId { get; set; }
|
||||
public ushort IRIGTimeDataPacketIntervalMs { get; set; }
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTime(int samplesPerSecond,
|
||||
int millisecBetweenSamples,
|
||||
ServiceCallback callback,
|
||||
object userData,
|
||||
bool allowMultipleSampleRealtime,
|
||||
int moduleIndex,
|
||||
ManualResetEvent stopEvent,
|
||||
byte[] channels,
|
||||
double aaf,
|
||||
int minCallbackUpdateTimeMs,
|
||||
bool UseUDPStreaming,
|
||||
string hostIPAddress)
|
||||
{
|
||||
var packet = new RealTimeAsyncPacket();
|
||||
packet.StopEvent = stopEvent;
|
||||
packet.Info = new SliceServiceAsyncInfo(callback, userData);
|
||||
packet.MillisecBetweenSamples = millisecBetweenSamples;
|
||||
packet.SamplesPerSecond = samplesPerSecond;
|
||||
packet.AllowMultipleSampleRealtime = allowMultipleSampleRealtime;
|
||||
packet.Channels = channels;
|
||||
packet.AAF = aaf;
|
||||
packet.minCallbackUpdateTimeMs = minCallbackUpdateTimeMs;
|
||||
packet.UseUDPStreaming = UseUDPStreaming;
|
||||
packet.StreamPortOffset = moduleIndex; // FB15388: udp ports must be unique, start index-0 unit at the default and iterate offset from there
|
||||
packet.HostIPAddress = hostIPAddress;
|
||||
LaunchAsyncWorker("Slice.RealTime", AsyncRealTime, packet);
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTimePolling(ServiceCallback callback,
|
||||
object userData,
|
||||
ManualResetEvent stopEvent,
|
||||
byte[] channels)
|
||||
{
|
||||
var packet = new RealTimeAsyncPacket
|
||||
{
|
||||
StopEvent = stopEvent,
|
||||
Info = new SliceServiceAsyncInfo(callback, userData),
|
||||
Channels = channels
|
||||
};
|
||||
LaunchAsyncWorker("Slice.RealtimePolling", AsyncRealTimePolling, packet);
|
||||
}
|
||||
/// <summary>
|
||||
/// returns an object implementing IGetRealtimeSamples capable of returning realtime samples
|
||||
/// </summary>
|
||||
/// <param name="iCommunication"></param>
|
||||
/// <param name="bPolling">whether realtime is polling or not</param>
|
||||
/// <returns></returns>
|
||||
protected virtual IGetRealtimeSamples GetRealtimeSamplesClass(DTS.Common.Interface.DASFactory.ICommunication iCommunication, bool bPolling = false)
|
||||
{
|
||||
return new GetRealtimeSamples(iCommunication, 2000, bPolling);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// indicates whether the DAS supports streaming
|
||||
/// 10572 implement SW side for single command streaming realtime
|
||||
/// </summary>
|
||||
public virtual bool SupportsIndividualChannelRealtimeStreaming => false;
|
||||
|
||||
/// <summary>
|
||||
/// indicates whether the das supports udp streaming
|
||||
/// 15160 Port UDP Realtime Stream from FWTU
|
||||
/// </summary>
|
||||
public virtual bool SupportsUDPRealtimeStreaming => false;
|
||||
/// <summary>
|
||||
/// depending on firmware, some devices will send back all channels even if you request less while others will send back what's requested.
|
||||
/// DataPRO is always expecting all channels to be returned. fix for these models is to always request all
|
||||
/// 31829 Datapro s6air br shows noise in realtime view chart that is not real noise and does not show up in fwtu realtime or recorded
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual byte[] GetRTChannelIndices(RealTimeAsyncPacket packet)
|
||||
{
|
||||
return packet.Channels;
|
||||
}
|
||||
/// <summary>
|
||||
/// this is the minimum of time between data callbacks for realtime
|
||||
/// this should be moved to the settings file, but it is fine here
|
||||
/// for now since there is the ms between samples setting and
|
||||
/// only the g8 and older firmware need to request samples at a fast rate
|
||||
/// </summary>
|
||||
//protected const int MIN_CALLBACK_UPDATE_TIME = 20;
|
||||
private void AsyncRealTime(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeAsyncPacket;
|
||||
try
|
||||
{
|
||||
var ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.TriggerPolarity, (byte)(InvertTrigger ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.StartRecordPolarity, (byte)(InvertStart ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
|
||||
// Set sample rate and adjustable anti-alias filter frequency in the
|
||||
// hardware based on the milliseconds between samples parameter that
|
||||
// was passed in via the RealTimeAsyncPacket object. Keep the filter
|
||||
// -3dB point at 1/5 the frequency of the sample rate.
|
||||
// number of samples per second
|
||||
var rtSampleRate = Convert.ToUInt32(packet.SamplesPerSecond);
|
||||
var uiMillisecondsBetweenSamples = packet.MillisecBetweenSamples;
|
||||
var setSampleRate = new SetRealtimeSampleRate(this);
|
||||
setSampleRate.SetValue(rtSampleRate);
|
||||
setSampleRate.SyncExecute();
|
||||
|
||||
var lastUpdate = DateTime.MinValue;
|
||||
StreamReaderUDP streamReader = null;
|
||||
|
||||
if (SupportsIndividualChannelRealtimeStreaming)
|
||||
{
|
||||
try
|
||||
{
|
||||
var saa = new SetArmAttribute(this);
|
||||
saa.SetValue(AttributeTypes.ArmAndEventAttributes.RealtimeAAFilterFrequencyHz,
|
||||
Convert.ToSingle(packet.AAF), true);
|
||||
saa.SyncExecute();
|
||||
|
||||
if (packet.UseUDPStreaming && SupportsUDPRealtimeStreaming)
|
||||
{
|
||||
//FB 18152 find the host ip
|
||||
string dasIp;
|
||||
string hostIpAddress = "";
|
||||
if (Common.Utils.NetworkUtils.TryParseConnectionString(ConnectString, out dasIp))
|
||||
{
|
||||
hostIpAddress = Common.Utils.PingUtils.DasToHost[dasIp].HostIpAddress;
|
||||
}
|
||||
else
|
||||
{ // We should not get here since SupportsUDPRealtimeStreaming is false for USB devices but just in case have a guard
|
||||
APILogger.Log("Streaming realtime with UDP is not supported for USB devices.");
|
||||
return;
|
||||
}
|
||||
|
||||
var udpAddress = new UriBuilder(DFConstantsAndEnums.RealtimeUDPAddress);
|
||||
udpAddress.Port += packet.StreamPortOffset;
|
||||
streamReader = new StreamReaderUDP(udpAddress.Uri.AbsoluteUri, hostIpAddress, UDPStreamProfile.DTS_UDP, packet.Channels);
|
||||
|
||||
var startTimeStampRealtime = new StartTimeStampStreamMode(this);
|
||||
startTimeStampRealtime.ParamsToSend = streamReader.cmdline.ToArray();
|
||||
startTimeStampRealtime.SyncExecute();
|
||||
}
|
||||
else
|
||||
{
|
||||
var startRT = new StartRealtimeStreamingMode(this, GetRTChannelIndices(packet));
|
||||
startRT.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var startRT = new StartRealtimeMode(this);
|
||||
startRT.SupportsMultipleSampleRealtime =
|
||||
packet.AllowMultipleSampleRealtime && SupportsMultipleSampleRealtime();
|
||||
startRT.SyncExecute();
|
||||
}
|
||||
var sampleNumbers = new List<ulong>(100);
|
||||
var timeStamps = new List<ulong>(100);
|
||||
var sequenceNumbers = new List<ulong>(100);
|
||||
var data = new List<short[][]>(100);
|
||||
// start calling for RT data
|
||||
|
||||
var getRTdata = GetRealtimeSamplesClass(this);
|
||||
getRTdata.LogCommands = false;
|
||||
|
||||
var numChannels = 0;
|
||||
|
||||
foreach (var mod in DASInfo.Modules)
|
||||
{
|
||||
switch (mod.TypeOfModule)
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.EmbeddedMicrophone:
|
||||
case DFConstantsAndEnums.ModuleType.EmbeddedMagnetometer:
|
||||
case DFConstantsAndEnums.ModuleType.EmbeddedMagnetInput:
|
||||
case DFConstantsAndEnums.ModuleType.UART:
|
||||
case DFConstantsAndEnums.ModuleType.StreamOut:
|
||||
case DFConstantsAndEnums.ModuleType.StreamIn:
|
||||
continue;
|
||||
default:
|
||||
numChannels += (int)mod.NumberOfChannels;
|
||||
break;
|
||||
}
|
||||
}
|
||||
getRTdata.Channels = (ushort)numChannels;
|
||||
if (SerialNumber.StartsWith("SPD") || SerialNumber.StartsWith("SLD"))
|
||||
{
|
||||
if (getRTdata is RealtimeStreamingNextSamples cmd)
|
||||
{
|
||||
cmd.DigitalInput = true;
|
||||
var transitions = new List<bool>();
|
||||
foreach (var mod in ConfigData.Modules)
|
||||
{
|
||||
foreach (var channel in mod.Channels)
|
||||
{
|
||||
var aic = (AnalogInputDASChannel)channel;
|
||||
switch (aic.DigitalMode)
|
||||
{
|
||||
case DigitalInputModes.CCNC:
|
||||
case DigitalInputModes.CCNO:
|
||||
transitions.Add(false);
|
||||
break;
|
||||
case DigitalInputModes.THL:
|
||||
case DigitalInputModes.TLH:
|
||||
transitions.Add(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cmd.TransitionMode = transitions.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
while (!packet.StopEvent.WaitOne(0, false))
|
||||
{
|
||||
if (null != streamReader)
|
||||
{
|
||||
try
|
||||
{
|
||||
var udpPacket = streamReader.Read();
|
||||
if (null != udpPacket)
|
||||
{
|
||||
data.Add(udpPacket.ChannelData);
|
||||
sampleNumbers.Add(udpPacket.SampleNumber);
|
||||
timeStamps.Add( /*Convert.ToUInt64(udpPacket.TimeStamp)*/0);
|
||||
sequenceNumbers.Add(udpPacket.SequenceNumber);
|
||||
|
||||
var newData = new NewDataData(data.ToArray(), sampleNumbers.ToArray(),
|
||||
timeStamps.ToArray(),
|
||||
sequenceNumbers.ToArray());
|
||||
|
||||
Task.Run(() => { packet.Info.NewData(newData); });
|
||||
|
||||
sampleNumbers.Clear();
|
||||
timeStamps.Clear();
|
||||
sequenceNumbers.Clear();
|
||||
data.Clear();
|
||||
}
|
||||
}
|
||||
catch (SocketException sox) //FB15531: Don't silently consume realtime errors
|
||||
{
|
||||
//if it's a timeout it could just be that there's no data yet,
|
||||
//give the device a chance to send data
|
||||
if (sox.SocketErrorCode != SocketError.TimedOut)
|
||||
{
|
||||
throw sox;
|
||||
}
|
||||
}
|
||||
catch (CommandException ce)
|
||||
{
|
||||
if (ce.Error == CommandErrorReason.ReceiveFailed ||
|
||||
ce.Error == CommandErrorReason.SendFailed)
|
||||
{
|
||||
packet.Info.Error(ce.Message, new Common.Classes.Connection.NotConnectedException(ce.Message));
|
||||
return;
|
||||
}
|
||||
//15909 Crash in Realtime when connection is lost
|
||||
//in the case of a communication error in start realtime, notify consumer
|
||||
packet.Info.Error(ce.Message, ce);
|
||||
return;
|
||||
}
|
||||
catch (Common.Classes.Connection.NotConnectedException nce)
|
||||
{
|
||||
//15909 Crash in Realtime when connection is lost
|
||||
//in the case of a communication error in start realtime, notify consumer
|
||||
packet.Info.Error(nce.Message, nce);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// call HW to get RT samples
|
||||
try
|
||||
{
|
||||
getRTdata.SyncExecute();
|
||||
|
||||
}
|
||||
catch (CommandException ce)
|
||||
{
|
||||
if (ce.Error == CommandErrorReason.ReceiveFailed ||
|
||||
ce.Error == CommandErrorReason.SendFailed)
|
||||
{
|
||||
packet.Info.Error(ce.Message, new Common.Classes.Connection.NotConnectedException(ce.Message));
|
||||
return;
|
||||
}
|
||||
//15909 Crash in Realtime when connection is lost
|
||||
//in the case of a communication error in start realtime, notify consumer
|
||||
packet.Info.Error(ce.Message, ce);
|
||||
return;
|
||||
}
|
||||
catch (Common.Classes.Connection.NotConnectedException nce)
|
||||
{
|
||||
//15909 Crash in Realtime when connection is lost
|
||||
//in the case of a communication error in start realtime, notify consumer
|
||||
packet.Info.Error(nce.Message, nce);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
|
||||
if (getRTdata.SamplesReturned > 0)
|
||||
{
|
||||
var rtData = new short[getRTdata.Channels][];
|
||||
for (int idx = 0; idx < getRTdata.Channels; idx++)
|
||||
{
|
||||
rtData[idx] = getRTdata.GetChannelData(idx);
|
||||
}
|
||||
|
||||
sampleNumbers.Add(getRTdata.SampleNumber);
|
||||
timeStamps.Add(getRTdata.TimeStamp);
|
||||
sequenceNumbers.Add(getRTdata.SequenceNumber);
|
||||
data.Add(rtData);
|
||||
}
|
||||
|
||||
if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds >= packet.minCallbackUpdateTimeMs)
|
||||
{
|
||||
lastUpdate = DateTime.Now;
|
||||
|
||||
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream))
|
||||
{
|
||||
var ihl =
|
||||
new InitializeHardwareLines(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ihl.LogCommands = false;
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands
|
||||
.InitHardwareInputLines) &&
|
||||
!packet.StopEvent.WaitOne(0, false))
|
||||
{
|
||||
ihl.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
} //TODO: Where is an Exception?
|
||||
|
||||
var d1 = new short[1][];
|
||||
|
||||
d1[0] = new short[2];
|
||||
d1[0][0] = (short)(ihl.StartRecordShorted ? 1 : 0);
|
||||
d1[0][1] = (short)(ihl.TriggerInputShorted ? 1 : 0);
|
||||
|
||||
data.Add(d1);
|
||||
sampleNumbers.Add(ulong.MaxValue);
|
||||
timeStamps.Add(ulong.MinValue);
|
||||
sequenceNumbers.Add(ulong.MinValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Thread.Sleep(50);
|
||||
}
|
||||
|
||||
ThreadPool.QueueUserWorkItem(packet.Info.NewData,
|
||||
new NewDataData(data.ToArray(), sampleNumbers.ToArray(), timeStamps.ToArray(),
|
||||
sequenceNumbers.ToArray()));
|
||||
|
||||
sampleNumbers.Clear();
|
||||
timeStamps.Clear();
|
||||
sequenceNumbers.Clear();
|
||||
data.Clear();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(uiMillisecondsBetweenSamples);
|
||||
}
|
||||
var endRealtime = new EndRealtimeMode(this);
|
||||
endRealtime.SyncExecute();
|
||||
packet.Info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
packet.Info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
packet.Info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
private void AsyncRealTimePolling(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeAsyncPacket;
|
||||
|
||||
try
|
||||
{
|
||||
var ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.TriggerPolarity, (byte)(InvertTrigger ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.StartRecordPolarity, (byte)(InvertStart ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
|
||||
// Set sample rate and adjustable anti-alias filter frequency in the
|
||||
// hardware based on the milliseconds between samples parameter that
|
||||
// was passed in via the RealTimeAsyncPacket object. Keep the filter
|
||||
// -3dB point at 1/5 the frequency of the sample rate.
|
||||
// number of samples per second
|
||||
var rtSampleRate = Convert.ToUInt32(50);
|
||||
const int uiMillisecondsBetweenSamples = 200;
|
||||
var setSampleRate = new SetRealtimeSampleRate(this);
|
||||
setSampleRate.SetValue(rtSampleRate);
|
||||
setSampleRate.SyncExecute();
|
||||
|
||||
|
||||
DateTime lastUpdate = DateTime.MinValue;
|
||||
// set RT mode in HW
|
||||
var startRT = new StartRealtimeMode(this);
|
||||
startRT.SupportsMultipleSampleRealtime = true;
|
||||
startRT.SyncExecute();
|
||||
var sampleNumbers = new List<ulong>(100);
|
||||
var timeStamps = new List<ulong>(100);
|
||||
var sequenceNumbers = new List<ulong>(100);
|
||||
var data = new List<short[][]>(100);
|
||||
// start calling for RT data
|
||||
var getRTdata = GetRealtimeSamplesClass(this, true);
|
||||
getRTdata.LogCommands = false;
|
||||
getRTdata.Channels = (ushort)DASInfo.Modules.Sum(m => m.NumberOfChannels);
|
||||
while (!packet.StopEvent.WaitOne(0, false))
|
||||
{
|
||||
// call HW to get RT samples
|
||||
try
|
||||
{
|
||||
getRTdata.SyncExecute();
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
if (getRTdata.SamplesReturned > 0)
|
||||
{
|
||||
var rtData = new short[getRTdata.Channels][];
|
||||
for (var idx = 0; idx < getRTdata.Channels; idx++)
|
||||
{
|
||||
rtData[idx] = getRTdata.GetChannelData(idx);
|
||||
}
|
||||
sampleNumbers.Add(getRTdata.SampleNumber);
|
||||
timeStamps.Add(getRTdata.TimeStamp);
|
||||
sequenceNumbers.Add(getRTdata.SequenceNumber);
|
||||
data.Add(rtData);
|
||||
}
|
||||
if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds >= packet.minCallbackUpdateTimeMs)
|
||||
{
|
||||
lastUpdate = DateTime.Now;
|
||||
|
||||
var ihl = new InitializeHardwareLines(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ihl.LogCommands = false;
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines) && !packet.StopEvent.WaitOne(0, false))
|
||||
{
|
||||
ihl.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
|
||||
if (Common.Constants.CheckStatusLinesInRealtime)
|
||||
{
|
||||
var d1 = new short[1][];
|
||||
|
||||
d1[0] = new short[2];
|
||||
d1[0][0] = (short)(ihl.StartRecordShorted ? 1 : 0);
|
||||
d1[0][1] = (short)(ihl.TriggerInputShorted ? 1 : 0);
|
||||
|
||||
data.Add(d1);
|
||||
sampleNumbers.Add(ulong.MaxValue);
|
||||
}
|
||||
//15244 Cannot run meter mode in realtime
|
||||
timeStamps.Add(ulong.MinValue);
|
||||
ThreadPool.QueueUserWorkItem(packet.Info.NewData, new NewDataData(data.ToArray(), sampleNumbers.ToArray(), timeStamps.ToArray(), sequenceNumbers.ToArray()));
|
||||
|
||||
sampleNumbers.Clear();
|
||||
timeStamps.Clear();
|
||||
sequenceNumbers.Clear();
|
||||
data.Clear();
|
||||
}
|
||||
Thread.Sleep(uiMillisecondsBetweenSamples);
|
||||
}
|
||||
var exitRT = new EndRealtimeMode(this);
|
||||
exitRT.SyncExecute();
|
||||
packet.Info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
packet.Info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
packet.Info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
void IRealTimeActions.ExitRealTimeMode(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
|
||||
LaunchAsyncWorker("Slice.ExitRealTimeMode", new WaitCallback(AsyncExitRealTimeMode), info);
|
||||
}
|
||||
|
||||
private void AsyncExitRealTimeMode(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as SliceServiceAsyncInfo;
|
||||
if (!SupportsRealtime())
|
||||
{
|
||||
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false;// FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
|
||||
info.Success();
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var exitRT = new EndRealtimeMode(this);
|
||||
exitRT.SyncExecute();
|
||||
if (null != DASArmStatus && RecordingModeExtensions.IsAStreamMode((DFConstantsAndEnums.RecordingMode)DASArmStatus.RecordingMode))
|
||||
{
|
||||
//for safety unset the auto arm flag in case the user reboots ...
|
||||
DisAutoArm();
|
||||
}
|
||||
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false; // FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTimeTiltPolling(ServiceCallback callback,
|
||||
object userData,
|
||||
ManualResetEvent stopEvent)
|
||||
|
||||
{
|
||||
var packet = new RealTimeTiltAsyncPacket();
|
||||
packet.StopEvent = stopEvent;
|
||||
packet.Info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("Slice.RealTimeTiltPolling", AsyncRealTimeTiltPolling, packet);
|
||||
}
|
||||
|
||||
private void AsyncRealTimeTiltPolling(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeTiltAsyncPacket;
|
||||
|
||||
try
|
||||
{
|
||||
while (!packet.StopEvent.WaitOne(0, false))
|
||||
{
|
||||
var axisADCData = new short[3] { 0, 0, 0 };
|
||||
var calFactor = new double[3] { 1, 1, 1 };
|
||||
var zeroData = new double[3] { 0, 0, 0 };
|
||||
|
||||
// Get raw tilt ADC
|
||||
var qtsd = new QueryTiltSensorData(this);
|
||||
qtsd.DeviceID = 1;
|
||||
qtsd.SyncExecute();
|
||||
axisADCData[0] = qtsd.Channel1ValueAdc;
|
||||
axisADCData[1] = qtsd.Channel2ValueAdc;
|
||||
axisADCData[2] = qtsd.Channel3ValueAdc;
|
||||
|
||||
//Get tilt sensor scale factors
|
||||
var scaleFactorGPerADC = new float[3] { 1, 1, 1 };
|
||||
if (RunTestVariables.InRunTest && RunTestVariables.TiltSensorScaleFactor > 0)
|
||||
{
|
||||
scaleFactorGPerADC = new[]
|
||||
{
|
||||
RunTestVariables.TiltSensorScaleFactor, RunTestVariables.TiltSensorScaleFactor,
|
||||
RunTestVariables.TiltSensorScaleFactor
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var scaleFactorQuery = new QueryArmAttribute(this)
|
||||
{
|
||||
Key = AttributeTypes.ArmAndEventAttributes.InSliceTiltSensorScaleFactorGPerADC
|
||||
};
|
||||
scaleFactorQuery.SyncExecute();
|
||||
scaleFactorGPerADC = scaleFactorQuery.Value as float[];
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
int dominantAxis = (axisADCData.Max() < Math.Abs(axisADCData.Min())) ?
|
||||
Array.IndexOf(axisADCData, axisADCData.Min()) : Array.IndexOf(axisADCData, axisADCData.Max());
|
||||
|
||||
var query = new QuerySystemAttribute_BridgeSlice6(this);
|
||||
query.DeviceID = 1;
|
||||
|
||||
try
|
||||
{
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_1;
|
||||
query.SyncExecute();
|
||||
calFactor[0] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
|
||||
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_7;
|
||||
query.SyncExecute();
|
||||
calFactor[1] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
|
||||
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_13;
|
||||
query.SyncExecute();
|
||||
calFactor[2] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
// Calculate Accel Data
|
||||
var accelData = new double[3];
|
||||
for (int i = 0; i < accelData.Length; i++)
|
||||
{
|
||||
var channel_2G = (axisADCData[i] / calFactor[i]) * scaleFactorGPerADC[i];
|
||||
if (channel_2G > 1)
|
||||
{
|
||||
channel_2G = 1;
|
||||
}
|
||||
else if (channel_2G < -1)
|
||||
{
|
||||
channel_2G = -1;
|
||||
}
|
||||
|
||||
accelData[i] = channel_2G;
|
||||
}
|
||||
|
||||
|
||||
bool positivePolarity = (axisADCData[dominantAxis] > 0);
|
||||
|
||||
switch (dominantAxis)
|
||||
{
|
||||
case 0:
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_2;
|
||||
break;
|
||||
case 1:
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_8;
|
||||
break;
|
||||
case 2:
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_14;
|
||||
break;
|
||||
default:
|
||||
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_2;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
query.SyncExecute();
|
||||
zeroData[dominantAxis] = Convert.ToDouble(query.Value);
|
||||
}
|
||||
catch { }
|
||||
|
||||
var query2 = new QuerySystemAttribute_BridgeSlice6(this);
|
||||
query2.DeviceID = 1;
|
||||
|
||||
switch (dominantAxis)
|
||||
{
|
||||
case 0:
|
||||
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_9 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_10;
|
||||
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_15 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_16;
|
||||
break;
|
||||
case 1:
|
||||
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_3 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_4;
|
||||
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_17 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_18;
|
||||
break;
|
||||
case 2:
|
||||
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_5 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_6;
|
||||
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_11 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_12;
|
||||
break;
|
||||
default:
|
||||
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_9 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_10;
|
||||
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_15 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_16;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
query.SyncExecute();
|
||||
query2.SyncExecute();
|
||||
|
||||
switch (dominantAxis)
|
||||
{
|
||||
case 0:
|
||||
zeroData[1] = Convert.ToDouble(query.Value);
|
||||
zeroData[2] = Convert.ToDouble(query2.Value);
|
||||
break;
|
||||
case 1:
|
||||
zeroData[0] = Convert.ToDouble(query.Value);
|
||||
zeroData[2] = Convert.ToDouble(query2.Value);
|
||||
break;
|
||||
case 2:
|
||||
zeroData[0] = Convert.ToDouble(query.Value);
|
||||
zeroData[1] = Convert.ToDouble(query2.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Calculate Tilt Data
|
||||
var Sx = (axisADCData[0] - zeroData[0]) / calFactor[0];
|
||||
var Sy = (axisADCData[1] - zeroData[1]) / calFactor[1];
|
||||
var Sz = (axisADCData[2] - zeroData[2]) / calFactor[2];
|
||||
var SG = Math.Sqrt(Math.Pow(Sx, 2) + Math.Pow(Sy, 2) + Math.Pow(Sz, 2));
|
||||
|
||||
var tiltInDegrees = new double[3];
|
||||
tiltInDegrees[0] = (180.0 / Math.PI) * Math.Asin(Sx / SG);
|
||||
tiltInDegrees[1] = (180.0 / Math.PI) * Math.Asin(Sy / SG);
|
||||
tiltInDegrees[2] = (180.0 / Math.PI) * Math.Asin(Sz / SG);
|
||||
|
||||
TiltAxisData = tiltInDegrees.ToList();
|
||||
ThreadPool.QueueUserWorkItem(packet.Info.NewData, new ServiceCallbackData.TiltNewData()
|
||||
{
|
||||
TiltData = tiltInDegrees,
|
||||
AccelData = accelData,
|
||||
});
|
||||
}
|
||||
packet.Info.Success();
|
||||
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
packet.Info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
packet.Info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public string UDPStreamAddress
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
// FB15313: Add UDP Streaming options
|
||||
void IRealTimeActions.SetUDPStreamProfile(ServiceCallback callback, object userData,
|
||||
UDPStreamProfile streamProfile, string udpAddress, ushort timeChannelId, ushort dataChannelId,
|
||||
uint[] tmnsConfig, ushort irigTimeDataPacketIntervalMs)
|
||||
{
|
||||
var packet = new RealTimeUDPStreamProfileAsyncPacket()
|
||||
{
|
||||
Info = new SliceServiceAsyncInfo(callback, userData),
|
||||
Profile = streamProfile,
|
||||
UDPAddress = udpAddress,
|
||||
TimeDataChannelId = timeChannelId,
|
||||
DataChannelId = dataChannelId,
|
||||
TMNSConfig = tmnsConfig,
|
||||
IRIGTimeDataPacketIntervalMs = irigTimeDataPacketIntervalMs
|
||||
};
|
||||
|
||||
LaunchAsyncWorker("Slice.SetUDPStreamProfile", AsyncSetUDPStreamProfile, packet);
|
||||
}
|
||||
|
||||
private void AsyncSetUDPStreamProfile(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeUDPStreamProfileAsyncPacket;
|
||||
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream))
|
||||
{
|
||||
var rtUDPAddress = packet.UDPAddress;
|
||||
var profile = (byte)packet.Profile;
|
||||
var timeChannelId = packet.TimeDataChannelId;
|
||||
var dataChannelId = packet.DataChannelId;
|
||||
var tmnsConfig = new TMNSConfig(packet.TMNSConfig);
|
||||
|
||||
var udpAddress = new UriBuilder(rtUDPAddress);
|
||||
byte[] tmp = Encoding.ASCII.GetBytes(udpAddress.Uri.AbsoluteUri.TrimEnd('/'));
|
||||
byte[] ipport = new byte[28];
|
||||
for (int i = 0; i < tmp.Length; i++)
|
||||
{
|
||||
ipport[i] = tmp[i];
|
||||
}
|
||||
|
||||
var ssaUDPStreamProfile = new StreamConfigUDPSet(this, AbstractCommandBase.Default_IO_Timeout)
|
||||
{
|
||||
Stream_Profile_Number = profile,
|
||||
Irig106Config0 = timeChannelId,
|
||||
Irig106Config1 = dataChannelId,
|
||||
TMNS_PCMSubFrameId = tmnsConfig.TMNS_PCMSubFrameId,
|
||||
TMNS_MsgId = tmnsConfig.TMNS_MsgId,
|
||||
TMNS_PCMMinorPerMajor = tmnsConfig.TMNS_PCMMinorPerMajor,
|
||||
TMNS_TMATSPortNumber = tmnsConfig.TMNS_TMATSPortNumber,
|
||||
IENAUDP_PortNumber = tmnsConfig.IENAUDP_PortNumber,
|
||||
TMNS5 = tmnsConfig.TMNS5,
|
||||
TMNS6 = tmnsConfig.TMNS6,
|
||||
TMNS7 = tmnsConfig.TMNS7,
|
||||
UdpIpPort = ipport
|
||||
};
|
||||
ssaUDPStreamProfile.SyncExecute();
|
||||
UDPStreamAddress = udpAddress.Uri.AbsoluteUri.TrimEnd('/');
|
||||
// FB15354: Enforce IRIG Time Data Packet Interval in order to read streaming data in NetView, etc.
|
||||
var ssaIRIGTimeData = new SetSystemAttributeSLICE2(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
ssaIRIGTimeData.SetValue(AttributeTypes.SystemAttributesSLICE2.S6A_IrigTimeDataPacketIntervalMsec, packet.IRIGTimeDataPacketIntervalMs.ToString(), true);
|
||||
ssaIRIGTimeData.SyncExecute();
|
||||
}
|
||||
packet.Info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
packet.Info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
packet.Info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
void IRealTimeActions.GetUDPStreamProfile(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("Slice.GetUDPStreamProfile", AsyncGetUDPStreamProfile, info);
|
||||
}
|
||||
|
||||
private void AsyncGetUDPStreamProfile(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as SliceServiceAsyncInfo;
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream))
|
||||
{
|
||||
var qsaUDPStreamProfile = new StreamConfigUDPGet(this, AbstractCommandBase.Default_IO_Timeout);
|
||||
qsaUDPStreamProfile.SyncExecute();
|
||||
var len = Array.IndexOf(qsaUDPStreamProfile.UdpIpPort, (byte)0x00);
|
||||
UDPStreamAddress = Encoding.ASCII.GetString(qsaUDPStreamProfile.UdpIpPort, 0, len < 0 ? qsaUDPStreamProfile.UdpIpPort.Length : len);
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class Slice<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
#region Trigger check
|
||||
void ITriggerCheckActions.PreStartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("Slice.PreStartTriggerCheck", AsyncPreStartTriggerCheck, info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// complete any prep work before starting trigger check that needs to be done
|
||||
/// </summary>
|
||||
protected virtual void AsyncPreStartTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
try
|
||||
{
|
||||
if (SupportsStartInversion())
|
||||
{
|
||||
var ssaPolarity = new SetSystemAttribute(this);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.StartRecordPolarity, (byte)(InvertStart ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
}
|
||||
if (SupportsTriggerInversion())
|
||||
{
|
||||
var ssaPolarity = new SetSystemAttribute(this);
|
||||
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.TriggerPolarity, (byte)(InvertTrigger ? 1 : 0), true);
|
||||
ssaPolarity.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log($"AsyncPreStartTriggerCheck failed, {ex.Message}");
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
void ITriggerCheckActions.PostStartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
void ITriggerCheckActions.StartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
LaunchAsyncWorker("Slice.StartTriggerCheck", AsyncStartTriggerCheck, info);
|
||||
}
|
||||
protected virtual void AsyncStartTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
var ihl = new InitializeHardwareLines(this) { LogCommands = true };
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
|
||||
{
|
||||
ihl.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InitializeHardwareLines.Log(ex, ihl);
|
||||
}
|
||||
if (ihl.TriggerInputShorted)
|
||||
{
|
||||
info.Error("TriggerInputShorted");
|
||||
return;
|
||||
}
|
||||
if (ihl.StartRecordShorted)
|
||||
{
|
||||
info.Error("StartInputShorted");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
return;
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
void ITriggerCheckActions.DoStartCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
|
||||
LaunchAsyncWorker("Slice.DoStartCheck", AsyncDoStartCheck, info);
|
||||
}
|
||||
void ITriggerCheckActions.DoTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
SliceServiceAsyncInfo info = null;
|
||||
if (null != callback)
|
||||
{
|
||||
info = new SliceServiceAsyncInfo(callback, userData);
|
||||
}
|
||||
|
||||
LaunchAsyncWorker("Slice.DoTriggerCheck", AsyncDoTriggerCheck, info);
|
||||
}
|
||||
|
||||
void ITriggerCheckActions.DoTriggerCheckSync()
|
||||
{
|
||||
var ihl = new InitializeHardwareLines(this) { LogCommands = false };
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
|
||||
{
|
||||
ihl.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
InitializeHardwareLines.Log(ex, ihl);
|
||||
}
|
||||
|
||||
var status = new ArmStatus
|
||||
{
|
||||
IsTriggered = ihl.TriggerInputShorted,
|
||||
IsArmed = !ihl.TriggerInputShorted,
|
||||
IsTriggerShorted = ihl.TriggerInputShorted,
|
||||
IsStartShorted = ihl.StartRecordShorted
|
||||
};
|
||||
SetDASArmStatus(status, true);
|
||||
}
|
||||
private void AsyncDoTriggerCheck(object asyncInfo)
|
||||
{
|
||||
SliceServiceAsyncInfo info = null;
|
||||
|
||||
if (asyncInfo is SliceServiceAsyncInfo)
|
||||
{
|
||||
info = (SliceServiceAsyncInfo)asyncInfo;
|
||||
}
|
||||
try
|
||||
{
|
||||
((ITriggerCheckActions)this).DoTriggerCheckSync();
|
||||
info?.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info?.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info?.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
private void AsyncDoStartCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
try
|
||||
{
|
||||
var ihl = new InitializeHardwareLines(this) { LogCommands = false };
|
||||
try
|
||||
{
|
||||
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines))
|
||||
{
|
||||
ihl.SyncExecute();
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { InitializeHardwareLines.Log(ex, ihl); }
|
||||
|
||||
var status = new ArmStatus
|
||||
{
|
||||
IsArmed = !ihl.TriggerInputShorted,
|
||||
IsRecording = ihl.StartRecordShorted
|
||||
};
|
||||
SetDASArmStatus(status, true);
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
void ITriggerCheckActions.CancelTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new SliceServiceAsyncInfo(callback, userData);
|
||||
|
||||
LaunchAsyncWorker("Slice.CancelTriggerCheck", AsyncCancelTriggerCheck, info);
|
||||
}
|
||||
|
||||
private void AsyncCancelTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is SliceServiceAsyncInfo info)) { return; }
|
||||
try
|
||||
{
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
480
DataPRO/IService/Classes/SLICEService/SLICE Service.cs
Normal file
480
DataPRO/IService/Classes/SLICEService/SLICE Service.cs
Normal file
@@ -0,0 +1,480 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using DTS.Common.DASResource;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Classes.Connection;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
|
||||
using DTS.Common.Events;
|
||||
using DTS.Common.Enums;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
|
||||
public partial class Slice<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// returns the requested range for an analog channel, making adjustment for nonlinear if needed
|
||||
/// </summary>
|
||||
protected static double GetRequestedRange(AnalogInputDASChannel analog, double MvPerEU)
|
||||
{
|
||||
if (null != analog.LinearizationFormula && analog.LinearizationFormula.IsValid())
|
||||
{
|
||||
switch (analog.LinearizationFormula.NonLinearStyle)
|
||||
{
|
||||
case NonLinearStyles.Polynomial:
|
||||
//polynomial can scale and should bypass this?
|
||||
break;
|
||||
default:
|
||||
if (MvPerEU.Equals(1))
|
||||
{
|
||||
APILogger.DebugLog($"GetRequestRange HC={analog?.HardwareChannelName ?? "NULL"}, mVPerEu={MvPerEU} - {InputRangeMV}");
|
||||
return InputRangeMV;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
APILogger.DebugLog($"GetRequestRange HC={analog?.HardwareChannelName ?? "NULL"}, mVPerEu={MvPerEU} DesiredRange={analog.DesiredRangeWithHeadroomEU}");
|
||||
return analog.DesiredRangeWithHeadroomEU * MvPerEU;
|
||||
}
|
||||
|
||||
public virtual bool SupportsRemoveLeapSeconds { get => false; }
|
||||
protected void SetRemoveSeconds()
|
||||
{
|
||||
//http://manuscript.dts.local/f/cases/31747/Add-support-for-GPS-Time-leap-seconds
|
||||
if (IsCommandSupported(ProtocolLimitedCommands.RemoveLeapSeconds))
|
||||
{
|
||||
try
|
||||
{
|
||||
var set = new SetSystemAttributeSLICE6AIR(this);
|
||||
set.SetValue(AttributeTypes.SystemAttributesSLICE6AIR.RemoveLeapSeconds, RunTestVariables.RemoveLeapSeconds ? (byte)1 : (byte)0, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected virtual QATSExtendedFault[] GetExtendedFaultFlags()
|
||||
{
|
||||
var list = new List<QATSExtendedFault>();
|
||||
try
|
||||
{
|
||||
if (!IsCommandSupported(ProtocolLimitedCommands.ExtendedFaultIds)) { return list.ToArray(); }
|
||||
var qee = new QueryArmAttribute(this) { Key = AttributeTypes.ArmAndEventAttributes.ExtFaultFlags, DeviceID = 0 };
|
||||
qee.SyncExecute();
|
||||
if (qee.Value is uint[] uints)
|
||||
{
|
||||
var first = uints[0];
|
||||
for (var i = 0; i < 32; i++)
|
||||
{
|
||||
if (0 != (first & (1 << i)))
|
||||
{
|
||||
list.Add((QATSExtendedFault)(1 << i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
public virtual bool SupportsADCSamplesPerPacket { get => false; }
|
||||
protected void SetADCSamplesPerPacket(int adcPerPacket)
|
||||
{
|
||||
//http://manuscript.dts.local/f/cases/31754/
|
||||
if (IsCommandSupported(ProtocolLimitedCommands.ADCSamplesPerPacket))
|
||||
{
|
||||
try
|
||||
{
|
||||
var get = new QuerySystemAttribute(this) { Key = AttributeTypes.SystemAttributes.S6A_IrigStreamBufferConfig };
|
||||
get.SyncExecute();
|
||||
var getParams = (ushort[])get.Value;
|
||||
getParams[1] = (ushort)adcPerPacket;
|
||||
var set = new SetSystemAttribute(this);
|
||||
set.SetValue(AttributeTypes.SystemAttributes.S6A_IrigStreamBufferConfig, getParams, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
APILogger.Log($"ADC samples per second not supported by firmware on {SerialNumber}");
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual uint[] GetExtendedFaultFlags(int eventIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var qee = new QueryEventAttribute(this) { Key = AttributeTypes.ArmAndEventAttributes.ExtFaultFlags, DeviceID = 0, EventNumber = Convert.ToUInt16(eventIndex) };
|
||||
qee.SyncExecute();
|
||||
return (uint[])qee.Value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
return new uint[] { 0, 0, 0, 0 };
|
||||
}
|
||||
/// <summary>
|
||||
/// surfaces an error to the application, if applicable
|
||||
/// http://manuscript.dts.local/f/cases/28312/Surface-Read-does-not-match-write-to-user
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
protected static void SurfaceApplicationError(string msg)
|
||||
{
|
||||
PageErrorEvent.SurfaceApplicationError(msg);
|
||||
}
|
||||
public ExcitationStatus ExcitationStatus { get; set; } = ExcitationStatus.Unknown;
|
||||
public virtual void SetIsStreamingSupported(bool supported = false)
|
||||
{
|
||||
IsStreamingSupported = false;
|
||||
}
|
||||
public virtual void ReadFirstUseDate()
|
||||
{
|
||||
IsFirstUseDateSupported = false;
|
||||
FirstUseDate = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// indicates date of first use
|
||||
/// null indicates the hardware has not been used since calibration
|
||||
/// only valid when IsFirstUseDateSupported is true
|
||||
/// 15524 DAS "First Use Date"
|
||||
/// </summary>
|
||||
public DateTime? FirstUseDate { get; set; } = null;
|
||||
/// <summary>
|
||||
/// returns whether the hardware supports first use or not
|
||||
/// for hardware to support first use the hardware must support
|
||||
/// storage for user attributes in firmware and also have been
|
||||
/// calibrated by software support hardware first use
|
||||
/// 15524 DAS "First Use Date"
|
||||
/// </summary>
|
||||
public bool IsFirstUseDateSupported { get; set; } = false;
|
||||
/// <summary>
|
||||
/// indicates whether or not streaming is supported
|
||||
/// 30429 TSR AIRs can enable/disable streaming via the DISABLE_STREAMING_FEATURE system attribute
|
||||
/// </summary>
|
||||
public bool IsStreamingSupported { get; set; } = false;
|
||||
public int RecordId { get; set; } = Common.Enums.Hardware.HardwareConstants.INVALID_IDASCOMMUNICATION_RECORD_ID;
|
||||
/// <summary>
|
||||
/// returns the total number of channels in the event
|
||||
/// </summary>
|
||||
/// <param name="eventNum"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual uint GetEventTotalChannels(int eventNum)
|
||||
{
|
||||
var eventTC = new QueryEventAttribute(this);
|
||||
eventTC.EventNumber = (ushort)eventNum;
|
||||
eventTC.Key = AttributeTypes.ArmAndEventAttributes.TotalChannels;
|
||||
eventTC.SyncExecute();
|
||||
return (byte)eventTC.Value;
|
||||
}
|
||||
|
||||
public string MACAddress { get; set; }
|
||||
public string[] DownstreamMACAddresses { get; set; }
|
||||
public virtual bool IsEthernetDistributor() { return false; }
|
||||
public virtual bool IsSlice6Distributor() { return false; }
|
||||
public virtual bool IsBattery() { return false; }
|
||||
public virtual bool IsTSRAIR() { return false; }
|
||||
public virtual bool IsSlice6Air() { return false; }
|
||||
public virtual bool IsSlice6AirTc() { return false; }
|
||||
public virtual bool IsScheduleEventCountSupported() { return false; }
|
||||
|
||||
public class SliceServiceQueryConfigAsyncInfo : SliceServiceAsyncInfo
|
||||
{
|
||||
public uint CRC { get; set; } = 0;
|
||||
public string ConfigString { get; set; } = string.Empty;
|
||||
public bool ReadIds { get; set; } = true;
|
||||
|
||||
public bool DeviceScaleFactors { get; set; } = true;
|
||||
public SliceServiceQueryConfigAsyncInfo(ServiceCallback _callback, object _userData, uint crc,
|
||||
string strConfig, bool bReadIds, bool bDeviceScaleFactors, bool differentModuleCountsAreOK) : base(_callback, _userData)
|
||||
{
|
||||
CRC = crc;
|
||||
ConfigString = strConfig;
|
||||
ReadIds = bReadIds;
|
||||
DeviceScaleFactors = bDeviceScaleFactors;
|
||||
DifferentModuleCountsAreOK = differentModuleCountsAreOK;
|
||||
}
|
||||
public bool DifferentModuleCountsAreOK { get; set; } = false;
|
||||
}
|
||||
public class SliceServiceQueryTestSetupAsyncInfo : SliceServiceAsyncInfo
|
||||
{
|
||||
public string TestSetupGuid { get; set; }
|
||||
public SliceServiceQueryTestSetupAsyncInfo(ServiceCallback _callback, object _userData, string testSetupGuid) : base(_callback, _userData)
|
||||
{
|
||||
TestSetupGuid = testSetupGuid;
|
||||
}
|
||||
}
|
||||
|
||||
public class SliceServiceSetTestSetupAsyncInfo : SliceServiceAsyncInfo
|
||||
{
|
||||
public string TestSetupXML { get; set; }
|
||||
public SliceServiceSetTestSetupAsyncInfo(ServiceCallback _callback, object _userData, string testSetupXML) : base(_callback, _userData)
|
||||
{
|
||||
TestSetupXML = testSetupXML;
|
||||
}
|
||||
}
|
||||
public class AutoDetectServiceAsyncInfo : SliceServiceAsyncInfo
|
||||
{
|
||||
public bool QueryConfiguration { get; set; } = true;
|
||||
|
||||
public AutoDetectServiceAsyncInfo(bool queryConfiguration, ServiceCallback callback, object userData)
|
||||
: base(callback, userData)
|
||||
{
|
||||
QueryConfiguration = queryConfiguration;
|
||||
}
|
||||
}
|
||||
public class SliceServiceAsyncInfo
|
||||
{
|
||||
public ServiceCallback callback { get; set; }
|
||||
public object userData { get; set; }
|
||||
public object functionData { get; set; }
|
||||
public PrePostResults PreOrPost { get; set; }
|
||||
public int? MaxTimeout { get; set; }
|
||||
|
||||
public SliceServiceAsyncInfo(ServiceCallback _callback, object _userData)
|
||||
{
|
||||
callback = _callback;
|
||||
userData = _userData;
|
||||
}
|
||||
|
||||
public void Error(string msg, Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cbData = new ServiceCallbackData();
|
||||
cbData.Status = ServiceCallbackData.CallbackStatus.Failure;
|
||||
cbData.ErrorMessage = msg;
|
||||
cbData.ErrorException = ex;
|
||||
cbData.UserData = userData;
|
||||
callback(cbData);
|
||||
}
|
||||
catch (Exception eex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoError, eex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Error(string msg)
|
||||
{
|
||||
Error(msg, null);
|
||||
}
|
||||
|
||||
public void Progress(int value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.ProgressReport;
|
||||
progressData.ProgressValue = value;
|
||||
progressData.UserData = userData;
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoProgressError, ex);
|
||||
}
|
||||
}
|
||||
|
||||
//public void NewData(IList<short[][]> datas, IList<UInt64> SampleNumbers)
|
||||
public void NewData(object obj)
|
||||
{
|
||||
if (obj is ServiceCallbackData.DiagnosticNewData)
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.SetNewDiagnosticData((obj as ServiceCallbackData.DiagnosticNewData));
|
||||
callback(progressData);
|
||||
}
|
||||
else if (obj is ServiceCallbackData.TiltNewData)
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.SetNewTiltData((obj as ServiceCallbackData.TiltNewData));
|
||||
callback(progressData);
|
||||
}
|
||||
else if (obj is ServiceCallbackData.UARTNewData)
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.SetNewUARTData(obj as ServiceCallbackData.UARTNewData);
|
||||
callback(progressData);
|
||||
}
|
||||
else if (obj is byte[])
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.SetNewByteData((byte[])obj);
|
||||
progressData.UserData = userData;
|
||||
callback(progressData);
|
||||
}
|
||||
else if (obj is DFConstantsAndEnums.T0CorrectionStatus status)
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
var i = (int)status;
|
||||
progressData.SetNewByteData(BitConverter.GetBytes(i));
|
||||
progressData.UserData = userData;
|
||||
callback(progressData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newdatadata = obj as NewDataData;
|
||||
var datas = newdatadata.datas;
|
||||
var samplenumbers = newdatadata.SampleNumbers;
|
||||
var timeStamps = newdatadata.TimeStamps;
|
||||
var sequenceNumbers = newdatadata.SequenceNumbers;
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
var sequenceNumber = 0UL;
|
||||
for (int i = 0; i < datas.Length && i < samplenumbers.Length; i++)
|
||||
{
|
||||
//polling apparently doesn't always populate sequence number
|
||||
//to prevent an indexing error just use the last one
|
||||
//18009 DataPRO becomes unusable when trying to put realtime in meter mode
|
||||
if (i < sequenceNumbers.Length) { sequenceNumber = sequenceNumbers[i]; }
|
||||
progressData.AddSampleData(datas[i], samplenumbers[i], timeStamps[i], sequenceNumber);
|
||||
}
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoNewDataError, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void NewData(short[][] data, UInt64 samplenumber, ulong timeStamp, ulong sequenceNumber)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.AddSampleData(data, samplenumber, timeStamp, sequenceNumber);
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoNewDataError, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Success()
|
||||
{
|
||||
try
|
||||
{
|
||||
var success = new ServiceCallbackData();
|
||||
success.Status = ServiceCallbackData.CallbackStatus.Success;
|
||||
success.UserData = userData;
|
||||
callback(success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoSuccessError, 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.SLICEAsyncInfoCancelError, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// compare to an object to determine equality
|
||||
/// </summary>
|
||||
/// <param name="right"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object right)
|
||||
{
|
||||
if (right == null)
|
||||
return false;
|
||||
|
||||
if (ReferenceEquals(this, right))
|
||||
return true;
|
||||
|
||||
var rightSlice = right as Slice<T>;
|
||||
if (rightSlice == null)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrEmpty(SerialNumber))
|
||||
{
|
||||
return string.IsNullOrEmpty(rightSlice.SerialNumber);
|
||||
}
|
||||
if (string.IsNullOrEmpty(rightSlice.SerialNumber))
|
||||
return false;
|
||||
return SerialNumber == rightSlice.SerialNumber;
|
||||
}
|
||||
/// <summary>
|
||||
/// returns identical index for any two 'equal' slice
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (string.IsNullOrEmpty(SerialNumber))
|
||||
return 0;
|
||||
return SerialNumber.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
DataPRO/IService/Classes/SampleData.cs
Normal file
25
DataPRO/IService/Classes/SampleData.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// represents a single poll of the h/w for data
|
||||
/// in G8 and older firmware there will probably be only one data point per channel
|
||||
/// per poll. Newer firmware should be capable of multiple datapoints per channel per request
|
||||
/// </summary>
|
||||
public class SampleData
|
||||
{
|
||||
public short[][] Data { get; set; }
|
||||
public ulong SampleNumber { get; set; }
|
||||
|
||||
public ulong TimeStamp { get; set; }
|
||||
|
||||
public ulong SequenceNumber { get; set; }
|
||||
|
||||
public SampleData(short[][] data, ulong sampleNumber, ulong timeStamp, ulong sequenceNumber)
|
||||
{
|
||||
Data = data;
|
||||
SampleNumber = sampleNumber;
|
||||
TimeStamp = timeStamp;
|
||||
SequenceNumber = sequenceNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
150
DataPRO/IService/Classes/ServiceCallbackData.cs
Normal file
150
DataPRO/IService/Classes/ServiceCallbackData.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// the base class for our internal callbacks (specific service callback to generic service)
|
||||
/// </summary>
|
||||
public class ServiceCallbackData
|
||||
{
|
||||
public class DiagnosticNewData
|
||||
{
|
||||
public int DasChannelNumber { get; set; }
|
||||
public enum Actions
|
||||
{
|
||||
MeasureBridgeMv, MeasureShunt, ScaleFactorMv, FactoryExcitation, MeasureExcitation,
|
||||
MeasureOffset, CalSignalCheck, FinalOffset, MeasureNoise, RemoveOffset, ShuntCheck, QueryModules, MeasureVoltages,
|
||||
TestChannelRun, TestChannelRead, MeasureInternalOffset, MeasureFinalInternalOffset
|
||||
};
|
||||
public Actions Action { get; set; }
|
||||
public object Result { get; set; }
|
||||
}
|
||||
|
||||
public class TiltNewData
|
||||
{
|
||||
public double[] TiltData { get; set; }
|
||||
|
||||
public double[] AccelData { get; set; }
|
||||
}
|
||||
|
||||
public class TemperatureData
|
||||
{
|
||||
public int Channel1 { get; set; }
|
||||
public int Channel2 { get; set; }
|
||||
public DateTime[] Timestamps { get; set; }
|
||||
public double[] Sensor1 { get; set; }
|
||||
public double[] Sensor2 { get; set; }
|
||||
}
|
||||
public class UARTNewData
|
||||
{
|
||||
public ulong DataOffset { get; set; }
|
||||
public byte[] UARTData { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The different types of callbacks
|
||||
/// </summary>
|
||||
public enum CallbackStatus
|
||||
{
|
||||
ProgressReport,
|
||||
NewData,
|
||||
Timeout,
|
||||
Success,
|
||||
Failure,
|
||||
Canceled,
|
||||
InvalidParameters // and others
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What kind of message is this
|
||||
/// </summary>
|
||||
public CallbackStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If it was an error (Status==Failure), the message is here
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If it was an exception (Status==Failure), it's here otherwise null
|
||||
/// </summary>
|
||||
public System.Exception ErrorException { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If it was ProgressReport, this is the percentage done
|
||||
/// </summary>
|
||||
public int ProgressValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user supplied data is here
|
||||
/// </summary>
|
||||
public object UserData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// callback could contain multiple non contiguous samples
|
||||
/// if so, we will need to know a separate sample number and short [][]
|
||||
/// for each break
|
||||
/// this is mostly for nicer realtime handling so data can be obtained from the
|
||||
/// h/w at a different rate then the UI is updated at
|
||||
/// </summary>
|
||||
private IList<SampleData> _Data = new List<SampleData>();
|
||||
/// <summary>
|
||||
/// returns a collection of <see cref="SampleData">SampleData</see>
|
||||
/// objects which contain sequences of channel data and a number indicating
|
||||
/// which samle number in the h/w each sequence begins at
|
||||
/// </summary>
|
||||
public SampleData[] DataSamples
|
||||
{
|
||||
get => _Data.ToArray();
|
||||
set => _Data = new List<SampleData>(value);
|
||||
}
|
||||
|
||||
private DiagnosticNewData _newDiagnosticData = null;
|
||||
|
||||
private TiltNewData _newTiltData = null;
|
||||
|
||||
private UARTNewData _newUartData = null;
|
||||
private TemperatureData _newTemperatureData = null;
|
||||
public DiagnosticNewData NewDiagnosticData => _newDiagnosticData;
|
||||
public void SetNewDiagnosticData(DiagnosticNewData data) { _newDiagnosticData = data; }
|
||||
|
||||
public void SetNewTiltData(TiltNewData data) { _newTiltData = data; }
|
||||
|
||||
public void SetNewTemperatureData(TemperatureData data) { _newTemperatureData = data; }
|
||||
public void SetNewUARTData(UARTNewData data) { _newUartData = data; }
|
||||
|
||||
private byte[] _byteData = null;
|
||||
public void SetNewByteData(byte[] data) { _byteData = data; }
|
||||
public byte[] ByteData { get => _byteData; }
|
||||
public TiltNewData NewTiltData => _newTiltData;
|
||||
|
||||
public UARTNewData NewUARTData => _newUartData;
|
||||
|
||||
public TemperatureData NewTemperatureData => _newTemperatureData;
|
||||
/// <summary>
|
||||
/// adds a new sample (composed of multiple channels of short [] data and
|
||||
/// a sample number indicating the start of the data
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="sampleNumber"></param>
|
||||
public void AddSampleData(short[][] data, ulong sampleNumber, ulong timeStamp, ulong sequenceNumber)
|
||||
{
|
||||
_Data.Add(new SampleData(data, sampleNumber, timeStamp, sequenceNumber));
|
||||
}
|
||||
/// <summary>
|
||||
/// returns the <see cref="SampleData">SampleData</see> struct
|
||||
/// at a given index among a collection of samples
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public SampleData GetSampleData(int index) { return _Data[index]; }
|
||||
/// <summary>
|
||||
/// the total number of different non contiguous samples in the data
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int GetNumberOfSamples() { return _Data.Count; }
|
||||
}
|
||||
}
|
||||
13
DataPRO/IService/Classes/StaticInformation.cs
Normal file
13
DataPRO/IService/Classes/StaticInformation.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class StaticInformation
|
||||
{
|
||||
public readonly double[] NominalRanges;
|
||||
|
||||
public StaticInformation(double[] _NominalRanges)
|
||||
{
|
||||
NominalRanges = _NominalRanges;
|
||||
}
|
||||
}
|
||||
}
|
||||
2208
DataPRO/IService/Classes/TDAS Service/Arming.cs
Normal file
2208
DataPRO/IService/Classes/TDAS Service/Arming.cs
Normal file
File diff suppressed because it is too large
Load Diff
2437
DataPRO/IService/Classes/TDAS Service/Callibration.cs
Normal file
2437
DataPRO/IService/Classes/TDAS Service/Callibration.cs
Normal file
File diff suppressed because it is too large
Load Diff
846
DataPRO/IService/Classes/TDAS Service/Config.Attributes.cs
Normal file
846
DataPRO/IService/Classes/TDAS Service/Config.Attributes.cs
Normal file
@@ -0,0 +1,846 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.DASLib.Service;
|
||||
using DTS.Slice.Service;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
long IDASCommunication.MaxMemory()
|
||||
{
|
||||
long result = 0;
|
||||
if ((DASInfo.MaxEventStorageSpaceInBytes == null) && (DASInfo.Modules.Count() > 0))
|
||||
{
|
||||
result = long.MaxValue;
|
||||
foreach (InfoResult.Module module in DASInfo.Modules)
|
||||
{
|
||||
if (module.SerialNumber != "EMPTY")
|
||||
{
|
||||
result = (long)Math.Min(result, (decimal)(module.MaxEventStorageSpaceInBytes / module.NumberOfBytesPerSampleClock));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((DASInfo.MaxEventStorageSpaceInBytes != null) && (DASInfo.NumberOfBytesPerSampleClock != null))
|
||||
{
|
||||
result = (long)(DASInfo.MaxEventStorageSpaceInBytes / DASInfo.NumberOfBytesPerSampleClock);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
uint IDASCommunication.MinSampleRate()
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
private const double _MaxG5SamplingRate = 100000.0;
|
||||
private const double _MaxSamplingRate = 305000.0; //FB16312 changed to 305kHz to match TDC "Version 5.1B"
|
||||
uint IDASCommunication.MaxSampleRate(int numberOfConfiguredChannels)
|
||||
{
|
||||
return MaxSampleRate(IsG5(), numberOfConfiguredChannels);
|
||||
}
|
||||
|
||||
uint IDASCommunication.MaxAAFilterRate()
|
||||
{
|
||||
return MaxAAFilterRateHz;
|
||||
}
|
||||
//FB16312: surface calculation for generic use
|
||||
public static uint MaxSampleRate(bool isG5, int numberOfConfiguredChannels)
|
||||
{
|
||||
if (isG5)
|
||||
{
|
||||
//return Convert.ToUInt32(System.Math.Floor(_MaxSamplingRate / 32D));
|
||||
return Convert.ToUInt32(_MaxG5SamplingRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (numberOfConfiguredChannels > 0) ?
|
||||
Convert.ToUInt32(Math.Floor(_MaxSamplingRate / numberOfConfiguredChannels)) :
|
||||
Convert.ToUInt32(Math.Floor(_MaxSamplingRate / 1));
|
||||
}
|
||||
}
|
||||
/*
|
||||
private class ConfigAttributes
|
||||
{
|
||||
ICommunication com { get; set; }
|
||||
|
||||
public ConfigAttributes(DTS.Common.Interface.DASFactory.ICommunication _com)
|
||||
{
|
||||
com = _com;
|
||||
}
|
||||
|
||||
public void PurgeStaleData(IDASCommunication das)
|
||||
{
|
||||
var cmd = new SetArmAttributesToDefaults(com);
|
||||
cmd.SyncExecute();
|
||||
|
||||
// get bridge stuff
|
||||
var dacValues = new UInt16[das.ConfigData.NumberOfChannels()];
|
||||
foreach (var module in das.DASInfo.Modules)
|
||||
{
|
||||
var odQuery = new QuerySystemAttribute_Bridge(com);
|
||||
odQuery.DeviceID = (byte)(module.ModuleArrayIndex + 1);
|
||||
|
||||
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACA_Midscale;
|
||||
odQuery.SyncExecute();
|
||||
dacValues[module.ModuleArrayIndex * 3 + 0] = (UInt16)odQuery.Value;
|
||||
|
||||
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACB_Midscale;
|
||||
odQuery.SyncExecute();
|
||||
dacValues[module.ModuleArrayIndex * 3 + 1] = (UInt16)odQuery.Value;
|
||||
|
||||
odQuery.Key = AttributeTypes.SystemAttributes_Bridge.OffsetDACC_Midscale;
|
||||
odQuery.SyncExecute();
|
||||
dacValues[module.ModuleArrayIndex * 3 + 2] = (UInt16)odQuery.Value;
|
||||
}
|
||||
|
||||
// set base stuff
|
||||
var odSet = new SetArmAttribute(com);
|
||||
odSet.SetValue(AttributeTypes.ArmAndEventAttributes.StackChannelOffsetDACSettings, dacValues, true);
|
||||
odSet.SyncExecute();
|
||||
}
|
||||
|
||||
#region Arm attribute helpers
|
||||
|
||||
private void SetArmAttribute(AttributeTypes.ArmAndEventAttributes key, object value, bool ShouldOverwrite)
|
||||
{
|
||||
var set = new SetArmAttribute(com);
|
||||
set.SetValue(key, value, ShouldOverwrite);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, Test.Module.RecordingMode value)
|
||||
{
|
||||
SetArmAttribute(key, (byte)value, true);
|
||||
}
|
||||
|
||||
public void SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, UInt32 value)
|
||||
{
|
||||
SetArmAttribute(key, value, true);
|
||||
}
|
||||
|
||||
public void SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, float value)
|
||||
{
|
||||
SetArmAttribute(key, value, true);
|
||||
}
|
||||
|
||||
public void SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, string value)
|
||||
{
|
||||
var set = new SetArmAttribute(com);
|
||||
var ByteArrayData = Encoding.UTF8.GetBytes(value);
|
||||
set.SetValue(key, ByteArrayData, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, UInt64 value)
|
||||
{
|
||||
SetArmAttribute(key, value, true);
|
||||
}
|
||||
|
||||
public void GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, out Test.Module.RecordingMode value)
|
||||
{
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = key;
|
||||
query.SyncExecute();
|
||||
if ((AttributeTypes.AttributeDataTypes)query.DataType != AttributeTypes.AttributeDataTypes.UInt8)
|
||||
throw new System.Exception("ConfigurationService.GetArmAttribute.RecordingMode: Found type " + (AttributeTypes.AttributeDataTypes)query.DataType);
|
||||
value = (Test.Module.RecordingMode)query.Value;
|
||||
}
|
||||
|
||||
public void GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, out UInt32 value)
|
||||
{
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = key;
|
||||
query.SyncExecute();
|
||||
if ((AttributeTypes.AttributeDataTypes)query.DataType != AttributeTypes.AttributeDataTypes.UInt32)
|
||||
throw new System.Exception("ConfigurationService.GetArmAttribute.UInt32: Found type " + (AttributeTypes.AttributeDataTypes)query.DataType);
|
||||
value = (UInt32)query.Value;
|
||||
}
|
||||
|
||||
public void GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, out float value)
|
||||
{
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = key;
|
||||
query.SyncExecute();
|
||||
if ((AttributeTypes.AttributeDataTypes)query.DataType != AttributeTypes.AttributeDataTypes.Float32)
|
||||
throw new System.Exception("ConfigurationService.GetArmAttribute.float: Found type " + (AttributeTypes.AttributeDataTypes)query.DataType);
|
||||
value = (float)query.Value;
|
||||
}
|
||||
|
||||
public void GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, out string value)
|
||||
{
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = key;
|
||||
query.SyncExecute();
|
||||
if ((AttributeTypes.AttributeDataTypes)query.DataType != AttributeTypes.AttributeDataTypes.Unicode)
|
||||
{
|
||||
throw new System.Exception("ConfigurationService.GetArmAttribute.string: Found type " + (AttributeTypes.AttributeDataTypes)query.DataType);
|
||||
}
|
||||
var values = query.Value as byte[];
|
||||
value = Encoding.UTF8.GetString(values);
|
||||
}
|
||||
|
||||
public void GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes key, out UInt64 value)
|
||||
{
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = key;
|
||||
query.SyncExecute();
|
||||
if ((AttributeTypes.AttributeDataTypes)query.DataType != AttributeTypes.AttributeDataTypes.UInt64)
|
||||
throw new System.Exception("ConfigurationService.GetArmAttribute.UInt64: Found type " + (AttributeTypes.AttributeDataTypes)query.DataType);
|
||||
value = (UInt64)query.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region XML attributes
|
||||
|
||||
public void StoreXMLConfig(string data, SliceServiceAsyncInfo info, double ProgressSteps)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// since this might contain multi byte characters, we need to convert it to a byte array first
|
||||
var ByteArrayData = Encoding.UTF8.GetBytes(data);
|
||||
|
||||
// calc how many we need
|
||||
var NumBlocks = ByteArrayData.Length / DTS.Slice.Service.Attribute.MaxSingleAttributeSize;
|
||||
if ((ByteArrayData.Length % DTS.Slice.Service.Attribute.MaxSingleAttributeSize) != 0)
|
||||
{
|
||||
NumBlocks++;
|
||||
}
|
||||
|
||||
// write the blocks
|
||||
// for progress, assume that we'll have about 40 blocks to write
|
||||
var blockWeight = 40.0 / (double)NumBlocks;
|
||||
for (int BlockIdx = 0; BlockIdx < NumBlocks; BlockIdx++)
|
||||
{
|
||||
// contruct the current block
|
||||
int blockLength = ByteArrayData.Length - (BlockIdx * DTS.Slice.Service.Attribute.MaxSingleAttributeSize);
|
||||
if (blockLength > DTS.Slice.Service.Attribute.MaxSingleAttributeSize)
|
||||
{
|
||||
blockLength = DTS.Slice.Service.Attribute.MaxSingleAttributeSize;
|
||||
}
|
||||
var block = new byte[blockLength];
|
||||
Array.Copy(ByteArrayData, BlockIdx * DTS.Slice.Service.Attribute.MaxSingleAttributeSize, block, 0, blockLength);
|
||||
|
||||
// write it to firmware
|
||||
var AttrSet = new SetArmAttribute(com);
|
||||
var attrNum = (AttributeTypes.ArmAndEventAttributes)(DTS.Slice.Service.Attribute.BulkAttributeStartNumber + BlockIdx);
|
||||
AttrSet.SetValue(attrNum, block, AttributeTypes.AttributeDataTypes.Unicode, true);
|
||||
AttrSet.SyncExecute();
|
||||
info.Progress((int)((12.0 + blockWeight * (double)BlockIdx) / ProgressSteps * 100.0));
|
||||
}
|
||||
|
||||
// write our speacial header attribute
|
||||
var InvariantCulture = new System.Globalization.CultureInfo("");
|
||||
var BlockList = new StringBuilder(DTS.Slice.Service.Attribute.BulkAttributeStartNumber.ToString(InvariantCulture),
|
||||
DTS.Slice.Service.Attribute.MaxSingleAttributeSize);
|
||||
for (int BlockIdx = 1; BlockIdx < NumBlocks; BlockIdx++)
|
||||
{
|
||||
BlockList.Append("," + (DTS.Slice.Service.Attribute.BulkAttributeStartNumber + BlockIdx).ToString(InvariantCulture));
|
||||
}
|
||||
var HeaderAttrSet = new SetArmAttribute(com);
|
||||
// this attribute only contains digits and commas so it's OK to keep it as Ascii
|
||||
HeaderAttrSet.SetValue(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.StoredConfigIndex,
|
||||
BlockList.ToString(), AttributeTypes.AttributeDataTypes.Ascii, true);
|
||||
HeaderAttrSet.SyncExecute();
|
||||
}
|
||||
|
||||
public string RetrieveXMLConfig()
|
||||
{
|
||||
// first get our special header attribute
|
||||
var AttrGet = new QueryArmAttribute(com);
|
||||
AttrGet.Key = AttributeTypes.ArmAndEventAttributes.StoredConfigIndex;
|
||||
AttrGet.SyncExecute();
|
||||
// this attribute only contains digits and commas so it's OK to keep it as Ascii (see above)
|
||||
var BlockListStr = AttrGet.Value as string;
|
||||
|
||||
// still there?
|
||||
if (string.IsNullOrEmpty(BlockListStr))
|
||||
{
|
||||
// "Slice.RetrieveAttributes: Header attribute as string is empty"
|
||||
throw new System.Exception(Strings.Slice_RetrieveAttributes_Err2);
|
||||
}
|
||||
|
||||
var InvariantCulture = new System.Globalization.CultureInfo("");
|
||||
var BlockListStrArr = BlockListStr.Split(',');
|
||||
var BlockList = new List<ushort>();
|
||||
foreach (string NumStr in BlockListStrArr)
|
||||
{
|
||||
ushort Number = 0;
|
||||
if (!ushort.TryParse(NumStr, System.Globalization.NumberStyles.Integer, InvariantCulture, out Number))
|
||||
{
|
||||
// "Slice.RetrieveAttributes: Header attribute is invalid"
|
||||
throw new System.Exception(Strings.Slice_RetrieveAttributes_Err3);
|
||||
}
|
||||
BlockList.Add(Number);
|
||||
}
|
||||
var AllStrings = new StringBuilder(BlockList.Count * DTS.Slice.Service.Attribute.MaxSingleAttributeSize);
|
||||
|
||||
foreach (var AttrNumber in BlockList)
|
||||
{
|
||||
AttrGet.Key = (AttributeTypes.ArmAndEventAttributes)AttrNumber;
|
||||
AttrGet.SyncExecute();
|
||||
// old version stored the data as Ascii
|
||||
if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Ascii)
|
||||
{
|
||||
var values = AttrGet.Value as string;
|
||||
AllStrings.Append(values);
|
||||
}
|
||||
// new version uses Unicode (basically byte[])
|
||||
else if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Unicode)
|
||||
{
|
||||
var values = AttrGet.Value as byte[];
|
||||
var str = Encoding.UTF8.GetString(values);
|
||||
AllStrings.Append(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is really bad!
|
||||
throw new System.Exception(string.Format("RetrieveXMLConfig: Unknown datatype {0}", AttrGet.DataType.ToString()));
|
||||
}
|
||||
}
|
||||
var WholeStr = AllStrings.ToString();
|
||||
if (string.IsNullOrEmpty(WholeStr))
|
||||
{
|
||||
// "Slice.RetrieveAttributes: Attributes are empty"
|
||||
throw new System.Exception(Strings.Slice_RetrieveAttributes_Err4);
|
||||
}
|
||||
return WholeStr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the XML string that was split and stored in the Arm attributes
|
||||
/// </summary>
|
||||
/// <param name="eventNum">The event number to get it from</param>
|
||||
/// <param name="progress"></param>
|
||||
/// <returns>The combined XML string</returns>
|
||||
public string RetrieveEventXMLConfig(int eventNum, QueryDownloadProgress progress)
|
||||
{
|
||||
// first get our special header attribute
|
||||
var AttrGet = new QueryEventAttribute(com);
|
||||
AttrGet.EventNumber = (ushort)eventNum;
|
||||
AttrGet.Key = AttributeTypes.ArmAndEventAttributes.StoredConfigIndex;
|
||||
AttrGet.SyncExecute();
|
||||
progress.Step();
|
||||
|
||||
var BlockListStr = AttrGet.Value as string;
|
||||
|
||||
// still there?
|
||||
if (string.IsNullOrEmpty(BlockListStr))
|
||||
{
|
||||
// "Slice.RetrieveEventAttributes: Header attribute is empty"
|
||||
throw new System.Exception(Strings.Slice_RetrieveEventAttributes_Err1);
|
||||
}
|
||||
|
||||
var InvariantCulture = new System.Globalization.CultureInfo("");
|
||||
var BlockListStrArr = BlockListStr.Split(',');
|
||||
var BlockList = new List<ushort>();
|
||||
foreach (string NumStr in BlockListStrArr)
|
||||
{
|
||||
ushort Number = 0;
|
||||
if (!ushort.TryParse(NumStr, System.Globalization.NumberStyles.Integer, InvariantCulture, out Number))
|
||||
{
|
||||
// "Slice.RetrieveEventAttributes: Header attribute is invalid"
|
||||
throw new System.Exception(Strings.Slice_RetrieveEventAttributes_Err2);
|
||||
}
|
||||
BlockList.Add(Number);
|
||||
}
|
||||
var AllStrings = new StringBuilder(BlockList.Count * DTS.Slice.Service.Attribute.MaxSingleAttributeSize);
|
||||
|
||||
foreach (var AttrNumber in BlockList)
|
||||
{
|
||||
AttrGet.Key = (AttributeTypes.ArmAndEventAttributes)AttrNumber;
|
||||
AttrGet.SyncExecute();
|
||||
progress.Step();
|
||||
// old version stored the data as Ascii
|
||||
if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Ascii)
|
||||
{
|
||||
var values = AttrGet.Value as string;
|
||||
AllStrings.Append(values);
|
||||
}
|
||||
// new version uses Unicode (basically byte[])
|
||||
else if (AttrGet.DataType == AttributeTypes.AttributeDataTypes.Unicode)
|
||||
{
|
||||
var values = AttrGet.Value as byte[];
|
||||
var str = Encoding.UTF8.GetString(values);
|
||||
AllStrings.Append(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is really bad!
|
||||
throw new System.Exception(string.Format("RetrieveEventXMLConfig(event={0}): Unknown datatype {1}",
|
||||
eventNum, AttrGet.DataType.ToString()));
|
||||
}
|
||||
}
|
||||
var WholeStr = AllStrings.ToString();
|
||||
if (string.IsNullOrEmpty(WholeStr))
|
||||
{
|
||||
// "Slice.RetrieveEventAttributes: Attributes are empty"
|
||||
throw new System.Exception(Strings.Slice_RetrieveEventAttributes_Err3);
|
||||
}
|
||||
return WholeStr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void ConfigureRange(float[] ranges)
|
||||
{
|
||||
// this function shall just set the range attribute for channel
|
||||
var set = new SetArmAttribute(com);
|
||||
set.SetValue(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.StackChannelRangesMillivolts, ranges, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void ConfigureBridge(bool[] IsHalfBridgeArray)
|
||||
{
|
||||
// we need to construct a byte array, true==1, false==0
|
||||
var byteArray = new byte[IsHalfBridgeArray.Length];
|
||||
for (int idx = 0; idx < IsHalfBridgeArray.Length; idx++)
|
||||
{
|
||||
byteArray[idx] = (byte)(IsHalfBridgeArray[idx] ? 1 : 0);
|
||||
}
|
||||
var set = new SetArmAttribute(com);
|
||||
set.SetValue(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.StackChannelBridgeCompletionEnable, byteArray, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public void ConfigureBridgeResistance(UInt16[] BridgeResistanceArray)
|
||||
{
|
||||
// this function shall just set the bridge resistance for the channels
|
||||
var set = new SetArmAttribute(com);
|
||||
set.SetValue(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.StackChannelBridgeResistanceOhms, BridgeResistanceArray, true);
|
||||
set.SyncExecute();
|
||||
}
|
||||
|
||||
public float[] GetScaleFactors()
|
||||
{
|
||||
// this function shall just set the range attribute for channel
|
||||
var query = new QueryArmAttribute(com);
|
||||
query.Key = AttributeTypes.ArmAndEventAttributes.StackChannelScaleFactorsMillivoltsPerADC;
|
||||
query.SyncExecute();
|
||||
return query.Value as float[];
|
||||
}
|
||||
|
||||
#region Attributes
|
||||
|
||||
public UInt32 SampleRate
|
||||
{
|
||||
get
|
||||
{
|
||||
UInt32 Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.SampleRate, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.SampleRate, value);
|
||||
}
|
||||
}
|
||||
|
||||
public float AAFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
float Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.AAFilterFrequency, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.AAFilterFrequency, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string TestID
|
||||
{
|
||||
get
|
||||
{
|
||||
string Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.Name, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.Name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string TestDescription
|
||||
{
|
||||
get
|
||||
{
|
||||
string Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.Description, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.Description, value);
|
||||
}
|
||||
}
|
||||
|
||||
public UInt64 PreTriggerSamples
|
||||
{
|
||||
get
|
||||
{
|
||||
UInt64 Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong PostTriggerSamples
|
||||
{
|
||||
get
|
||||
{
|
||||
UInt64 Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Test.Module.RecordingMode TestType
|
||||
{
|
||||
get
|
||||
{
|
||||
Test.Module.RecordingMode Value;
|
||||
GetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.ArmMode, out Value);
|
||||
return Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetArmAttribute(DTS.DASLib.Command.SLICE.AttributeTypes.ArmAndEventAttributes.ArmMode, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper functions
|
||||
|
||||
public uint CalculateNumberOfModules(ConfigurationData config, uint numChannels)
|
||||
{
|
||||
// this is a shortcut for now
|
||||
return numChannels / 3;
|
||||
}
|
||||
|
||||
public UInt64 GetEventTotalSamples(int eventNum)
|
||||
{
|
||||
ulong samples = 0L;
|
||||
var eventSamples = new QueryEventAttribute(com);
|
||||
eventSamples.EventNumber = (ushort)eventNum;
|
||||
eventSamples.Key = AttributeTypes.ArmAndEventAttributes.TotalSamplesRecorded;
|
||||
try
|
||||
{
|
||||
eventSamples.SyncExecute();
|
||||
samples = (ulong)eventSamples.Value;
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
try
|
||||
{ //
|
||||
// Try to get enough info to proceed with a rump download.
|
||||
//
|
||||
var preSamplesRequested = new QueryEventAttribute(com);
|
||||
preSamplesRequested.EventNumber = (ushort)eventNum;
|
||||
preSamplesRequested.Key = AttributeTypes.ArmAndEventAttributes.PreTriggerSamplesRequested;
|
||||
preSamplesRequested.SyncExecute();
|
||||
|
||||
var postSamplesRequested = new QueryEventAttribute(com);
|
||||
postSamplesRequested.EventNumber = (ushort)eventNum;
|
||||
postSamplesRequested.Key = AttributeTypes.ArmAndEventAttributes.PostTriggerSamplesRequested;
|
||||
postSamplesRequested.SyncExecute();
|
||||
|
||||
samples = (ulong)preSamplesRequested.Value + (ulong)postSamplesRequested.Value + 1L;
|
||||
|
||||
var totalSamplesRecorded = new SetEventAttribute(com);
|
||||
totalSamplesRecorded.EventNumber = (ushort)eventNum;
|
||||
totalSamplesRecorded.SetValue(AttributeTypes.ArmAndEventAttributes.TotalSamplesRecorded, samples, true);
|
||||
totalSamplesRecorded.SyncExecute();
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new System.ApplicationException("encountered problem re-querying pre/post samples after initial total sample request failure", ex);
|
||||
}
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
public UInt64 GetEventTriggerSampleNumber(int eventNum)
|
||||
{
|
||||
var eventTSN = new QueryEventAttribute(com);
|
||||
eventTSN.EventNumber = (ushort)eventNum;
|
||||
eventTSN.Key = AttributeTypes.ArmAndEventAttributes.TriggerSampleNumber;
|
||||
try { eventTSN.SyncExecute(); }
|
||||
catch (System.Exception) { return (ulong)0; }
|
||||
return (ulong)eventTSN.Value;
|
||||
}
|
||||
|
||||
public void SetEventTriggerSampleNumber(int eventNum, UInt64 sampleNumber)
|
||||
{
|
||||
var eventTSN = new SetEventAttribute(com);
|
||||
eventTSN.EventNumber = (ushort)eventNum;
|
||||
eventTSN.SetValue(AttributeTypes.ArmAndEventAttributes.TriggerSampleNumber, sampleNumber, true);
|
||||
eventTSN.SyncExecute();
|
||||
}
|
||||
|
||||
public UInt64 GetEventStartRecordSampleNumber(int eventNum)
|
||||
{
|
||||
var eventSRSN = new QueryEventAttribute(com);
|
||||
eventSRSN.EventNumber = (ushort)eventNum;
|
||||
eventSRSN.Key = AttributeTypes.ArmAndEventAttributes.StartRecordSampleNumber;
|
||||
try { eventSRSN.SyncExecute(); }
|
||||
catch (System.Exception) { return (ulong)0; }
|
||||
return (ulong)eventSRSN.Value;
|
||||
}
|
||||
|
||||
public uint GetEventSamplerate(int eventNum)
|
||||
{
|
||||
var eventSR = new QueryEventAttribute(com);
|
||||
eventSR.EventNumber = (ushort)eventNum;
|
||||
eventSR.Key = AttributeTypes.ArmAndEventAttributes.SampleRate;
|
||||
eventSR.SyncExecute();
|
||||
return (uint)eventSR.Value;
|
||||
}
|
||||
|
||||
public uint GetEventTotalChannels(int eventNum)
|
||||
{
|
||||
var eventTC = new QueryEventAttribute(com);
|
||||
eventTC.EventNumber = (ushort)eventNum;
|
||||
eventTC.Key = AttributeTypes.ArmAndEventAttributes.TotalChannels;
|
||||
eventTC.SyncExecute();
|
||||
return (uint)(byte)eventTC.Value;
|
||||
}
|
||||
|
||||
public DateTime GetEventStartTime(int eventNum)
|
||||
{
|
||||
var eventST = new QueryEventAttribute(com);
|
||||
eventST.EventNumber = (ushort)eventNum;
|
||||
eventST.Key = AttributeTypes.ArmAndEventAttributes.StartTime;
|
||||
try { eventST.SyncExecute(); }
|
||||
catch (System.Exception) { return new DateTime(0); }
|
||||
DateTime rv = new DateTime(0).AddSeconds((double)((uint)eventST.Value));
|
||||
return rv;
|
||||
}
|
||||
|
||||
public double GetEventAAFilter(int eventNum)
|
||||
{
|
||||
var eventFF = new QueryEventAttribute(com);
|
||||
eventFF.EventNumber = (ushort)eventNum;
|
||||
eventFF.Key = AttributeTypes.ArmAndEventAttributes.AAFilterFrequency;
|
||||
eventFF.SyncExecute();
|
||||
float aafilter = (float)eventFF.Value;
|
||||
return (double)aafilter;
|
||||
}
|
||||
|
||||
public double GetEventExcitation(int eventNum)
|
||||
{
|
||||
var eventExc = new QueryEventAttribute(com);
|
||||
eventExc.EventNumber = (ushort)eventNum;
|
||||
throw new ApplicationException("GetEventExcitation needs to be implemented by channel ...");
|
||||
//return (double)eventExc.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of "level triggered" samples required for a level trigger to be declared by the DAS.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="eventNum">
|
||||
/// The <see cref="int"/> event number for which we want level trigger qualification sample information.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The <see cref="int"/> number of contiguous "level triggered" samples required for a level trigger event.
|
||||
/// </returns>
|
||||
///
|
||||
private int[] GetLevelTriggerQualificationSamples(int eventNum)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventLevTrigQlfSamps = new QueryEventAttribute(com);
|
||||
eventLevTrigQlfSamps.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerQualificationSamples;
|
||||
eventLevTrigQlfSamps.SyncExecute();
|
||||
return (int[])(eventLevTrigQlfSamps.Value);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new ApplicationException("encountered problem getting number of level trigger qualification samples from hardware for event " + eventNum.ToString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get determination from hardware whether or not the associated DAS has directly experienced a level trigger event.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="eventNum">
|
||||
/// The <see cref="int"/> event number for which we want level trigger seen information.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// <see cref="bool"/> True if the associated DAS has experienced a level trigger event; False otherwise.
|
||||
/// </returns>
|
||||
///
|
||||
private bool[] GetLevelTriggerSeen(int eventNum)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventLevTrigSeen = new QueryEventAttribute(com);
|
||||
eventLevTrigSeen.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerSeen;
|
||||
eventLevTrigSeen.SyncExecute();
|
||||
return (bool[])(eventLevTrigSeen.Value);
|
||||
}
|
||||
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
throw new ApplicationException("encountered problem getting \"level trigger seen\" condition from hardware for event " + eventNum.ToString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get number of samples that the associated hardware adjusted its level trigger time value from the time it
|
||||
/// actually issued a trigger fault. This adjustment is necessary because several contiguous level-triggered
|
||||
/// samples are necessary before some flavors of DAS will declare an actual level trigger. Once the hardware has
|
||||
/// determined that a trigger has occured, it must "backdate" the T0 to match the time of the first
|
||||
/// level-triggered sample. This number only exists for hardware that has directly experienced a level trigger
|
||||
/// condition.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="eventNum">
|
||||
/// The <see cref="int"/> number of the event we want the adjustment samples for.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The number of samples that this DAS' trigger time value has been adjusted to compensate for time required
|
||||
/// by the hardware for level trigger evaluation. If the associated hardware did not directly experience the
|
||||
/// level trigger, this value will be null.
|
||||
/// </returns>
|
||||
///
|
||||
public int?[] GetEventLevelTriggerT0AdjustmentSamples(int eventNum)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventLevTrigT0AdjSamp = new QueryEventAttribute(com);
|
||||
eventLevTrigT0AdjSamp.EventNumber = (ushort)eventNum;
|
||||
eventLevTrigT0AdjSamp.Key = AttributeTypes.ArmAndEventAttributes.LevelTriggerT0AdjustmentSamples;
|
||||
eventLevTrigT0AdjSamp.SyncExecute();
|
||||
var levelTriggerAdjSamples = (int[])(eventLevTrigT0AdjSamp.Value);
|
||||
|
||||
var levelTriggerSeen = GetLevelTriggerSeen(eventNum);
|
||||
|
||||
var finalAdjustment = new int?[levelTriggerAdjSamples.Length];
|
||||
|
||||
for (int channel = 0; channel < finalAdjustment.Length; channel++)
|
||||
{
|
||||
finalAdjustment[channel] = levelTriggerSeen[channel] ? levelTriggerAdjSamples[channel] : (int?)null;
|
||||
}
|
||||
|
||||
return finalAdjustment;
|
||||
}
|
||||
|
||||
catch (System.Exception)
|
||||
{
|
||||
// CGO
|
||||
// This is a hacked change for now to support 00G8 and prior firmware
|
||||
// in the 1.04 release of SLICEWare. This and the other CGO commented
|
||||
// block of code need more general cleanup before 1.05.
|
||||
return (int?[])null;
|
||||
//throw new ApplicationException( "encountered problem getting event level trigger T0 adjustment samples from hardware for event " + eventNum.ToString( ), ex );
|
||||
}
|
||||
}
|
||||
|
||||
public bool EventHasBeenDownloaded(int eventNum, out uint flag)
|
||||
{
|
||||
try
|
||||
{
|
||||
var eventDLFlag = new QueryEventAttribute(com);
|
||||
eventDLFlag.EventNumber = (ushort)eventNum;
|
||||
eventDLFlag.Key = AttributeTypes.ArmAndEventAttributes.EventHasBeenDownloaded;
|
||||
eventDLFlag.SyncExecute();
|
||||
flag = (uint)eventDLFlag.Value;
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
flag = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEventDownloaded(int eventNum, uint flag)
|
||||
{
|
||||
var eventDLFlag = new SetEventAttribute(com);
|
||||
eventDLFlag.EventNumber = (ushort)eventNum;
|
||||
eventDLFlag.SetValue(AttributeTypes.ArmAndEventAttributes.EventHasBeenDownloaded, flag, true);
|
||||
eventDLFlag.SyncExecute();
|
||||
}
|
||||
|
||||
public string GetEventID(int eventNum)
|
||||
{
|
||||
var eventName = new QueryEventAttribute(com);
|
||||
eventName.EventNumber = (ushort)eventNum;
|
||||
eventName.Key = AttributeTypes.ArmAndEventAttributes.Name;
|
||||
eventName.SyncExecute();
|
||||
var values = eventName.Value as byte[];
|
||||
if (null == values)
|
||||
{
|
||||
return eventName.Value as string;
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = Encoding.UTF8.GetString(values);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public Guid GetEventGuid(int eventNum)
|
||||
{
|
||||
var eventGuid = new QueryEventAttribute(com);
|
||||
eventGuid.EventNumber = (ushort)eventNum;
|
||||
eventGuid.Key = AttributeTypes.ArmAndEventAttributes.EventGuid;
|
||||
eventGuid.SyncExecute();
|
||||
return new Guid(eventGuid.Value as string);
|
||||
}
|
||||
|
||||
public string GetEventDescription(int eventNum)
|
||||
{
|
||||
var eventDescr = new QueryEventAttribute(com);
|
||||
eventDescr.EventNumber = (ushort)eventNum;
|
||||
eventDescr.Key = AttributeTypes.ArmAndEventAttributes.Description;
|
||||
eventDescr.SyncExecute();
|
||||
var values = eventDescr.Value as byte[];
|
||||
if (values == null || values.Length == 0)
|
||||
return eventDescr.Value as string;
|
||||
var value = Encoding.UTF8.GetString(values);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
2202
DataPRO/IService/Classes/TDAS Service/Configuration.cs
Normal file
2202
DataPRO/IService/Classes/TDAS Service/Configuration.cs
Normal file
File diff suppressed because it is too large
Load Diff
988
DataPRO/IService/Classes/TDAS Service/Download.cs
Normal file
988
DataPRO/IService/Classes/TDAS Service/Download.cs
Normal file
@@ -0,0 +1,988 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.DASLib.Service;
|
||||
using DTS.Slice.Service;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.DASResource;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory.Download;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
#region Downloading
|
||||
|
||||
public class TDASSetEventInfoAsync : TDASServiceAsyncInfo
|
||||
{
|
||||
public int EventIndex { get; set; }
|
||||
public UInt32 EventHasDownloaded { get; set; }
|
||||
public TDASSetEventInfoAsync(ServiceCallback callback,
|
||||
object userData,
|
||||
int eventIndex,
|
||||
UInt32 eventHasDownloaded)
|
||||
: base(callback, userData)
|
||||
{
|
||||
EventIndex = eventIndex;
|
||||
EventHasDownloaded = eventHasDownloaded;
|
||||
}
|
||||
}
|
||||
public void CorrectT0s(ServiceCallback callback, object userData)
|
||||
{
|
||||
var asyncInfo = new TDASServiceAsyncInfo(callback, userData);
|
||||
asyncInfo.Error("Not supported");
|
||||
return;
|
||||
}
|
||||
void IDownloadActions.SetEventInfo(int eventindex,
|
||||
string id,
|
||||
Guid guid,
|
||||
ulong totalSamples,
|
||||
ulong[] triggerSamples,
|
||||
ulong startRecordSample,
|
||||
UInt32 eventHasDownloaded,
|
||||
ServiceCallback callback,
|
||||
object userData)
|
||||
{
|
||||
var info = new TDASSetEventInfoAsync(callback, userData, eventindex, eventHasDownloaded);
|
||||
LaunchAsyncWorker("TDAS.SetEventInfo", new WaitCallback(AsyncSetEventInfo), info);
|
||||
}
|
||||
|
||||
private void AsyncSetEventInfo(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as TDASSetEventInfoAsync;
|
||||
try
|
||||
{
|
||||
if (UInt32.MaxValue != info.EventHasDownloaded)
|
||||
{
|
||||
foreach (DASModule module in ConfigData.Modules)
|
||||
{
|
||||
if (DASInfo.Modules[module.ModuleArrayIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Command.TDAS.ClearDataAvailable cda = new DTS.DASLib.Command.TDAS.ClearDataAvailable(this);
|
||||
cda.ModuleIndex = module.ModuleArrayIndex;
|
||||
cda.SyncExecute();
|
||||
if (cda.IsErrored) { throw new Exception(string.Format("{0}:{1}", SerialNumber, cda.ResponseData)); }
|
||||
// Only need to do once for G5
|
||||
if (IsG5()) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error("Failed to set event downloaded status", ex);
|
||||
return;
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
|
||||
void IDownloadActions.Download(ServiceCallback callback, object userData)
|
||||
{
|
||||
if (!Connected)
|
||||
{
|
||||
// "Slice.Download: Not currently connected"
|
||||
throw new Exception(string.Format(Strings.TDAS_Download_NotConnected, ((InfoResult)DASInfo).OwningDAS.SerialNumber));
|
||||
}
|
||||
var state = new TDASDownloadState(callback, userData, WhatToDownload);
|
||||
LaunchAsyncWorker("TDAS.Download", new WaitCallback(TDASDownload), state);
|
||||
}
|
||||
private class TDASDownloadState : TDASServiceAsyncInfo
|
||||
{
|
||||
public IDownloadRequest Request;
|
||||
public ulong SamplesDownloaded; // how many samples have we downloaded so far
|
||||
|
||||
public Command.TDAS.Download DownloadCommand;
|
||||
|
||||
public TDASDownloadState(ServiceCallback cb, object cbObj, IDownloadRequest _Request)
|
||||
: base(cb, cbObj)
|
||||
{
|
||||
Request = _Request;
|
||||
SamplesDownloaded = 0;
|
||||
DownloadCommand = null;
|
||||
}
|
||||
}
|
||||
private static string ToByteFormat(int valIn, int digits)
|
||||
{
|
||||
var bitsString = new StringBuilder(digits);
|
||||
int mask = (1 << digits - 1);
|
||||
for (int i = 0; i < digits; i++)
|
||||
{
|
||||
bitsString.Append((valIn & mask) != 0 ? "1" : "0");
|
||||
mask >>= 1;
|
||||
}
|
||||
return bitsString.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// reflects the number of channels on a TOM module (4 SQUIB x 2 channels (squib + current) + 8 digital)
|
||||
/// </summary>
|
||||
private const int TOM_CHANNEL_COUNT = 16;
|
||||
private void TDASDownload(object asyncInfo)
|
||||
{
|
||||
var state = asyncInfo as TDASDownloadState;
|
||||
|
||||
try
|
||||
{
|
||||
int NumberOfChannels = 0;
|
||||
ulong moduleZerosT0 = 0;
|
||||
foreach (var module in EventInfo.Events[WhatToDownload.EventNumber].Modules)
|
||||
{
|
||||
//Since "What to Download" was calculated using the last module with configured channel's trigger point,
|
||||
//set moduleZerosT0 here on the same basis so that the delta calculation below is correct.
|
||||
if ((module.TriggerSampleNumbers != null) && (module.NumberOfConfiguredChannels() > 0))
|
||||
{
|
||||
moduleZerosT0 = module.TriggerSampleNumbers[0];
|
||||
}
|
||||
//if ((module.Channels.Length > 0) && module.Channels[0].ConfigurationMode != DASChannel.ConfigMode.DummyArm)
|
||||
//20088 TDAS Download with unused TOM fails.
|
||||
//TOM modules are included in NewData even if they are dummy armed
|
||||
//so include them in the count
|
||||
if (module.IsDummyArmed() && (!IsG5()) && !IsTom(module)) { continue; }
|
||||
else
|
||||
{
|
||||
NumberOfChannels += module.NumberOfChannels();
|
||||
}
|
||||
}
|
||||
|
||||
ulong totalNumberOfSamples = 1 + WhatToDownload.EndSample - WhatToDownload.StartSample;
|
||||
//const uint downloadChunkSize = 16384;
|
||||
|
||||
ulong downloadChunkSize = 1 + WhatToDownload.EndSample - WhatToDownload.StartSample;
|
||||
|
||||
ulong samplesDownloaded = 0;
|
||||
|
||||
int channelsToDownload = 0;
|
||||
foreach (var iDASModule in EventInfo.Events[WhatToDownload.EventNumber].Modules)
|
||||
{
|
||||
var m = (DASModule)iDASModule;
|
||||
if ((m.Channels.Length > 0) && (!(IsTom(m) && (m.Channels[0].ConfigurationMode == DFConstantsAndEnums.ConfigMode.DummyArm))))
|
||||
{
|
||||
//If DummyArm and a G5, then count the channels; if a TOM don't
|
||||
foreach (var ch in m.Channels)
|
||||
{
|
||||
if (ch is DTS.DASLib.Service.AnalogInputDASChannel)
|
||||
{
|
||||
var aic = ch as DTS.DASLib.Service.AnalogInputDASChannel;
|
||||
if (aic.ConfigurationMode == DFConstantsAndEnums.ConfigMode.Normal)
|
||||
{
|
||||
channelsToDownload++;
|
||||
}
|
||||
}
|
||||
else if (ch is DTS.DASLib.Service.OutputSquibChannel)
|
||||
{
|
||||
var osc = ch as DTS.DASLib.Service.OutputSquibChannel;
|
||||
if (osc.ConfigurationMode == DFConstantsAndEnums.ConfigMode.Normal)
|
||||
{
|
||||
channelsToDownload++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int channelsDownloaded = 0;
|
||||
for (ulong z = WhatToDownload.StartSample; z <= WhatToDownload.EndSample; z += downloadChunkSize)
|
||||
{
|
||||
ulong end = z + downloadChunkSize;
|
||||
bool bDigitalDownload = false;
|
||||
|
||||
if (end > WhatToDownload.EndSample) { end = WhatToDownload.EndSample; }
|
||||
short[][] newData = new short[NumberOfChannels][];
|
||||
for (int i = 0; i < NumberOfChannels; i++)
|
||||
{
|
||||
newData[i] = new short[end + 1 - z];
|
||||
}
|
||||
int channelIdx = -1;
|
||||
for (int i = 0; i < EventInfo.Events[WhatToDownload.EventNumber].Modules.Length && z < WhatToDownload.EndSample; i++)
|
||||
{
|
||||
if (EventInfo.Events[WhatToDownload.EventNumber].Modules[i].IsDummyArmed())
|
||||
{
|
||||
if (IsG5())
|
||||
{
|
||||
//Unlike modules in a rack that don't have channels, G5 modules that don't have channels must all be downloaded (and then purged)
|
||||
channelIdx += EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Count();
|
||||
}
|
||||
|
||||
//20088A TDAS Download with unused TOM fails.
|
||||
//TOM channels are included in the NewData structure
|
||||
//even when dummyarmed, so we must account for it if we see it
|
||||
if (IsTom(EventInfo.Events[WhatToDownload.EventNumber].Modules[i]))
|
||||
{
|
||||
channelIdx += TOM_CHANNEL_COUNT;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
DASModule mod = (DASModule)EventInfo.Events[WhatToDownload.EventNumber].Modules[i];
|
||||
//tdas wants start, end, but wants it specified in terms of - = pretrigger,
|
||||
//+ = post trigger, so we have to convert.
|
||||
|
||||
long start = 0;
|
||||
long stop = 0;
|
||||
|
||||
//we make the adjustment here because the "What to Download" was calculated using
|
||||
//the last module with configured channel's trigger point, but trigger points in tdas are module specific
|
||||
//so we just adjust by the difference in triggers.
|
||||
double delta = mod.TriggerSampleNumbers[0] - (double)moduleZerosT0;
|
||||
|
||||
//hack to move everything to the the left in the window (by moving the data download to the right
|
||||
//this seems inaccurate but is consistent with the TDC viewer.
|
||||
//http://fogbugz/fogbugz/default.asp?7084#45268
|
||||
//DTM - 2016-09-28 we are now _UNDOING_ thing change, per TJK
|
||||
double startSample = (double)(z + delta);
|
||||
double endSample = (double)(end + delta) + 1;
|
||||
|
||||
startSample -= mod.PreTriggerSeconds * mod.SampleRateHz;
|
||||
endSample -= 1 + mod.PreTriggerSeconds * mod.SampleRateHz;
|
||||
|
||||
start = Convert.ToInt64(startSample);
|
||||
stop = Convert.ToInt64(endSample);
|
||||
|
||||
//also per CPB and TJK we are one sample too far, so don't do the below adjustment...
|
||||
//start -= 1;
|
||||
//stop -= 1;
|
||||
|
||||
//NOW per TJK, ADD a sample, for
|
||||
//http://fogbugz/fogbugz/default.asp?8747
|
||||
start += 1;
|
||||
stop += 1;
|
||||
|
||||
short[] dimData = new short[0];
|
||||
bool bIsDIM = !IsG5() &&
|
||||
EventInfo.Events[WhatToDownload.EventNumber].Modules[i].SerialNumber()
|
||||
.StartsWith("DIM");
|
||||
|
||||
if (bIsDIM)
|
||||
{
|
||||
Command.TDAS.Download download = new Command.TDAS.Download(this);
|
||||
download.ChannelIndex = 0;
|
||||
download.ModuleIndex = mod.ModuleArrayIndex;
|
||||
download.FirstPoint = start;
|
||||
download.LastPoint = stop;
|
||||
|
||||
download.SyncExecute();
|
||||
dimData = download.GetData();
|
||||
}
|
||||
|
||||
for (int k = 0; k < EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Length; k++)
|
||||
{
|
||||
channelIdx++;
|
||||
if (EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels[k].ConfigurationMode != DFConstantsAndEnums.ConfigMode.Normal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//DIMS send there data with all 16 channels per each short
|
||||
//so to get one channel we've already gotten all channels, so to increase efficiency, we process all channels at the same time here as well
|
||||
if (bIsDIM)
|
||||
{
|
||||
if (dimData.Length > 0)
|
||||
{
|
||||
//note that k doesn't necessarily start at 0, so we just start wherever k started at
|
||||
//first we initialize the data structures since we know how much data we will have
|
||||
for (int curChannel = k;
|
||||
curChannel <
|
||||
EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Length;
|
||||
curChannel++)
|
||||
{
|
||||
//we also have to keep in mind, we might have started at 1, and we are adding in the "current" channel index
|
||||
//this is OK with digital channels, because at worse we'll write blank data into the next modules channels, which aren't downloaded yet
|
||||
//[ideally we'd keep track of which channel we are in the module as well, rather than just overall in the DAS]
|
||||
//but we need to make sure we don't index out of range ...
|
||||
if ((curChannel + channelIdx) < newData.Length)
|
||||
{
|
||||
newData[curChannel + channelIdx] = new short[dimData.Length];
|
||||
}
|
||||
}
|
||||
//for each data point, break out all the remaining channels and store the bits
|
||||
//we store them as ADC, which is wasteful, but consistent with Slice pro dim
|
||||
for (int iDataIndex = 0; iDataIndex < dimData.Length; iDataIndex++)
|
||||
{
|
||||
System.Collections.Specialized.BitVector32 bv =
|
||||
new System.Collections.Specialized.BitVector32(
|
||||
Convert.ToInt32(dimData[iDataIndex]));
|
||||
|
||||
for (int curChannel = k;
|
||||
curChannel <
|
||||
EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Length;
|
||||
curChannel++)
|
||||
{
|
||||
//bit vectors expect a bit mask, our bit mask is just the one channel we are interested in
|
||||
if (bv[(1 << curChannel)])
|
||||
{
|
||||
//cur channel starts at k, so we are inserting at just channelIdx, which is what we want
|
||||
//as we increase curChannel we are at channelIdx+1, +2, etc.
|
||||
newData[(curChannel - k) + channelIdx][iDataIndex] = short.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
newData[(curChannel - k) + channelIdx][iDataIndex] = short.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
//update progress
|
||||
int numberOfDigitalIns = EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Length - k;
|
||||
channelsDownloaded += numberOfDigitalIns;
|
||||
state.Progress((int)(100D * channelsDownloaded / channelsToDownload));
|
||||
channelIdx += numberOfDigitalIns - 1;//we are ++ at the begining, so we have to subtract one here as numberOfDigitalIns is inclusive
|
||||
}
|
||||
//we've finished all channels in this module, since it's a DIM ...
|
||||
k = EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels.Length;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels[k] is DTS.DASLib.Service.AnalogInputDASChannel &&
|
||||
(EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels[k] as DTS.DASLib.Service.AnalogInputDASChannel).TypeOfBridge == SensorConstants.BridgeType.DigitalInput
|
||||
&& IsG5())
|
||||
{//download digital all at once
|
||||
bDigitalDownload = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Command.TDAS.Download download = new DTS.DASLib.Command.TDAS.Download(this);
|
||||
if (IsTom(mod))
|
||||
{
|
||||
OutputSquibChannel osc = EventInfo.Events[WhatToDownload.EventNumber].Modules[i].Channels[k] as OutputSquibChannel;
|
||||
if (null == osc) { continue; }
|
||||
switch (osc.MeasurementType)
|
||||
{
|
||||
case SquibMeasurementType.INIT_SIGNAL:
|
||||
case SquibMeasurementType.VOLTAGE:
|
||||
download.DoVoltageOrInsertionDownload = true;
|
||||
break;
|
||||
case SquibMeasurementType.CURRENT:
|
||||
case SquibMeasurementType.NONE:
|
||||
default:
|
||||
download.DoCurrentDownload = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
download.ModuleIndex = mod.ModuleArrayIndex;
|
||||
download.ChannelIndex = k;
|
||||
if (IsTom(mod))
|
||||
{
|
||||
download.ChannelIndex = Convert.ToInt32(System.Math.Floor(download.ChannelIndex / 2D));
|
||||
}
|
||||
|
||||
download.FirstPoint = start;
|
||||
download.LastPoint = stop;
|
||||
|
||||
try
|
||||
{
|
||||
download.SyncExecute();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Failed to download: ", ex);
|
||||
download = new Command.TDAS.Download(this, download);
|
||||
download.SyncExecute();
|
||||
}
|
||||
|
||||
newData[channelIdx] = download.GetData();
|
||||
channelsDownloaded++;
|
||||
state.Progress((int)(100D * channelsDownloaded / channelsToDownload));
|
||||
}
|
||||
}
|
||||
if (bDigitalDownload && IsG5())
|
||||
{
|
||||
Command.TDAS.Download download = new DTS.DASLib.Command.TDAS.Download(this);
|
||||
download.ModuleIndex = 0;
|
||||
|
||||
var mod = EventInfo.Events[0].Modules[0];
|
||||
long start = 0;
|
||||
long stop = 0;
|
||||
|
||||
//we make the adjustment here because the "What to Download" was calculated using
|
||||
//the last module's trigger point, but trigger points in tdas are module specific
|
||||
//so we just adjust by the difference in triggers.
|
||||
double delta = mod.TriggerSampleNumbers[0] - (double)moduleZerosT0;
|
||||
|
||||
double startSample = (double)(z + delta);
|
||||
double endSample = (double)(end + delta);
|
||||
|
||||
startSample -= mod.PreTriggerSeconds * mod.SampleRateHz;
|
||||
endSample -= 1 + mod.PreTriggerSeconds * mod.SampleRateHz;
|
||||
|
||||
start = Convert.ToInt64(startSample);
|
||||
stop = Convert.ToInt64(endSample);
|
||||
|
||||
// Similar to analog channels, this is a somewhat emperically determined adjustment that is suspect.
|
||||
// In contrast, these adjustments are expected to be 1 more sample because the digital channels do not have a filter,
|
||||
// and therefore do not have the same phase delay.
|
||||
download.FirstPoint = start - 1;
|
||||
download.LastPoint = stop - 1;
|
||||
download.Digital = true;
|
||||
download.Bank = 1;
|
||||
try
|
||||
{
|
||||
download.SyncExecute();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("failed; ", ex);
|
||||
download = new Command.TDAS.Download(this, download);
|
||||
download.SyncExecute();
|
||||
}
|
||||
short[] data = download.GetData();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (newData[32 + i].Length < data.Length) { newData[32 + i] = new short[data.Length]; }
|
||||
}
|
||||
|
||||
//each short is actually 16 channels of binary data, so we have to parse it out and convert it to ADC for the purpose of the .chn files
|
||||
for (int iDataIndex = 0; iDataIndex < data.Length; iDataIndex++)
|
||||
{
|
||||
System.Collections.Specialized.BitVector32 bv = new System.Collections.Specialized.BitVector32(Convert.ToInt32(data[iDataIndex]));
|
||||
|
||||
//there's another trick in here that we've preserved from TDC, we invert the incoming bit. We do this so that the data appears like
|
||||
//contact closure normally open
|
||||
for (int iChannelIdx = 0; iChannelIdx < 16; iChannelIdx++)
|
||||
{
|
||||
//also note that the bitvector [] operator expects a bitmask, not an index ...
|
||||
if (bv[(1 << iChannelIdx)]) { newData[32 + iChannelIdx][iDataIndex] = short.MinValue; }
|
||||
else { newData[32 + iChannelIdx][iDataIndex] = short.MaxValue; }
|
||||
}
|
||||
}
|
||||
}
|
||||
state.SamplesDownloaded = end - z;
|
||||
|
||||
state.NewData(newData, state.SamplesDownloaded + 1, ulong.MinValue, ulong.MinValue);
|
||||
samplesDownloaded += downloadChunkSize;
|
||||
double ratio = Convert.ToDouble(samplesDownloaded) / Convert.ToDouble(totalNumberOfSamples);
|
||||
if (ratio > 1) { ratio = 1; }
|
||||
//double ratio = Math.Min(1.0, (double)end / (double)(state.Request.EndSample - state.Request.StartSample + 1));
|
||||
state.Progress((int)(ratio * 100.0));
|
||||
}
|
||||
|
||||
//foreach (DASModule module in ConfigData.Modules)
|
||||
foreach (DASModule module in EventInfo.Events[WhatToDownload.EventNumber].Modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DASInfo.Modules[module.ModuleArrayIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK
|
||||
|| module.IsDummyArmed())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Command.TDAS.ClearDataAvailable cda = new DTS.DASLib.Command.TDAS.ClearDataAvailable(this);
|
||||
cda.ModuleIndex = module.ModuleArrayIndex;
|
||||
cda.SyncExecute();
|
||||
|
||||
if (IsG5()) { continue; } // only need to do it once
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Failed to set event downloaded status", ex);
|
||||
}
|
||||
}
|
||||
//state.NewData(data.ToArray(), WhatToDownload.EndSample-WhatToDownload.StartSample);
|
||||
state.Progress(100);
|
||||
// send data to user
|
||||
state.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
state.Cancel();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
state.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Query download
|
||||
void IDownloadActions.QueryDownload(ServiceCallback callback, object userData, int eventIndex, TDASServiceSetupInfo setupInfo)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
TDASDownloadServiceAsyncInfo dlSetupInfo = new TDASDownloadServiceAsyncInfo(info, setupInfo);
|
||||
|
||||
if (eventIndex > 0) { info.Error("only single event support for TDAS"); }
|
||||
else { LaunchAsyncWorker("TDAS.QueryDownload", new WaitCallback(AsyncQueryDownloadedStatus), dlSetupInfo); }
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Query downloaded status
|
||||
|
||||
void IDownloadActions.QueryDownloadedStatus(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
var dlSetupInfo = new TDASDownloadServiceAsyncInfo(info, null);
|
||||
|
||||
LaunchAsyncWorker("TDAS.QueryDownloadedStatus", new WaitCallback(AsyncQueryDownloadedStatus), dlSetupInfo);
|
||||
|
||||
}
|
||||
|
||||
private void AsyncQueryDownloadedStatus(object asyncInfo)
|
||||
{
|
||||
var downloadInfo = asyncInfo as TDASDownloadServiceAsyncInfo;
|
||||
|
||||
var info = downloadInfo.info;
|
||||
var setupInfo = downloadInfo.setupInfo;
|
||||
|
||||
try
|
||||
{
|
||||
var eventDownloadStatus = new List<bool>();
|
||||
var eventIDs = new List<string>();
|
||||
var eventDescriptions = new List<string>();
|
||||
//List<string> eventDescriptions = new List<string>();
|
||||
var eventGUIDs = new List<Guid>();
|
||||
var faultFlags = new List<ushort>();
|
||||
var dasModulesPerEvent = new List<List<DASModule>>();
|
||||
DateTime eventStartTime = DateTime.Now;
|
||||
int levelTriggerAdjustment = 0;
|
||||
|
||||
//turn off lights & clear serial on racks
|
||||
//var qse = new Command.TDAS.QuerySerialNumberBroadcast(this, -1);
|
||||
//qse.SyncExecute();
|
||||
|
||||
for (int i = 0; i < DASInfo.Modules.Length; i++)
|
||||
{
|
||||
string testConfig = "";
|
||||
string testDescription = "";
|
||||
double actualSampleRate = 1D;
|
||||
float hardwareFilterRate = 1F;
|
||||
Command.TDAS.SetupDASLoad.ARMMode recordingMode = Command.TDAS.SetupDASLoad.ARMMode.WAIT;
|
||||
|
||||
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||||
{
|
||||
TDASModuleConfig tConfig = new TDASModuleConfig(DASInfo.Modules[i].SerialNumber + ".xml");
|
||||
|
||||
DASModule module = new DASModule(DASInfo.Modules[i].ModuleArrayIndex, this);
|
||||
|
||||
module.StartRecordSampleNumber = 0;
|
||||
|
||||
module.PreTriggerSeconds = 0;
|
||||
module.PostTriggerSeconds = 0;
|
||||
|
||||
module.NumberOfSamples = ulong.MaxValue;
|
||||
|
||||
module.TriggerSampleNumbers = new UInt64[1];
|
||||
module.TriggerSampleNumbers[0] = 0;
|
||||
|
||||
module.Channels = new DASChannel[DASInfo.Modules[i].NumberOfChannels];
|
||||
module.AAFilterRateHz = hardwareFilterRate;
|
||||
module.SampleRateHz = Convert.ToUInt32(System.Math.Abs(actualSampleRate));
|
||||
if (ConfigData != null)
|
||||
{
|
||||
module.Channels = (DASChannel[])ConfigData.Modules[i].Channels.Clone();
|
||||
}
|
||||
|
||||
// update the channel info
|
||||
|
||||
for (uint channelIdx = 0; channelIdx < module.Channels.Length; channelIdx++)
|
||||
{
|
||||
module.Channels[channelIdx].EventStartTime = eventStartTime;
|
||||
}
|
||||
if (dasModulesPerEvent.Count > 0)
|
||||
{
|
||||
//dasModulesPerEvent.Add(new List<DASModule>());
|
||||
dasModulesPerEvent[dasModulesPerEvent.Count - 1].Add(module);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Command.TDAS.QueryDataAvailable qda = new DTS.DASLib.Command.TDAS.QueryDataAvailable(this);
|
||||
qda.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||||
|
||||
qda.SyncExecute();
|
||||
if (null == qda.EventCodes || qda.EventCodes.Length == 0) { APILogger.Log(string.Format("No events found on {0}:{1}", SerialNumber, DASInfo.Modules[i].SerialNumber)); continue; }
|
||||
|
||||
try
|
||||
{
|
||||
//if (IsTom(ConfigData.Modules[i]))
|
||||
if (IsTom(DASInfo.Modules[i].TypeOfModule))
|
||||
{
|
||||
if ((setupInfo == null) || ((setupInfo.CheckoutMode != null) && (setupInfo.SamplesPerSecond == null)))
|
||||
{
|
||||
//We were not called from the Download tile
|
||||
Command.TDAS.SetupTOMDASRead sdr = new DTS.DASLib.Command.TDAS.SetupTOMDASRead(this);
|
||||
sdr.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||||
sdr.SyncExecute();
|
||||
string sTemp = sdr.TestConfig;
|
||||
string[] tokens = sTemp.Split(SETUPDASREAD_SENTINEL);
|
||||
if (tokens.Length >= 2) { testConfig = tokens[0]; testDescription = tokens[1]; }
|
||||
else { testConfig = tokens[0]; }
|
||||
|
||||
//testConfig = sdr.TestConfig;
|
||||
actualSampleRate = sdr.ActualSampleRate;
|
||||
if ((setupInfo != null) && ((bool)setupInfo.CheckoutMode))
|
||||
{
|
||||
actualSampleRate = Math.Abs(actualSampleRate);
|
||||
}
|
||||
hardwareFilterRate = sdr.HardwareFilter;
|
||||
recordingMode = sdr.ArmMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We were called from the Download tile, which means that SDL was not done, so SDR above would have failed
|
||||
GetUserSelectedSetupInfo(setupInfo, ref testConfig, ref testDescription, ref actualSampleRate, ref hardwareFilterRate, ref recordingMode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DASInfo.Modules[i].TypeOfModule == DFConstantsAndEnums.ModuleType.ProDIM && !IsG5())
|
||||
{
|
||||
if ((setupInfo == null) || ((setupInfo.CheckoutMode != null) && (setupInfo.SamplesPerSecond == null)))
|
||||
{
|
||||
//We were not called from the Download tile
|
||||
Command.TDAS.SetupDASReadDIM sdr = new DTS.DASLib.Command.TDAS.SetupDASReadDIM(this);
|
||||
|
||||
sdr.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||||
sdr.SyncExecute();
|
||||
string sTemp = sdr.TestConfig;
|
||||
string[] tokens = sTemp.Split(SETUPDASREAD_SENTINEL);
|
||||
if (2 <= tokens.Length)
|
||||
{
|
||||
testConfig = tokens[0];
|
||||
testDescription = tokens[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
testConfig = tokens[0];
|
||||
testDescription = tokens[0];
|
||||
}
|
||||
|
||||
recordingMode = sdr.ArmMode;
|
||||
actualSampleRate = sdr.ActualSampleRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We were called from the Download tile, which means that SDL was not done, so SDR above would have failed
|
||||
GetUserSelectedSetupInfo(setupInfo, ref testConfig, ref testDescription, ref actualSampleRate, ref hardwareFilterRate, ref recordingMode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((setupInfo == null) || ((setupInfo.CheckoutMode != null) && (setupInfo.SamplesPerSecond == null)))
|
||||
{
|
||||
//We were not called from the Download tile
|
||||
Command.TDAS.SetupDASRead sdr = new DTS.DASLib.Command.TDAS.SetupDASRead(this);
|
||||
|
||||
sdr.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||||
sdr.SyncExecute();
|
||||
string sTemp = sdr.TestConfig;
|
||||
string[] tokens = sTemp.Split(SETUPDASREAD_SENTINEL);
|
||||
if (2 <= tokens.Length)
|
||||
{
|
||||
testConfig = tokens[0];
|
||||
testDescription = tokens[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
testConfig = tokens[0];
|
||||
testDescription = tokens[0];
|
||||
}
|
||||
|
||||
actualSampleRate = sdr.ActualSampleRate;
|
||||
hardwareFilterRate = sdr.HardwareFilter;
|
||||
recordingMode = sdr.ArmMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
//We were called from the Download tile, which means that SDL was not done, so SDR above would have failed
|
||||
GetUserSelectedSetupInfo(setupInfo, ref testConfig, ref testDescription, ref actualSampleRate, ref hardwareFilterRate, ref recordingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Error get SDR", ex);
|
||||
}
|
||||
//Command.TDAS.QueryDataAvailable qda = new DTS.DASLib.Command.TDAS.QueryDataAvailable(this);
|
||||
//qda.ModuleIndex = DASInfo.Modules[i].ModuleArrayIndex;
|
||||
|
||||
//qda.SyncExecute();
|
||||
TDASModuleConfig tConfig = new TDASModuleConfig(DASInfo.Modules[i].SerialNumber + ".xml");
|
||||
//if (null != qda.eventCodes && qda.eventCodes.Length > 0)
|
||||
{
|
||||
foreach (string eventCode in qda.EventCodes)
|
||||
{
|
||||
if (!eventIDs.Contains(eventCode))
|
||||
{
|
||||
if (testConfig.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
eventGUIDs.Add(new Guid("11111111111111111111111111111111"));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("invalid test guid - ", testConfig, ex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else { continue; }
|
||||
eventIDs.Add(eventCode);
|
||||
eventDescriptions.Add(testDescription);
|
||||
|
||||
//eventGUIDs.Add(Guid.Empty);
|
||||
faultFlags.Add(0);
|
||||
eventDownloadStatus.Add(qda.IsDownloaded);
|
||||
dasModulesPerEvent.Add(new List<DASModule>());
|
||||
}
|
||||
DASModule module = new DASModule(DASInfo.Modules[i].ModuleArrayIndex, this);
|
||||
|
||||
switch (recordingMode)
|
||||
{
|
||||
case Command.TDAS.SetupDASLoad.ARMMode.WAIT:
|
||||
module.RecordingMode = DFConstantsAndEnums.RecordingMode.CircularBuffer;
|
||||
break;
|
||||
case Command.TDAS.SetupDASLoad.ARMMode.TAPE:
|
||||
module.RecordingMode = DFConstantsAndEnums.RecordingMode.RecorderMode;
|
||||
break;
|
||||
}
|
||||
module.StartRecordSampleNumber = 0;
|
||||
module.PreTriggerSeconds = System.Math.Truncate(100D * qda.PreTriggerSamples / actualSampleRate) / 100D;
|
||||
module.PostTriggerSeconds = System.Math.Truncate(100D * qda.PostTriggerSamples / actualSampleRate) / 100D;
|
||||
|
||||
module.NumberOfSamples = Convert.ToUInt64(qda.PreTriggerSamples + qda.PostTriggerSamples);
|
||||
module.TriggerSampleNumbers = new UInt64[1];
|
||||
module.TriggerSampleNumbers[0] = Convert.ToUInt64(qda.PreTriggerSamples + 1);
|
||||
|
||||
ulong phaseshift = GetPhaseShiftSamples(Convert.ToUInt32(module.ModuleArrayIndex), actualSampleRate, Convert.ToUInt32(hardwareFilterRate), module.TriggerSampleNumbers[0]);
|
||||
|
||||
module.TriggerSampleNumbers[0] += phaseshift;
|
||||
|
||||
module.Channels = new DASChannel[DASInfo.Modules[i].NumberOfChannels];
|
||||
module.AAFilterRateHz = hardwareFilterRate;
|
||||
module.SampleRateHz = Convert.ToUInt32(System.Math.Abs(actualSampleRate));
|
||||
if (null != ConfigData)
|
||||
{
|
||||
module.Channels = (DASChannel[])ConfigData.Modules[i].Channels.Clone();
|
||||
|
||||
// update the channel info
|
||||
|
||||
for (uint channelIdx = 0; channelIdx < module.Channels.Length; channelIdx++)
|
||||
{
|
||||
module.Channels[channelIdx].EventStartTime = eventStartTime;
|
||||
}
|
||||
dasModulesPerEvent[eventIDs.IndexOf(eventCode)].Add(module);
|
||||
}
|
||||
|
||||
if (qda.LevelTriggerOffset > levelTriggerAdjustment)
|
||||
{
|
||||
levelTriggerAdjustment = qda.LevelTriggerOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < dasModulesPerEvent.Count() && 0 < dasModulesPerEvent[0].Count())
|
||||
{
|
||||
foreach (DASModule tempModule in dasModulesPerEvent[0])
|
||||
{
|
||||
foreach (var channel in tempModule.Channels)
|
||||
{
|
||||
channel.LevelTriggerT0AdjustmentSamples = levelTriggerAdjustment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetEventGuids(eventGUIDs.ToArray());
|
||||
SetEventFaultFlags(faultFlags.ToArray());
|
||||
DownloadReport dlReport = new DownloadReport();
|
||||
dlReport.Events = new DownloadReport.EventInfo[EventGuids.Length];
|
||||
for (int eventIndex = 0; eventIndex < EventGuids.Length; eventIndex++)
|
||||
{
|
||||
dlReport.Events[eventIndex] = new DownloadReport.EventInfo();
|
||||
dlReport.Events[eventIndex].Description = eventDescriptions[eventIndex];
|
||||
dlReport.Events[eventIndex].EventNumber = eventIndex;
|
||||
dlReport.Events[eventIndex].TestID = eventIDs[eventIndex];
|
||||
dlReport.Events[eventIndex].HasBeenDownloaded = false;
|
||||
dlReport.Events[eventIndex].WasTriggered = false;
|
||||
dlReport.Events[eventIndex].TestGUID = EventGuids[eventIndex];
|
||||
dlReport.Events[eventIndex].ClearFaults();
|
||||
dlReport.Events[eventIndex].Modules = dasModulesPerEvent[eventIndex].ToArray();
|
||||
}
|
||||
|
||||
for (int eventIndex = 0; eventIndex < EventGuids.Length; eventIndex++)
|
||||
{
|
||||
double minPre = double.MaxValue;
|
||||
double minPost = double.MaxValue;
|
||||
bool dummyArmed = true;
|
||||
foreach (var module in dasModulesPerEvent[eventIndex])
|
||||
{
|
||||
if (DASInfo.Modules[module.ModuleArrayIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) { continue; }
|
||||
if ((module.PreTriggerSeconds >= 0) && (module.PostTriggerSeconds >= 0))
|
||||
{
|
||||
// Negative trigger seconds are from dummy-armed modules
|
||||
minPre = System.Math.Min(module.PreTriggerSeconds, minPre);
|
||||
minPost = System.Math.Min(module.PostTriggerSeconds, minPost);
|
||||
dummyArmed = false;
|
||||
}
|
||||
}
|
||||
if (0 == dlReport.Events[eventIndex].Modules.Length) { }
|
||||
else
|
||||
{
|
||||
if (!dummyArmed)
|
||||
{
|
||||
ulong numberOfSamples = Convert.ToUInt64((minPre + minPost) * dlReport.Events[eventIndex].Modules[0].SampleRateHz);
|
||||
for (int i = 0; i < dlReport.Events[eventIndex].Modules.Length; i++)
|
||||
{
|
||||
DASModule module = (DASModule)dlReport.Events[eventIndex].Modules[i];
|
||||
module.PreTriggerSeconds = minPre;
|
||||
module.PostTriggerSeconds = minPost;
|
||||
module.TriggerSampleNumbers = new ulong[]
|
||||
{
|
||||
Convert.ToUInt64(minPre*System.Math.Abs(module.SampleRateHz))
|
||||
};
|
||||
// If not triggered, racks return 0 and G5s return number of samples
|
||||
if ((module.TriggerSampleNumbers[0] > 0) && (module.TriggerSampleNumbers[0] < numberOfSamples))
|
||||
{
|
||||
dlReport.Events[eventIndex].WasTriggered = true;
|
||||
}
|
||||
//the above statement the pretrigger seconds appears to be off by one sample, so I adjust it here as
|
||||
//there might already be a lot of different side effects to changing the pre trigger time.
|
||||
if (module.TriggerSampleNumbers[0] > 0) { module.TriggerSampleNumbers[0] = module.TriggerSampleNumbers[0] - 1; }
|
||||
|
||||
module.NumberOfSamples = numberOfSamples;
|
||||
//module.NumberOfSamples = Convert.ToUInt64(qda.PreTriggerSamples + qda.PostTriggerSamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//normalize the data here just for sanity sake.
|
||||
//IE, set start to min(abs(preTrigger))
|
||||
//set end to min(abs(posttrigger))
|
||||
//set t0 to min(abs(preTrigger))
|
||||
|
||||
SetEventInfo(dlReport);
|
||||
SetEventDownloadStatus(eventDownloadStatus.ToArray());
|
||||
if (null != EventInfo && EventInfo.Events.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < EventInfo.Events.Length && i < EventDownloadedStatus.Length; i++)
|
||||
{
|
||||
if (EventInfo.Events[i].TestID == "TESTTRIG") { EventDownloadedStatus[i] = true; }
|
||||
}
|
||||
}
|
||||
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetUserSelectedSetupInfo(TDASServiceSetupInfo setupInfo, ref string testConfig, ref string testDescription, ref double actualSampleRate,
|
||||
ref float hardwareFilterRate, ref Command.TDAS.SetupDASLoad.ARMMode recordingMode)
|
||||
{
|
||||
if (setupInfo == null)
|
||||
{
|
||||
testConfig = "";
|
||||
testDescription = "";
|
||||
actualSampleRate = 1D;
|
||||
hardwareFilterRate = 1F;
|
||||
recordingMode = Command.TDAS.SetupDASLoad.ARMMode.WAIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this was from the Download tile, use the SETUP that the user selected
|
||||
testConfig = "UsingUser-specifiedTestSetup";
|
||||
testDescription = setupInfo.SetupDescription;
|
||||
actualSampleRate = (double)setupInfo.SamplesPerSecond;
|
||||
hardwareFilterRate = setupInfo.HardwareFilterRateHz;
|
||||
switch (setupInfo.RecordingMode)
|
||||
{
|
||||
case DFConstantsAndEnums.RecordingMode.CircularBuffer:
|
||||
case DFConstantsAndEnums.RecordingMode.CircularBufferPlusUART:
|
||||
recordingMode = Command.TDAS.SetupDASLoad.ARMMode.WAIT;
|
||||
break;
|
||||
case DFConstantsAndEnums.RecordingMode.RecorderMode:
|
||||
case DFConstantsAndEnums.RecordingMode.RecorderModePlusUART:
|
||||
case DFConstantsAndEnums.RecordingMode.a14_NormalRecorderAndStreamSubSampleMode:
|
||||
recordingMode = Command.TDAS.SetupDASLoad.ARMMode.TAPE;
|
||||
break;
|
||||
default:
|
||||
recordingMode = Command.TDAS.SetupDASLoad.ARMMode.WAIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Set trigger sample numbers
|
||||
|
||||
void IDownloadActions.SetTriggerSampleNumbers(ServiceCallback callback, object userData)
|
||||
{
|
||||
throw new NotSupportedException("SetTriggerSampleNumbers not supported for TDAS");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Set downloaded
|
||||
void IDownloadActions.SetDownloaded(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TDASSetEventInfoAsync(callback, userData, 0, 1);
|
||||
//FB12656: Launch synchronously. This call needs the full round-trip (4s) before proceeding with other commands
|
||||
CallSyncMethod("TDAS.SetDownloaded", SendClearDataAvailable, info);
|
||||
}
|
||||
|
||||
private void SendClearDataAvailable(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as TDASSetEventInfoAsync;
|
||||
try
|
||||
{
|
||||
if (UInt32.MaxValue != info.EventHasDownloaded)
|
||||
{
|
||||
foreach (DASModule module in ConfigData.Modules)
|
||||
{
|
||||
if (DASInfo.Modules[module.ModuleArrayIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK
|
||||
|| module.IsDummyArmed())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Command.TDAS.ClearDataAvailable cda = new DTS.DASLib.Command.TDAS.ClearDataAvailable(this);
|
||||
cda.ModuleIndex = module.ModuleArrayIndex;
|
||||
cda.SyncExecute();
|
||||
if (cda.IsErrored) { throw new Exception(string.Format("{0}:{1}", SerialNumber, cda.ResponseData)); }
|
||||
// Only need to do once for G5
|
||||
if (IsG5()) { break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error("Failed to set event downloaded status", ex);
|
||||
return;
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
342
DataPRO/IService/Classes/TDAS Service/Public.cs
Normal file
342
DataPRO/IService/Classes/TDAS Service/Public.cs
Normal file
@@ -0,0 +1,342 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DTS.Common;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.DASLib.Command;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.SerialConnection;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
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.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using static DTS.Common.Enums.DASFactory.DFConstantsAndEnums;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
public ExcitationStatus ExcitationStatus { get; set; } = ExcitationStatus.Unknown;
|
||||
public HardwareTypes GetHardwareType()
|
||||
{
|
||||
if (SerialNumber.StartsWith("5M"))
|
||||
{
|
||||
switch (G5Mode)
|
||||
{
|
||||
case G5Modes.INDUMMY: return HardwareTypes.G5INDUMMY;
|
||||
case G5Modes.VDS:
|
||||
default:
|
||||
return HardwareTypes.G5VDS;
|
||||
}
|
||||
}
|
||||
else if (SerialNumber.StartsWith("DR")) { return HardwareTypes.TDAS_Pro_Rack; }
|
||||
else if (SerialNumber.StartsWith("SM")) { return HardwareTypes.SIM; }
|
||||
else if (SerialNumber.StartsWith("TOM")) { return HardwareTypes.TOM; }
|
||||
else if (SerialNumber.StartsWith("LR"))
|
||||
{
|
||||
return HardwareTypes.TDAS_LabRack;
|
||||
}
|
||||
else
|
||||
{
|
||||
//invalid serial number, just treat as rack?
|
||||
return HardwareTypes.TDAS_Pro_Rack;
|
||||
}
|
||||
}
|
||||
public bool StartRecord
|
||||
{
|
||||
get;
|
||||
protected 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; }
|
||||
public double MinimumValidBatteryVoltage { get; set; }
|
||||
public double MaximumValidBatteryVoltage { get; set; }
|
||||
public bool CheckAAF(float rate) { return true; }
|
||||
/// <summary>
|
||||
/// phase shift information not known for TDAS modules right now, so assuming 0
|
||||
/// </summary>
|
||||
/// <param name="ModuleIndex"></param>
|
||||
/// <param name="ActualSampleRate"></param>
|
||||
/// <param name="HardwareAAF"></param>
|
||||
/// <returns></returns>
|
||||
public ulong GetPhaseShiftSamples(uint ModuleIndex, double ActualSampleRate, uint HardwareAAF, ulong originalT0) { return 0; }
|
||||
#region Configuration
|
||||
|
||||
// our public configure member
|
||||
|
||||
public IConfigurationData ConfigData { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Diagnostics
|
||||
|
||||
// our public diagnostics member
|
||||
|
||||
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 IBaseInputValues BaseInput { get; set; }
|
||||
public IOptimizationValues OptimizationValues { get; set; }
|
||||
#region Clock Sync
|
||||
public IDictionary<InputClockSource, bool> DASClockSyncStatus { get; set; } = null;
|
||||
public bool ClockSyncInUTC { get; set; } = false;
|
||||
|
||||
public ClockSyncProfile DASClockSyncProfile { get; set; }
|
||||
public byte PTPDomainID { get; set; }
|
||||
#endregion
|
||||
public IArmCheckActions ArmCheckActions { get; set; }
|
||||
public IArmCheckResults ArmCheckResults { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Trigger check
|
||||
|
||||
// our public trigger check member
|
||||
|
||||
public ITriggerCheckResult TriggerResult { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Real time
|
||||
|
||||
// our public real time member
|
||||
|
||||
public List<int> RealtimeDASChannels { get; set; }
|
||||
public List<double> TiltAxisData { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region FlashErase
|
||||
|
||||
public FlashEraseStatus DASFlashEraseStatus { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Arming
|
||||
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 IArmStatusData DASArmStatus { get; set; }
|
||||
public void SetDASArmStatus(IArmStatusData status, bool bSetInDb)
|
||||
{
|
||||
ArmStatus.SetArmStatus(this, status, bSetInDb);
|
||||
}
|
||||
public void SetDASArmStatus()
|
||||
{
|
||||
ArmStatus.SetArmStatus(this, DASArmStatus, true);
|
||||
}
|
||||
private DFConstantsAndEnums.CommandStatus _autoArmStatus = DFConstantsAndEnums.CommandStatus.StatusNoError;
|
||||
public DFConstantsAndEnums.CommandStatus AutoArmStatus
|
||||
{
|
||||
get { return _autoArmStatus; }
|
||||
set { _autoArmStatus = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Downloading
|
||||
|
||||
public IDownloadRequest WhatToDownload { get; set; }
|
||||
public void SetWhatToDownload(IDownloadRequest request, bool bSetInDb = true)
|
||||
{
|
||||
DownloadRequest.SetWhatToDownload(this, request, bSetInDb);
|
||||
}
|
||||
public IDownloadReport EventInfo { get; set; }
|
||||
public void SetEventInfo(IDownloadReport eventInfo, bool bSetInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventInfo(this, eventInfo, bSetInDb);
|
||||
}
|
||||
public bool[] EventDownloadedStatus { get; set; }
|
||||
public void SetEventDownloadStatus(bool[] status, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventDownloadStatus(this, status, storeInDb);
|
||||
}
|
||||
public Guid[] EventGuids { get; set; }
|
||||
public void SetEventGuids(Guid[] guids, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventGuids(this, guids, 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);
|
||||
}
|
||||
public ushort[] FaultFlags { get; set; }
|
||||
public void SetEventFaultFlags(ushort[] flags, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventFaultFlags(this, flags, storeInDb);
|
||||
}
|
||||
public byte[] ArmAttempts { get; set; }
|
||||
public void SetEventArmAttemps(byte[] armAttempts, bool storeInDb = true)
|
||||
{
|
||||
DownloadReport.SetEventArmAttempts(this, armAttempts, storeInDb);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Information
|
||||
|
||||
/// <summary>
|
||||
/// note, this property hides a property inherited from ICommunication, but that
|
||||
/// one is declared with a different type (Communication_DASInfo), so I'm assuming this
|
||||
/// was intended to hide that property
|
||||
/// 6/29/2010 - dtm
|
||||
/// </summary>
|
||||
|
||||
public new IInfoResult DASInfo { get; set; }
|
||||
public void SetDASInfo(IInfoResult dasInfo, bool bSetInDb = true)
|
||||
{
|
||||
InfoResult.SetDASInfo(this, dasInfo, bSetInDb);
|
||||
}
|
||||
public void SetDASInfo() { InfoResult.SetDASInfo(this); }
|
||||
#endregion
|
||||
|
||||
#region Firmware Utility
|
||||
|
||||
#endregion
|
||||
|
||||
//I'm guessing hiding was not intended, this member hides an inherited member (from ICommunication)
|
||||
//public string SerialNumber { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
var sn = SerialNumber;
|
||||
if (!string.IsNullOrEmpty(sn))
|
||||
return sn;
|
||||
return "Unknown DAS";
|
||||
}
|
||||
|
||||
public int NumberOfConfiguredChannels()
|
||||
{
|
||||
if (null == ConfigData) { return 0; }
|
||||
return ConfigData.NumberOfConfiguredChannels();
|
||||
}
|
||||
|
||||
|
||||
public int NumberOfChannels()
|
||||
{
|
||||
if (null == ConfigData) { return 0; }
|
||||
return ConfigData.NumberOfChannels();
|
||||
}
|
||||
|
||||
|
||||
public int CompareTo(IDASCommunication das)
|
||||
{
|
||||
if (das == null || string.IsNullOrEmpty(das.SerialNumber) || string.IsNullOrEmpty(SerialNumber))
|
||||
return 0;
|
||||
return SerialNumber.CompareTo(das.SerialNumber);
|
||||
}
|
||||
|
||||
public bool DiagnosticsHasBeenRun { get; set; }
|
||||
private bool _configureHasBeenRun = false;
|
||||
public bool ConfigureHasBeenRun
|
||||
{
|
||||
get { return _configureHasBeenRun; }
|
||||
set { _configureHasBeenRun = value; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region Sub classes used for identification
|
||||
|
||||
public class EthernetTDAS : TDAS<EthernetConnection>
|
||||
{
|
||||
|
||||
public EthernetTDAS()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class SerialTDAS : TDAS<SerialConnection>
|
||||
{
|
||||
public SerialTDAS()
|
||||
{
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
674
DataPRO/IService/Classes/TDAS Service/Realtime.cs
Normal file
674
DataPRO/IService/Classes/TDAS Service/Realtime.cs
Normal file
@@ -0,0 +1,674 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.TDAS;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
#region Real time
|
||||
public bool ControlsDAQ() { return false; }
|
||||
public bool SupportsHardwareInputCheck() { return false; }
|
||||
public bool InvertStart
|
||||
{
|
||||
get { return false; }
|
||||
set { if (value) { throw new NotSupportedException("TDAS does not support inverted start"); } }
|
||||
}
|
||||
public bool InvertTrigger
|
||||
{
|
||||
get { return false; }
|
||||
set { if (value) { throw new NotSupportedException("TDAS does not support inverted trigger"); } }
|
||||
}
|
||||
public bool SupportsTriggerInversion() => HardwareConstants.SupportsTriggerInversion(GetHardwareType(), ProtocolVersion);
|
||||
public bool SupportsStartInversion() => HardwareConstants.SupportsStartInversion(GetHardwareType(), ProtocolVersion);
|
||||
public bool SupportsRealtime()
|
||||
{
|
||||
if (DFConstantsAndEnums.ModuleType.G5Analog == DASInfo.Modules[0].TypeOfModule)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var module in DASInfo.Modules)
|
||||
{
|
||||
switch (module.TypeOfModule)
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.ProDIM:
|
||||
case DFConstantsAndEnums.ModuleType.ProSIM:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool IgnoreShortedStart
|
||||
{
|
||||
get { return false; }
|
||||
set { if (value) { throw new NotSupportedException("TDAS does not support ignore shorted start"); } }
|
||||
}
|
||||
public bool IgnoreShortedTrigger
|
||||
{
|
||||
get { return false; }
|
||||
set { if (value) { throw new NotSupportedException("TDAS does not support ignore shorted trigger"); } }
|
||||
}
|
||||
public bool SupportsAutoArm() { return false; }
|
||||
public bool SupportsLevelTrigger() { return false; }
|
||||
public bool SupportsMultipleEvents() { return false; }
|
||||
public bool SupportsMultipleSampleRealtime() { return false; }
|
||||
public bool SupportsMultiChannelRealtime() { return false; }
|
||||
|
||||
private class RealTimeAsyncPacket
|
||||
{
|
||||
public TDASServiceAsyncInfo info { get; set; }
|
||||
public System.Threading.Timer timer { get; set; }
|
||||
public int samplesPerSecond { get; set; }
|
||||
public int millisecBetweenSamples { get; set; }
|
||||
public bool realtimeMultipleSamplesEnabled { get; set; }
|
||||
public int ModuleIndex { get; set; }
|
||||
public System.Threading.ManualResetEvent StopEvent { get; set; }
|
||||
public bool CareAboutSampleNumber { get; set; }
|
||||
public int minCallbackUpdateTimeMs { get; set; }
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTimePolling(ServiceCallback callback,
|
||||
object userData,
|
||||
ManualResetEvent mre,
|
||||
byte[] channels)
|
||||
{
|
||||
var packet = new RealTimeAsyncPacket();
|
||||
packet.info = new TDASServiceAsyncInfo(callback, userData);
|
||||
packet.StopEvent = mre;
|
||||
if (IsG5())
|
||||
{
|
||||
packet.millisecBetweenSamples = 50;
|
||||
packet.samplesPerSecond = 1000;
|
||||
packet.CareAboutSampleNumber = false;
|
||||
LaunchAsyncWorker("TDAS.Realtime", new WaitCallback(AsyncRealTime), packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
LaunchAsyncWorker("TDAS.RealtimePolling", new WaitCallback(AsyncRealTimePolling), packet);
|
||||
}
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTime(int samplesPerSecond,
|
||||
int millisecBetweenSamples,
|
||||
ServiceCallback callback,
|
||||
object userData,
|
||||
bool realtimeMultipleSamplesEnabled,
|
||||
int moduleIndex,
|
||||
ManualResetEvent stopEvent,
|
||||
byte[] channels,
|
||||
double aaf,
|
||||
int minCallbackUpdateTimeMs,
|
||||
bool UseUDPStreaming,
|
||||
string hostIPAddress)
|
||||
{
|
||||
|
||||
var packet = new RealTimeAsyncPacket
|
||||
{
|
||||
info = new TDASServiceAsyncInfo(callback, userData),
|
||||
millisecBetweenSamples = millisecBetweenSamples,
|
||||
samplesPerSecond = samplesPerSecond,
|
||||
realtimeMultipleSamplesEnabled = realtimeMultipleSamplesEnabled,
|
||||
ModuleIndex = moduleIndex,
|
||||
CareAboutSampleNumber = true,
|
||||
StopEvent = stopEvent,
|
||||
minCallbackUpdateTimeMs = minCallbackUpdateTimeMs
|
||||
};
|
||||
LaunchAsyncWorker("TDAS.RealTime", new WaitCallback(AsyncRealTime), packet);
|
||||
}
|
||||
|
||||
void IRealTimeActions.RealTimeTiltPolling(ServiceCallback callback, object userData, ManualResetEvent stopEvent)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
|
||||
public string UDPStreamAddress { get; }
|
||||
void IRealTimeActions.SetUDPStreamProfile(ServiceCallback callback, object userData, UDPStreamProfile streamProfile, string udpAddress, ushort timeChannelId, ushort dataChannelId, uint[] tmnsConfig, ushort irigTimeDataPacketIntervalMs)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
void IRealTimeActions.GetUDPStreamProfile(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
|
||||
private object CallbackLock = new object();
|
||||
private DateTime lastUpdate = DateTime.MinValue;
|
||||
private const int MIN_CALLBACK_UPDATE_TIME = 10;
|
||||
private List<UInt64> _timeStamps = new List<ulong>();
|
||||
private List<UInt64> _sequenceNumbers = new List<ulong>();
|
||||
private List<UInt64> _sampleNumbers = new List<ulong>();
|
||||
private List<short[][]> _dataSamples = new List<short[][]>();
|
||||
|
||||
private const int BufferSize = 4096;
|
||||
private readonly byte[] _buffer = new byte[BufferSize];
|
||||
private RealTimeAsyncPacket _packet;
|
||||
private const int NumChannels = 8;
|
||||
private const int StartChannel = 0;
|
||||
|
||||
private void ProcessData(IAsyncResult ar)
|
||||
{
|
||||
lock (CallbackLock)
|
||||
{
|
||||
var bytes = sock.EndReceive(ar);
|
||||
if (0 == bytes) { return; }
|
||||
var s = Encoding.ASCII.GetString(_buffer, 0, bytes);
|
||||
s = s.Replace("\r\n", Convert.ToChar(0xBF).ToString());
|
||||
var lines = s.Split(Convert.ToChar(0xBF));
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var rtData = new short[NumChannels][];
|
||||
if (!line.Contains("MD")) { continue; }
|
||||
var tokens = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (tokens.Length < 8) { continue; }
|
||||
//0 = command, 1 = time, 2 = channel 0, etc
|
||||
for (var i = 0; i < NumChannels; i++)
|
||||
{
|
||||
rtData[i] = new short[1];
|
||||
rtData[i][0] = short.MaxValue;
|
||||
if (i >= StartChannel)
|
||||
{
|
||||
var index = i - StartChannel + 2;
|
||||
if (index < tokens.Length)
|
||||
{
|
||||
short.TryParse(tokens[i - StartChannel + 2], out rtData[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
_dataSamples.Add(rtData);
|
||||
}
|
||||
//TDAS reporting interval is slow enough, don't restrict it further!
|
||||
//if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds > MIN_CALLBACK_UPDATE_TIME)
|
||||
{
|
||||
_packet.info.NewData(_dataSamples, _sampleNumbers, _timeStamps, _sequenceNumbers);
|
||||
|
||||
_dataSamples.Clear();
|
||||
//lastUpdate = DateTime.Now;
|
||||
}
|
||||
}
|
||||
sock.BeginReceive(_buffer, 0, BufferSize, new AsyncCallback(ProcessData), null);
|
||||
}
|
||||
/// <summary>
|
||||
/// only used with RACK,
|
||||
/// is a polling (sampleaverage/single sample) realtime mode
|
||||
/// </summary>
|
||||
/// <param name="asyncInfo"></param>
|
||||
private void AsyncRealTimePolling(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeAsyncPacket;
|
||||
|
||||
//List<ulong> sampleNumbers = new List<ulong>();
|
||||
//List<short[][]> data = new List<short[][]>();
|
||||
const int numTDASDIMChannels = 16;
|
||||
|
||||
ulong sampleNumber = 0;
|
||||
var numChannels = ConfigData.Modules.Sum(module => module.NumberOfChannels());
|
||||
|
||||
while (!(this as DTS.Common.Interface.DASFactory.ICommunication).IsCanceled() && !packet.StopEvent.WaitOne(0))
|
||||
{
|
||||
var curChannel = 0;
|
||||
//first array is channels, second array are samples
|
||||
var rtData = new short[numChannels][];
|
||||
|
||||
foreach (var module in DASInfo.Modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (module.TypeOfModule)
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.EMPTYBANK:
|
||||
continue;
|
||||
case DFConstantsAndEnums.ModuleType.ProTOM:
|
||||
{
|
||||
curChannel += 16; //8squibs, 8 digitals
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var ss = new SampleAverage(this)
|
||||
{
|
||||
ModuleIndex = module.ModuleArrayIndex
|
||||
};
|
||||
ss.SyncExecute();
|
||||
if (module.TypeOfModule == DFConstantsAndEnums.ModuleType.ProDIM)
|
||||
{
|
||||
//apparently the DIM for SA just returns 1.0, 0
|
||||
for (int ch = 0; ch < numTDASDIMChannels; ch++)
|
||||
{
|
||||
rtData[curChannel++] = new short[]
|
||||
{
|
||||
0 == ss.ChannelValues[ch] ? short.MinValue : short.MaxValue
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int ch = 0; ch < 8; ch++)
|
||||
{
|
||||
rtData[curChannel++] = new short[] { Convert.ToInt16(ss.ChannelValues[ch]) };
|
||||
}
|
||||
}
|
||||
|
||||
//if (IsG5() && i == 0)
|
||||
//{
|
||||
// int digitalbits = (ss.ChannelValues[9] << 16) | ss.ChannelValues[8];
|
||||
// BitVector32 bv = new BitVector32(digitalbits);
|
||||
// for (int digCh = 0; digCh < 16; digCh++)
|
||||
// {
|
||||
// if (bv[(1 << digCh)])
|
||||
// {
|
||||
// rtData[32 + digCh] = new short[] {short.MinValue};
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// rtData[32 + digCh] = new short[] {short.MaxValue};
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
packet.info.NewData(new List<short[][]>() { rtData }, new List<ulong>(new ulong[] { sampleNumber }), new List<ulong>(new ulong[] { ulong.MinValue }), new List<ulong>(new ulong[] { ulong.MinValue }));
|
||||
Thread.Sleep(50);
|
||||
sampleNumber++;
|
||||
//if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds >= MIN_CALLBACK_UPDATE_TIME)
|
||||
//{
|
||||
// lastUpdate = DateTime.Now;
|
||||
// packet.info.NewData(data, sampleNumbers);
|
||||
// sampleNumbers.Clear();
|
||||
// data.Clear();
|
||||
//}
|
||||
}
|
||||
packet.info.Success();
|
||||
}
|
||||
/// <summary>
|
||||
/// indicates whether the DAS supports streaming
|
||||
/// 10572 implement SW side for single command streaming realtime
|
||||
/// </summary>
|
||||
public bool SupportsIndividualChannelRealtimeStreaming => false;
|
||||
|
||||
/// <summary>
|
||||
/// this is used to space out the samples in a multiple sample packet of g5 realtime
|
||||
/// I based it on the max SPS, which is what we always send to the g5 (1k SPS)
|
||||
/// through empirical testing with the sig-gen, I changed to 1/978 for U5
|
||||
/// </summary>
|
||||
private const double _g5RealtimeInterval = 1 / 978D;
|
||||
//private DateTime _lastRTLogTime = DateTime.MinValue;
|
||||
//private int _samplesProcessed = 0;
|
||||
/// <summary>
|
||||
/// The worker for realtime service.
|
||||
/// </summary>
|
||||
/// <param name="asyncInfo">A RealTimeAsyncPacket for responses</param>
|
||||
private void AsyncRealTime(object asyncInfo)
|
||||
{
|
||||
var packet = asyncInfo as RealTimeAsyncPacket;
|
||||
_packet = packet;
|
||||
|
||||
//tdas devices for realtime have both a sampling rate and a reporting rate
|
||||
//ultimately the reporting rate will drive what we see in realtime
|
||||
//the user has requested a specific realtime rate, however right now
|
||||
//we just force the rate on TDAS equipment, this means we have to go and
|
||||
//adjust our sample numbers as if we were running at the requested rate.
|
||||
double expectedSampleRate = packet.samplesPerSecond;
|
||||
bool bG5 = IsG5();
|
||||
try
|
||||
{
|
||||
if (!SupportsRealtime()) { packet.info.Success(); return; }
|
||||
|
||||
FlushTimeoutMilliSec = 0;
|
||||
var sampleNumbers = new List<ulong>();
|
||||
var timeStamps = new List<ulong>();
|
||||
var sequenceNumbers = new List<ulong>();
|
||||
var data = new List<short[][]>();
|
||||
var dtSTart = DateTime.Now;
|
||||
var sampleNumberCarryover = 0;
|
||||
|
||||
if (bG5)
|
||||
{
|
||||
var mdx = new G5MonitorData(this);
|
||||
mdx.SyncExecute();
|
||||
}
|
||||
else
|
||||
{
|
||||
Command.TDAS.ProMonitorData md = new Command.TDAS.ProMonitorData(this, DASInfo.Modules[packet.ModuleIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.ProSIM);
|
||||
md.ModuleIndex = packet.ModuleIndex;
|
||||
md.SyncExecute();
|
||||
}
|
||||
|
||||
|
||||
// Then consume the constant responses. Be sure to turn off logging for performance.
|
||||
Command.TDAS.MonitorDataNextSampleBase.MonitorType mt;
|
||||
if (IsG5())
|
||||
{
|
||||
mt = Command.TDAS.MonitorDataNextSampleBase.MonitorType.G5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DASInfo.Modules[packet.ModuleIndex].TypeOfModule == DFConstantsAndEnums.ModuleType.ProDIM)
|
||||
{
|
||||
mt = MonitorDataNextSampleBase.MonitorType.DIM;
|
||||
}
|
||||
else
|
||||
{
|
||||
mt = MonitorDataNextSampleBase.MonitorType.Pro;
|
||||
}
|
||||
}
|
||||
|
||||
Command.TDAS.MonitorDataNextSampleBase next = new Command.TDAS.MonitorDataNextSampleBase(this, mt);
|
||||
|
||||
next.LogCommands = false;
|
||||
while (true && !(this as DTS.Common.Interface.DASFactory.ICommunication).IsCanceled() && !packet.StopEvent.WaitOne(1))
|
||||
{
|
||||
Thread.Sleep(50);
|
||||
sampleNumbers.Clear();
|
||||
timeStamps.Clear();
|
||||
data.Clear();
|
||||
|
||||
// get the next response(s)
|
||||
next.SyncExecute();
|
||||
|
||||
var moreData = next.RTData;
|
||||
var timeSamples = next.Times;
|
||||
// Maybe we're ahead of the das.
|
||||
if (0 == moreData.Count())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bG5)
|
||||
{
|
||||
for (int currentSample = 0; currentSample < moreData.Count; currentSample++)
|
||||
{
|
||||
short digitalBits = moreData[currentSample][32];
|
||||
short[] newData = new short[48];
|
||||
Array.Copy(moreData[currentSample], newData, 32);
|
||||
|
||||
System.Collections.Specialized.BitVector32 bv = new System.Collections.Specialized.BitVector32(Convert.ToInt32(digitalBits));
|
||||
|
||||
for (int iChannelIdx = 0; iChannelIdx < 16; iChannelIdx++)
|
||||
{
|
||||
//also note that the bitvector [] operator expects a bitmask, not an index ...
|
||||
if (bv[(1 << iChannelIdx)]) { newData[32 + iChannelIdx] = short.MinValue; }
|
||||
else { newData[32 + iChannelIdx] = short.MaxValue; }
|
||||
}
|
||||
moreData[currentSample] = newData;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//the service is expecting a DAS full of realtime sample data,
|
||||
//however with realtime on a rack, we're only going to have one module responding with data, so we need to fake data from the other modules
|
||||
//for now since the first SIM module is the only module we're accepting data from I can spoof data from all other channels
|
||||
bool bFound = false;
|
||||
List<List<short>> largerDataArray = new List<List<short>>();
|
||||
|
||||
for (int sample = 0; sample < moreData.Count; sample++)
|
||||
{
|
||||
bFound = false;
|
||||
for (int iModule = 0; iModule < DASInfo.Modules.Length; iModule++)
|
||||
{
|
||||
if (largerDataArray.Count <= sample) { largerDataArray.Add(new List<short>()); }
|
||||
switch (DASInfo.Modules[iModule].TypeOfModule)
|
||||
{
|
||||
case DFConstantsAndEnums.ModuleType.EMPTYBANK://ignore
|
||||
break;
|
||||
case DFConstantsAndEnums.ModuleType.ProDIM:
|
||||
if (!bFound && iModule == packet.ModuleIndex)
|
||||
{
|
||||
bFound = true;
|
||||
foreach (var d in moreData[sample])
|
||||
{
|
||||
System.Collections.Specialized.BitVector32 bv = new System.Collections.Specialized.BitVector32(d);
|
||||
short[] array = new short[16];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (bv[1 << i])
|
||||
{
|
||||
if (!IsG5())
|
||||
{
|
||||
array[i] = short.MaxValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[i] = short.MaxValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsG5())
|
||||
{
|
||||
array[i] = short.MinValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
array[i] = short.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
largerDataArray[sample].AddRange(array);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
largerDataArray[sample].AddRange(new short[]
|
||||
{
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue
|
||||
});
|
||||
}
|
||||
break;
|
||||
case DFConstantsAndEnums.ModuleType.ProSIM:
|
||||
if (!bFound && iModule == packet.ModuleIndex)
|
||||
{
|
||||
bFound = true;
|
||||
largerDataArray[sample].AddRange(moreData[sample]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//add 8 channels of short.minvalue
|
||||
largerDataArray[sample].AddRange(new short[]
|
||||
{
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue,
|
||||
short.MinValue
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < DASInfo.Modules[iModule].NumberOfChannels; i++)
|
||||
{
|
||||
largerDataArray[sample].Add(short.MinValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
moreData = new List<short[]>(largerDataArray.Count);
|
||||
for (int sample = 0; sample < largerDataArray.Count; sample++)
|
||||
{
|
||||
moreData.Add(largerDataArray[sample].ToArray());
|
||||
}
|
||||
|
||||
}
|
||||
// Need to transpose the data to comply with the service interface.
|
||||
int maxSample = moreData.Count();
|
||||
if (!packet.CareAboutSampleNumber)
|
||||
{
|
||||
maxSample = 1;//just do one sample back, we are in meter table mode and don't need the update speed...
|
||||
}
|
||||
for (int currentSample = 0; currentSample < maxSample; currentSample++)
|
||||
{
|
||||
short[][] transposedData = new short[moreData[0].Count()][];
|
||||
for (int currentChannel = 0; currentChannel < transposedData.Length; currentChannel++)
|
||||
{
|
||||
transposedData[currentChannel] = new short[1];
|
||||
transposedData[currentChannel][0] = moreData[currentSample][currentChannel];
|
||||
}
|
||||
data.Add(transposedData.ToArray());
|
||||
if (packet.CareAboutSampleNumber)
|
||||
{
|
||||
if (IsG5())
|
||||
{
|
||||
//compute sample numbers by starting at 0 and then just incrementing
|
||||
//finally, convert from that number to what the requested rate is. ideally the request rate is faster to prevent sample
|
||||
//number overlap, but it's more important the time scale is correct
|
||||
//this should just cause aliasing if the sample numbers overlap
|
||||
sampleNumbers.Add(
|
||||
Convert.ToUInt64(Convert.ToDouble(sampleNumberCarryover * _g5RealtimeInterval) *
|
||||
expectedSampleRate));
|
||||
timeStamps.Add(ulong.MinValue);
|
||||
if (sampleNumberCarryover == Int32.MaxValue)
|
||||
{
|
||||
sampleNumberCarryover = 0;
|
||||
}
|
||||
sampleNumberCarryover++;
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleNumbers.Add(Convert.ToUInt64(timeSamples[currentSample] * expectedSampleRate));
|
||||
timeStamps.Add(ulong.MinValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sampleNumberCarryover == Int32.MaxValue)
|
||||
{
|
||||
sampleNumberCarryover = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleNumberCarryover++;
|
||||
}
|
||||
sampleNumbers.Add(Convert.ToUInt64(sampleNumberCarryover));
|
||||
timeStamps.Add(ulong.MinValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Send the data to the caller.
|
||||
packet.info.NewData(data, sampleNumbers, timeStamps, sequenceNumbers);
|
||||
}
|
||||
if ((this as DTS.Common.Interface.DASFactory.ICommunication).IsCanceled())
|
||||
{
|
||||
packet.info.Cancel();
|
||||
}
|
||||
StopRealtime();
|
||||
packet.info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
// We land here when the user cancels real time.
|
||||
packet.info.Cancel();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
packet.info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this service to terminate real time streaming.
|
||||
/// </summary>
|
||||
/// <param name="callback">User provided callback</param>
|
||||
/// <param name="userData">User provided data object</param>
|
||||
void IRealTimeActions.ExitRealTimeMode(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TDASServiceAsyncInfo(callback, userData);
|
||||
|
||||
LaunchAsyncWorker("TDAS.ExitRealTimeMode", new WaitCallback(AsyncExitRealTimeMode), info);
|
||||
}
|
||||
|
||||
private void StopRealtime()
|
||||
{
|
||||
if (!SupportsRealtime()) { return; }
|
||||
else
|
||||
{
|
||||
|
||||
if (IsG5())
|
||||
{
|
||||
QuitG5Monitoring qm = new QuitG5Monitoring(this);
|
||||
qm.SyncExecute();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
QuerySerialNumber qs = new QuerySerialNumber(this, 2000);
|
||||
qs.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void AsyncExitRealTimeMode(object asyncInfo)
|
||||
{
|
||||
var info = asyncInfo as TDASServiceAsyncInfo;
|
||||
|
||||
try
|
||||
{
|
||||
StopRealtime();
|
||||
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false;// FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
|
||||
info.Success();
|
||||
}
|
||||
catch (CanceledException)
|
||||
{
|
||||
info.Cancel();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
272
DataPRO/IService/Classes/TDAS Service/TDAS Service.cs
Normal file
272
DataPRO/IService/Classes/TDAS Service/TDAS Service.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
//using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.DASResource;
|
||||
using DTS.Common.ICommunication;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Classes.Connection;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
public bool IsEthernetDistributor() { return false; }
|
||||
public bool IsSlice6Distributor() { return false; }
|
||||
public bool IsBattery() { return false; }
|
||||
public bool IsTSRAIR() { return false; }
|
||||
public bool IsSlice6Air() { return false; }
|
||||
public bool IsSlice6AirTc() { return false; }
|
||||
public bool IsScheduleEventCountSupported() { return false; }
|
||||
public class TDASDownloadServiceAsyncInfo
|
||||
{
|
||||
public TDASServiceAsyncInfo info { get; set; }
|
||||
public TDASServiceSetupInfo setupInfo { get; set; }
|
||||
|
||||
public TDASDownloadServiceAsyncInfo(TDASServiceAsyncInfo _info, object _setupInfo)
|
||||
{
|
||||
info = _info;
|
||||
if (_setupInfo != null)
|
||||
{
|
||||
setupInfo = _setupInfo as TDASServiceSetupInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TDASServiceQueryConfigAsyncInfo : TDASServiceAsyncInfo
|
||||
{
|
||||
public bool ReadIds { get; set; } = true;
|
||||
|
||||
public TDASServiceQueryConfigAsyncInfo(bool bReadIds, ServiceCallback callback, object userData)
|
||||
: base(callback, userData)
|
||||
{
|
||||
ReadIds = bReadIds;
|
||||
}
|
||||
}
|
||||
public class TDASServiceAsyncInfo
|
||||
{
|
||||
public ServiceCallback callback { get; set; }
|
||||
public object userData { get; set; }
|
||||
public object functionData { get; set; }
|
||||
|
||||
public TDASServiceAsyncInfo(ServiceCallback _callback, object _userData)
|
||||
{
|
||||
callback = _callback;
|
||||
userData = _userData;
|
||||
}
|
||||
|
||||
public void Error(string msg, Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cbData = new ServiceCallbackData();
|
||||
cbData.Status = ServiceCallbackData.CallbackStatus.Failure;
|
||||
cbData.ErrorMessage = msg;
|
||||
cbData.ErrorException = ex;
|
||||
cbData.UserData = userData;
|
||||
callback(cbData);
|
||||
}
|
||||
catch (Exception eex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.TDASAsyncInfoError, eex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Error(string msg)
|
||||
{
|
||||
Error(msg, null);
|
||||
}
|
||||
|
||||
public void Progress(int value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.ProgressReport;
|
||||
progressData.ProgressValue = value;
|
||||
progressData.UserData = userData;
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.TDASAsyncInfoProgressError, ex);
|
||||
}
|
||||
}
|
||||
public void NewData(object obj)
|
||||
{
|
||||
if (obj is ServiceCallbackData.DiagnosticNewData)
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.SetNewDiagnosticData((obj as ServiceCallbackData.DiagnosticNewData));
|
||||
callback(progressData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var newdatadata = obj as NewDataData;
|
||||
var datas = newdatadata.datas;
|
||||
var samplenumbers = newdatadata.SampleNumbers;
|
||||
var timeStamps = newdatadata.TimeStamps;
|
||||
var sequenceNumbers = newdatadata.SequenceNumbers;
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
for (var i = 0; i < datas.Length && i < samplenumbers.Length; i++)
|
||||
{
|
||||
progressData.AddSampleData(datas[i], samplenumbers[i], timeStamps[i], sequenceNumbers[i]);
|
||||
}
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.SLICEAsyncInfoNewDataError, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void NewData(IList<short[][]> datas, IList<ulong> samplenumbers, IList<ulong> timeStamps, IList<ulong> sequenceNumbers)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
for (var i = 0; i < datas.Count && i < samplenumbers.Count; i++)
|
||||
{
|
||||
progressData.AddSampleData(datas[i], samplenumbers[i], timeStamps[i], 0);
|
||||
}
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.TDASAsyncInfoNewDataError, ex);
|
||||
}
|
||||
}
|
||||
public void NewData(short[][] data, ulong samplenumber, ulong timeStamp, ulong sequenceNumber)
|
||||
{
|
||||
try
|
||||
{
|
||||
var progressData = new ServiceCallbackData();
|
||||
progressData.Status = ServiceCallbackData.CallbackStatus.NewData;
|
||||
progressData.ProgressValue = 0;
|
||||
progressData.UserData = userData;
|
||||
progressData.AddSampleData(data, samplenumber, timeStamp, sequenceNumber);
|
||||
callback(progressData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.TDASAsyncInfoNewDataError, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Success()
|
||||
{
|
||||
try
|
||||
{
|
||||
var success = new ServiceCallbackData();
|
||||
success.Status = ServiceCallbackData.CallbackStatus.Success;
|
||||
success.UserData = userData;
|
||||
callback(success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
APILogger.Log("MessageBox", Strings.TDASAsyncInfoSuccessError, 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.TDASAsyncInfoCancelError, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LaunchAsyncWorker(string Invoker, WaitCallback cb, object asyncInfo)
|
||||
{
|
||||
if (!Connected)
|
||||
{
|
||||
// "{0}: Not currently connected"
|
||||
throw new NotConnectedException(string.Format(Strings.Slice_LaunchAsyncWorker_Err1, Invoker));
|
||||
}
|
||||
|
||||
if (!ThreadPool.QueueUserWorkItem(cb, asyncInfo))
|
||||
{
|
||||
// "{0}: Unable to enqueue function"
|
||||
throw new Exception(string.Format(Strings.Slice_LaunchAsyncWorker_Err2, Invoker));
|
||||
}
|
||||
}
|
||||
|
||||
private void CallSyncMethod(string Invoker, WaitCallback cb, object info)
|
||||
{
|
||||
if (!Connected)
|
||||
{
|
||||
// "{0}: Not currently connected"
|
||||
throw new NotConnectedException(string.Format(Strings.Slice_LaunchAsyncWorker_Err1, Invoker));
|
||||
}
|
||||
cb(info);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// compare to an object to determine equality
|
||||
/// </summary>
|
||||
/// <param name="right"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object right)
|
||||
{
|
||||
|
||||
if (right == null)
|
||||
return false;
|
||||
|
||||
if (ReferenceEquals(this, right))
|
||||
return true;
|
||||
|
||||
if (!(right is TDAS<T> rightSlice))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(SerialNumber))
|
||||
{
|
||||
return string.IsNullOrEmpty(rightSlice.SerialNumber);
|
||||
}
|
||||
if (string.IsNullOrEmpty(rightSlice.SerialNumber))
|
||||
return false;
|
||||
return SerialNumber == rightSlice.SerialNumber;
|
||||
}
|
||||
/// <summary>
|
||||
/// returns identical index for any two 'equal' slice
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (string.IsNullOrEmpty(SerialNumber))
|
||||
return 0;
|
||||
return SerialNumber.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
326
DataPRO/IService/Classes/TDAS Service/TriggerCheck.cs
Normal file
326
DataPRO/IService/Classes/TDAS Service/TriggerCheck.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using System.Threading;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.ICommunication;
|
||||
using System;
|
||||
using DTS.Common.Interface.Connection;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public partial class TDAS<T> : Communication<T>,
|
||||
IDASCommunication,
|
||||
IConfigurationActions,
|
||||
IDiagnosticsActions,
|
||||
ITriggerCheckActions,
|
||||
IRealTimeActions,
|
||||
IArmActions,
|
||||
IDownloadActions where T : IConnection, new()
|
||||
{
|
||||
#region Trigger check
|
||||
void ITriggerCheckActions.PreStartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
void ITriggerCheckActions.PostStartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
info.Success();
|
||||
}
|
||||
private class TriggerCheckPacket : TDASServiceAsyncInfo
|
||||
{
|
||||
public TriggerCheckPacket(ServiceCallback cb, object ud)
|
||||
: base(cb, ud)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void ITriggerCheckActions.StartTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
LaunchAsyncWorker("TDAS.StartTriggerCheck", AsyncStartTriggerCheck, info);
|
||||
}
|
||||
|
||||
private void AsyncStartTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is TriggerCheckPacket info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (null == DASArmStatus)
|
||||
{
|
||||
SetDASArmStatus(new ArmStatus(), true);
|
||||
}
|
||||
var status = DASArmStatus;
|
||||
try
|
||||
{
|
||||
status.IsArmed = true;
|
||||
status.IsRecording = false;
|
||||
status.IsTriggered = false;
|
||||
foreach (var module in DASInfo.Modules)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (module.TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsG5())
|
||||
{
|
||||
var testTrigger = new Command.TDAS.TestTrigger(this)
|
||||
{
|
||||
ModuleIndex = module.ModuleArrayIndex,
|
||||
SubCommand = Command.TDAS.TestTrigger.SubCommandValues.ARM
|
||||
};
|
||||
testTrigger.SyncExecute();
|
||||
break;
|
||||
}
|
||||
|
||||
var qsn = new Command.TDAS.QuerySerialNumberBroadcast(this, module.ModuleArrayIndex);
|
||||
qsn.SyncExecute();
|
||||
|
||||
var ttb = new Command.TDAS.TestTriggerBroadcast(this, module.ModuleArrayIndex)
|
||||
{
|
||||
SubCommand = Command.TDAS.TestTrigger.SubCommandValues.ARM
|
||||
};
|
||||
ttb.SyncExecute();
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetDASArmStatus(status, true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
//assuming this is for logging purposes...unknown
|
||||
var ta = new Command.TDAS.TestAll(this) { Mode = Command.TDAS.TestAllCommandString.Modes.CURR };
|
||||
ta.SyncExecute();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error(ex.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
info.Success();
|
||||
}
|
||||
|
||||
void ITriggerCheckActions.DoTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
LaunchAsyncWorker("TDAS.DoTriggercheck", AsyncDoTriggerCheck, info);
|
||||
}
|
||||
void ITriggerCheckActions.DoStartCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
LaunchAsyncWorker("TDAS.DoStartcheck", AsyncDoStartCheck, info);
|
||||
}
|
||||
private void AsyncDoStartCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is TriggerCheckPacket info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (null == DASArmStatus)
|
||||
{
|
||||
SetDASArmStatus(new ArmStatus(), false);
|
||||
}
|
||||
var status = DASArmStatus;
|
||||
try
|
||||
{
|
||||
var ta = new Command.TDAS.TestAll(this) { Mode = Command.TDAS.TestAllCommandString.Modes.PREV };
|
||||
try
|
||||
{
|
||||
ta.SyncExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
info.Error(ex.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ta.StartedRecordingFlag == DFConstantsAndEnums.VoltageStatusColor.Yellow
|
||||
|| ta.StartedRecordingFlag == DFConstantsAndEnums.VoltageStatusColor.Red)
|
||||
{
|
||||
status.IsRecording = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartRecord = false;
|
||||
}
|
||||
|
||||
if (DASArmStatus.IsRecording)
|
||||
{
|
||||
status.IsArmed = false;
|
||||
}
|
||||
status.IsArmed = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetDASArmStatus(status, true);
|
||||
}
|
||||
|
||||
info.Success();
|
||||
}
|
||||
|
||||
void ITriggerCheckActions.DoTriggerCheckSync()
|
||||
{
|
||||
//this function was created as part of
|
||||
//5211 Add check to ECM event line during ArmChecklist
|
||||
//however to minimize impact since the issue doesn't affect TDAS
|
||||
//I'll not make the changes to TDAS trigger check/armchecklist checks
|
||||
//instead for now I'll leave it as is
|
||||
//since this function shouldn't be used (unless we make the changes above), I'll leave it
|
||||
//with an exception to warn anyone that hooks it up not realizing the issue
|
||||
throw new NotImplementedException("DoTriggerCheckSync is not implemented for TDAS");
|
||||
}
|
||||
private void AsyncDoTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is TriggerCheckPacket info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var ta = new Command.TDAS.TestAll(this) { Mode = Command.TDAS.TestAllCommandString.Modes.PREV };
|
||||
ta.SyncExecute();
|
||||
|
||||
if (ta.TriggerFlag == DFConstantsAndEnums.VoltageStatusColor.Red
|
||||
|| ta.TriggerFlag == DFConstantsAndEnums.VoltageStatusColor.Yellow)
|
||||
{
|
||||
DASArmStatus.IsTriggered = true;
|
||||
SetDASArmStatus();
|
||||
try
|
||||
{
|
||||
var status = new ArmStatus();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var module in DASInfo.Modules)
|
||||
{
|
||||
if (IsG5() && 0 < module.ModuleArrayIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (module.TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var testTrigger = new Command.TDAS.TestTrigger(this, 5000);
|
||||
testTrigger.ModuleIndex = module.ModuleArrayIndex;
|
||||
testTrigger.SubCommand = Command.TDAS.TestTrigger.SubCommandValues.STATUS;
|
||||
try
|
||||
{
|
||||
testTrigger.SyncExecute();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Module probably timed out because it is still armed and never responded to the rack trigger/event line.
|
||||
status.IsArmed = true;
|
||||
status.IsTriggered = false;
|
||||
info.Error(module.SerialNumber + " did not trigger, but other modules did");
|
||||
return;
|
||||
}
|
||||
|
||||
if (testTrigger.TriggerStatus == Command.TDAS.TestTrigger.StatusValues.OFF)
|
||||
{
|
||||
status.IsTriggered = true;
|
||||
status.IsArmed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status.IsTriggered)
|
||||
{
|
||||
info.Error(module.SerialNumber + " did not trigger, but other modules did");
|
||||
return;
|
||||
}
|
||||
|
||||
status.IsTriggered = false;
|
||||
status.IsArmed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally { SetDASArmStatus(status, true); }
|
||||
|
||||
info.Success();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error(ex.Message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
info.Success();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
info.Error(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
void ITriggerCheckActions.CancelTriggerCheck(ServiceCallback callback, object userData)
|
||||
{
|
||||
var info = new TriggerCheckPacket(callback, userData);
|
||||
LaunchAsyncWorker("TDAS.CancelTriggerCheck", AsyncCancelTriggerCheck, info);
|
||||
}
|
||||
|
||||
private void AsyncCancelTriggerCheck(object asyncInfo)
|
||||
{
|
||||
if (!(asyncInfo is TriggerCheckPacket info))
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
foreach (var m in DASInfo.Modules)
|
||||
{
|
||||
if (m.SerialNumber == "EMPTY" || m.TypeOfModule == DFConstantsAndEnums.ModuleType.EMPTYBANK) continue;
|
||||
if (IsG5())
|
||||
{
|
||||
var testTrigger = new Command.TDAS.TestTrigger(this);
|
||||
testTrigger.ModuleIndex = m.ModuleArrayIndex;
|
||||
testTrigger.SubCommand = Command.TDAS.TestTrigger.SubCommandValues.OFF;
|
||||
testTrigger.SyncExecute();
|
||||
|
||||
var qsn = new Command.TDAS.QuerySerialNumber(this);
|
||||
qsn.ModuleIndex = m.ModuleArrayIndex;
|
||||
qsn.SyncExecute();
|
||||
break;
|
||||
}
|
||||
var qsc = new Command.TDAS.QuerySerialNumberBroadcast(this, m.ModuleArrayIndex);
|
||||
qsc.SyncExecute();
|
||||
|
||||
var tbc = new Command.TDAS.TestTriggerBroadcast(this, m.ModuleArrayIndex);
|
||||
tbc.SubCommand = Command.TDAS.TestTrigger.SubCommandValues.OFF;
|
||||
tbc.SyncExecute();
|
||||
|
||||
var qsnb = new Command.TDAS.QuerySerialNumberBroadcast(this, m.ModuleArrayIndex);
|
||||
qsnb.SyncExecute();
|
||||
break;
|
||||
}
|
||||
info.Success();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
info.Error(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
118
DataPRO/IService/Classes/TDAS/TDASConfig.cs
Normal file
118
DataPRO/IService/Classes/TDAS/TDASConfig.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class TDASConfig : IXmlSerializable
|
||||
{
|
||||
private Dictionary<string, TDASModuleConfig> _modules = new Dictionary<string, TDASModuleConfig>();
|
||||
public Dictionary<string, TDASModuleConfig> Modules { get { return _modules; } }
|
||||
private string _fileName;
|
||||
public string FileName { get { return _fileName; } }
|
||||
|
||||
public TDASConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public TDASConfig(string fileName, bool deleteIfPresent)
|
||||
{
|
||||
const string dasConfigs = "DASConfigs";
|
||||
var location = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), dasConfigs), fileName);
|
||||
|
||||
_fileName = location; //fileName;
|
||||
if (File.Exists(location))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (deleteIfPresent)
|
||||
{
|
||||
try { File.Delete(_fileName); }
|
||||
catch (Exception ex) { APILogger.Log("Problem deleting ", _fileName, ex); }
|
||||
}
|
||||
else { using (var sr = new StreamReader(_fileName)) { ReadXml(XmlReader.Create(sr)); } }
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log("Problem reading ", _fileName, ex); }
|
||||
}
|
||||
}
|
||||
public void SetModule(TDASModuleConfig module)
|
||||
{
|
||||
if (_modules.ContainsKey(module.SerialNumber)) { _modules[module.SerialNumber] = module; }
|
||||
else { _modules.Add(module.SerialNumber, module); }
|
||||
}
|
||||
public TDASModuleConfig GetModule(TDASModuleConfig module)
|
||||
{
|
||||
if (_modules.ContainsKey(module.SerialNumber)) { return _modules[module.SerialNumber]; }
|
||||
else
|
||||
{
|
||||
_modules.Add(module.SerialNumber, module);
|
||||
return module;
|
||||
}
|
||||
}
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Generates an object from its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// reader:
|
||||
// The System.Xml.XmlReader stream from which the object is deserialized.
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
reader.ReadStartElement("TDASConfig");
|
||||
|
||||
reader.ReadStartElement("Modules");
|
||||
|
||||
while (reader.MoveToContent() == XmlNodeType.Element)
|
||||
{
|
||||
TDASModuleConfig tConfig = new TDASModuleConfig();
|
||||
tConfig.ReadXml(reader);
|
||||
SetModule(tConfig);
|
||||
}
|
||||
|
||||
reader.ReadEndElement();
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Converts an object into its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// writer:
|
||||
// The System.Xml.XmlWriter stream to which the object is serialized.
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("TDASConfig");
|
||||
|
||||
writer.WriteStartElement("Modules");
|
||||
writer.Flush();
|
||||
|
||||
foreach (TDASModuleConfig module in _modules.Values)
|
||||
{
|
||||
module.WriteXml(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
326
DataPRO/IService/Classes/TDAS/TDASModuleConfig.cs
Normal file
326
DataPRO/IService/Classes/TDAS/TDASModuleConfig.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Utilities.DotNetProgrammingConstructs;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class TDASModuleConfig : IXmlSerializable
|
||||
{
|
||||
private string _serialNumber = "";
|
||||
public string SerialNumber { get { return _serialNumber; } set { _serialNumber = value; } }
|
||||
|
||||
private string _testId = "";
|
||||
public string TestId { get { return _testId; } set { _testId = value; } }
|
||||
|
||||
private string _testDescription = "";
|
||||
public string TestDescription { get { return _testDescription; } set { _testDescription = value; } }
|
||||
|
||||
public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; } = DFConstantsAndEnums.RecordingMode.InvalidArmMode;
|
||||
|
||||
private float _aaFilterRateHz = 0;
|
||||
public float AAFilterRateHz { get { return _aaFilterRateHz; } set { _aaFilterRateHz = value; } }
|
||||
|
||||
private double _preTriggerSeconds = 0;
|
||||
public double PreTriggerSeconds { get { return _preTriggerSeconds; } set { _preTriggerSeconds = value; } }
|
||||
|
||||
private double _postTriggerSeconds = 0;
|
||||
public double PostTriggerSeconds { get { return _postTriggerSeconds; } set { _postTriggerSeconds = value; } }
|
||||
|
||||
private Dictionary<int, DASChannel> _channels = new Dictionary<int, DASChannel>();
|
||||
|
||||
private string _fileName;
|
||||
public string FileName { get { return _fileName; } }
|
||||
|
||||
private string _firmwareVersion = "";
|
||||
public string FirmwareVersion { get { return _firmwareVersion; } set { _firmwareVersion = value; } }
|
||||
|
||||
private UInt64? _maxEventStorageSpaceInBytes = 0;
|
||||
public UInt64? MaxEventStorageSpaceInBytes { get { return _maxEventStorageSpaceInBytes; } set { _maxEventStorageSpaceInBytes = value; } }
|
||||
|
||||
private int moduleArrayIndex = 0;
|
||||
public int ModuleArrayIndex { get { return moduleArrayIndex; } set { moduleArrayIndex = value; } }
|
||||
|
||||
public TDASModuleConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public TDASModuleConfig(string fileName)
|
||||
{
|
||||
const string dasConfigs = "DASConfigs";
|
||||
var location = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), dasConfigs), fileName);
|
||||
_fileName = location; //fileName;
|
||||
if (File.Exists(_fileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamReader sr = new StreamReader(_fileName))
|
||||
{
|
||||
ReadXml(System.Xml.XmlReader.Create(sr));
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
APILogger.Log("Problem reading ", _fileName, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void SetChannel(OutputTOMDigitalChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { _channels[channel.ModuleChannelNumber] = channel; }
|
||||
else { _channels.Add(channel.ModuleChannelNumber, channel); }
|
||||
}
|
||||
public void SetChannel(OutputSquibChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { _channels[channel.ModuleChannelNumber] = channel; }
|
||||
else { _channels.Add(channel.ModuleChannelNumber, channel); }
|
||||
}
|
||||
public void SetChannel(AnalogInputDASChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { _channels[channel.ModuleChannelNumber] = channel; }
|
||||
else { _channels.Add(channel.ModuleChannelNumber, channel); }
|
||||
}
|
||||
public AnalogInputDASChannel GetChannel(AnalogInputDASChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { return _channels[channel.ModuleChannelNumber] as AnalogInputDASChannel; }
|
||||
else
|
||||
{
|
||||
_channels.Add(channel.ModuleChannelNumber, channel);
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
public OutputSquibChannel GetChannel(OutputSquibChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { return _channels[channel.ModuleChannelNumber] as OutputSquibChannel; }
|
||||
else
|
||||
{
|
||||
_channels.Add(channel.ModuleChannelNumber, channel);
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
public OutputTOMDigitalChannel GetChannel(OutputTOMDigitalChannel channel)
|
||||
{
|
||||
if (_channels.ContainsKey(channel.ModuleChannelNumber)) { return _channels[channel.ModuleChannelNumber] as OutputTOMDigitalChannel; }
|
||||
else
|
||||
{
|
||||
_channels.Add(channel.ModuleChannelNumber, channel);
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
public XmlSchema GetSchema()
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Generates an object from its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// reader:
|
||||
// The System.Xml.XmlReader stream from which the object is deserialized.
|
||||
public void ReadXml(XmlReader reader)
|
||||
{
|
||||
reader.MoveToContent();
|
||||
reader.ReadStartElement("TDASModule");
|
||||
reader.ReadStartElement("SerialNumber");
|
||||
_serialNumber = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("TestId");
|
||||
_testId = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
reader.ReadStartElement("TestDescription");
|
||||
_testDescription = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("RecordingMode");
|
||||
string recordingMode = reader.ReadString();
|
||||
try
|
||||
{
|
||||
RecordingMode = (DFConstantsAndEnums.RecordingMode)Enum.Parse(typeof(DFConstantsAndEnums.RecordingMode), recordingMode);
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("Failed to load RecordingMode ", recordingMode, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("AAFilterRateHz");
|
||||
string aaFilterRateHz = reader.ReadString();
|
||||
try
|
||||
{
|
||||
AAFilterRateHz = (float)Convert.ToDouble(aaFilterRateHz);
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("Failed to load AAFilterRateHz ", aaFilterRateHz, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("PreTriggerSeconds");
|
||||
string preTriggerSeconds = reader.ReadString();
|
||||
try
|
||||
{
|
||||
PreTriggerSeconds = Convert.ToDouble(preTriggerSeconds);
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("Failed to load PreTriggerSeconds ", preTriggerSeconds, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("PostTriggerSeconds");
|
||||
string postTriggerSeconds = reader.ReadString();
|
||||
try
|
||||
{
|
||||
PostTriggerSeconds = Convert.ToDouble(postTriggerSeconds);
|
||||
}
|
||||
catch (System.Exception ex) { APILogger.Log("Failed to load PostTriggerSeconds ", postTriggerSeconds, ex); }
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("FirmwareVersion");
|
||||
_firmwareVersion = reader.ReadString();
|
||||
reader.ReadEndElement();
|
||||
|
||||
reader.ReadStartElement("MaxEventStorageSpaceInBytes");
|
||||
string maxEventStorageSpaceInBytes = reader.ReadString();
|
||||
|
||||
{
|
||||
double d;
|
||||
if (double.TryParse(maxEventStorageSpaceInBytes, out d))
|
||||
{
|
||||
if (d >= 0 && d < ulong.MaxValue) { MaxEventStorageSpaceInBytes = Convert.ToUInt64(d); }
|
||||
else { APILogger.Log("Failed to load MaxEventStorageSpaceInBytes ", maxEventStorageSpaceInBytes); }
|
||||
}
|
||||
else { APILogger.Log("Failed to load MaxEventStorageSpaceInBytes ", maxEventStorageSpaceInBytes); }
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
|
||||
try
|
||||
{
|
||||
reader.ReadStartElement("ModuleArrayIndex");
|
||||
string moduleArrayIndex = reader.ReadString();
|
||||
|
||||
{
|
||||
int m;
|
||||
if (int.TryParse(moduleArrayIndex, out m))
|
||||
{
|
||||
if (m >= 0 && m < int.MaxValue) { ModuleArrayIndex = Convert.ToInt32(m); }
|
||||
else { APILogger.Log("Failed to load ModuleArrayIndex ", moduleArrayIndex); }
|
||||
}
|
||||
else { APILogger.Log("Failed to load ModuleArrayIndex ", moduleArrayIndex); }
|
||||
}
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
catch
|
||||
{
|
||||
//This must be an old config file
|
||||
}
|
||||
|
||||
reader.ReadStartElement("Channels");
|
||||
|
||||
while (reader.MoveToContent() == XmlNodeType.Element)
|
||||
{
|
||||
string sType = reader.GetAttribute("type");
|
||||
switch (sType)
|
||||
{
|
||||
case "OutputSquibChannel":
|
||||
OutputSquibChannel osc = new OutputSquibChannel();
|
||||
osc.ReadXml(reader);
|
||||
SetChannel(osc);
|
||||
break;
|
||||
case "OutputTOMDigitalChannel":
|
||||
OutputTOMDigitalChannel tom = new OutputTOMDigitalChannel();
|
||||
tom.ReadXml(reader);
|
||||
SetChannel(tom);
|
||||
break;
|
||||
default:
|
||||
AnalogInputDASChannel aic = new AnalogInputDASChannel();
|
||||
aic.ReadXml(reader);
|
||||
SetChannel(aic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reader.ReadEndElement();
|
||||
reader.ReadEndElement();
|
||||
}
|
||||
//
|
||||
// Summary:
|
||||
// Converts an object into its XML representation.
|
||||
//
|
||||
// Parameters:
|
||||
// writer:
|
||||
// The System.Xml.XmlWriter stream to which the object is serialized.
|
||||
public void WriteXml(XmlWriter writer)
|
||||
{
|
||||
//writer.WriteStartElement ( attributeExtractor.ExtractAttachedAttributeFromObject ( this
|
||||
writer.WriteStartElement("TDASModule");
|
||||
writer.WriteStartElement("SerialNumber");
|
||||
writer.WriteString(SerialNumber);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("TestId");
|
||||
writer.WriteString(TestId);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteStartElement("TestDescription");
|
||||
writer.WriteString(TestDescription);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("RecordingMode");
|
||||
writer.WriteString(RecordingMode.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("AAFilterRateHz");
|
||||
writer.WriteString(AAFilterRateHz.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("PreTriggerSeconds");
|
||||
writer.WriteString(PreTriggerSeconds.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("PostTriggerSeconds");
|
||||
writer.WriteString(PostTriggerSeconds.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("FirmwareVersion");
|
||||
writer.WriteString(FirmwareVersion);
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("MaxEventStorageSpaceInBytes");
|
||||
writer.WriteString(MaxEventStorageSpaceInBytes.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("ModuleArrayIndex");
|
||||
writer.WriteString(ModuleArrayIndex.ToString());
|
||||
writer.WriteEndElement();
|
||||
|
||||
writer.WriteStartElement("Channels");
|
||||
writer.Flush();
|
||||
|
||||
foreach (DASChannel channel in _channels.Values)
|
||||
{
|
||||
channel.WriteElementStart(writer);
|
||||
channel.WriteXml(writer);
|
||||
channel.WriteElementEnd(writer);
|
||||
writer.Flush();
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndElement();
|
||||
writer.Flush();
|
||||
}
|
||||
public virtual void WriteElementStart(XmlWriter writer)
|
||||
{
|
||||
writer.WriteStartElement("TDASModule");
|
||||
var tgt = GetType();
|
||||
writer.WriteAttributeString("xsi", "type", null, tgt.Name);
|
||||
}
|
||||
|
||||
public virtual void WriteElementEnd(XmlWriter writer)
|
||||
{
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
23
DataPRO/IService/Classes/TDAS/TDASServiceSetupInfo.cs
Normal file
23
DataPRO/IService/Classes/TDAS/TDASServiceSetupInfo.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class TDASServiceSetupInfo
|
||||
{
|
||||
public string SetupDescription { get; set; }
|
||||
public double? SamplesPerSecond { get; set; }
|
||||
public float HardwareFilterRateHz { get; set; }
|
||||
public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; }
|
||||
public bool? CheckoutMode { get; set; }
|
||||
|
||||
public TDASServiceSetupInfo(string setupDescription, double? samplesPerSecond, float hardwareFilterRateHz, DFConstantsAndEnums.RecordingMode recordingMode, bool? checkoutMode)
|
||||
{
|
||||
SetupDescription = setupDescription;
|
||||
SamplesPerSecond = samplesPerSecond;
|
||||
HardwareFilterRateHz = hardwareFilterRateHz;
|
||||
RecordingMode = recordingMode;
|
||||
CheckoutMode = checkoutMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
28
DataPRO/IService/Classes/TDAS/TDASServiceSetupInfoLookup.cs
Normal file
28
DataPRO/IService/Classes/TDAS/TDASServiceSetupInfoLookup.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// This is identical to TDASServiceSetupInfo except that the SamplesPerSecond and HardwareFilterRateHz
|
||||
/// are Dictionaries so that they can differ based on the DAS being used.
|
||||
/// </summary>
|
||||
public class TDASServiceSetupInfoLookup
|
||||
{
|
||||
public string SetupDescription { get; set; }
|
||||
public Dictionary<string, double> SamplesPerSecondLookup { get; set; }
|
||||
public Dictionary<string, float> HardwareFilterRateHzLookup { get; set; }
|
||||
public DFConstantsAndEnums.RecordingMode RecordingMode { get; set; }
|
||||
public bool? CheckoutMode { get; set; }
|
||||
|
||||
public TDASServiceSetupInfoLookup(string setupDescription, Dictionary<string, double> sampleRateLookup, Dictionary<string, float> aafLookup, DFConstantsAndEnums.RecordingMode recordingMode, bool? checkoutMode)
|
||||
{
|
||||
SetupDescription = setupDescription;
|
||||
SamplesPerSecondLookup = sampleRateLookup;
|
||||
HardwareFilterRateHzLookup = aafLookup;
|
||||
RecordingMode = recordingMode;
|
||||
CheckoutMode = checkoutMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
506
DataPRO/IService/Classes/TMTFile.cs
Normal file
506
DataPRO/IService/Classes/TMTFile.cs
Normal file
@@ -0,0 +1,506 @@
|
||||
using DTS.Common;
|
||||
using DTS.Common.Behaviors;
|
||||
using DTS.Common.Classes.Sensors;
|
||||
using DTS.Common.Classes.TMAT;
|
||||
using DTS.Common.DAS.Concepts;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.DASFactory;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.Enums.Sensors;
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using DTS.Common.Interface.DASFactory.Config;
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
using DTS.Common.Utilities.Logging;
|
||||
using DTS.DASLib.Command.SLICE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service.Classes
|
||||
{
|
||||
public interface ITmtFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the TMT file to the device
|
||||
/// </summary>
|
||||
void WriteTmtFile(IDASCommunication das, Dictionary<IDASCommunication, ushort> dataChannelIds, Dictionary<IDASCommunication, ushort> timeChannelIds, Dictionary<IDASCommunication, ushort> uartChannelIds, int dasIndex, ICommunication communication, float[] scaleFactors = null, float[] ranges = null, float[] measuredOffset = null);
|
||||
}
|
||||
//FB 25526 This class encapsulates the methods used in SLICE6AIR.cs before to intract with TMT files, the subclasses can support multiple types need like SLICE6AIR & TSRAIR
|
||||
public abstract class TmtFile : ITmtFile
|
||||
{
|
||||
protected TmtFile(string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults)
|
||||
{
|
||||
SerialNumber = serialNumber;
|
||||
DASInfo = dasInfo;
|
||||
ConfigData = configData;
|
||||
ChannelDiagnosticsResults = channelDiagnosticsResults;
|
||||
}
|
||||
|
||||
protected static ITMTTemplate GetTMTTemplate(TMAT_TEMPLATES tmat_TEMPLATES)
|
||||
{
|
||||
var tmtFileName = StringMetaDataAttr.GetStringMetaData(tmat_TEMPLATES);
|
||||
|
||||
var tokens = tmtFileName.Split(';');
|
||||
if ( tokens.Length == 2) { return GetSplitFile(tokens[0], tokens[1]); }
|
||||
|
||||
if (string.IsNullOrWhiteSpace(tmtFileName))
|
||||
{
|
||||
tmtFileName = "S6ATMTTemplate_PCM.tmt";
|
||||
}
|
||||
return GetTMTSingleFile(tmtFileName);
|
||||
}
|
||||
/// <summary>
|
||||
/// returns a single file template
|
||||
/// </summary>
|
||||
private static ITMTTemplate GetTMTSingleFile(string tmtFileName)
|
||||
{
|
||||
return new TmtSingleFile($"TMTTemplates/{tmtFileName}");
|
||||
}
|
||||
/// <summary>
|
||||
/// returns split file template
|
||||
/// </summary>
|
||||
private static ITMTTemplate GetSplitFile(string dasTemplate, string channelTemplate)
|
||||
{
|
||||
return new TmtSplitFile($"TMTTemplates/{dasTemplate}", $"TMTTemplates/{channelTemplate}");
|
||||
}
|
||||
|
||||
protected TMAT_TEMPLATES Template { get; set; }
|
||||
protected int MaxChannels { get; set; }
|
||||
protected string SerialNumber { get; set; }
|
||||
protected IInfoResult DASInfo { get; set; }
|
||||
protected IConfigurationData ConfigData { get; set; }
|
||||
protected IDiagnosticResult[] ChannelDiagnosticsResults { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// writes tmats file to the DASConfigs log directory, file is serial_TMT.txt
|
||||
/// </summary>
|
||||
protected static void WriteTMTFilePC(byte[] data, string testDirectory, string serialNumber)
|
||||
{
|
||||
const string dasConfigs = "DASConfigs";
|
||||
try
|
||||
{
|
||||
var fileName = Path.Combine(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), dasConfigs),
|
||||
$"{serialNumber}_TMT.txt");
|
||||
if (File.Exists(fileName)) { File.Delete(fileName); }
|
||||
File.WriteAllBytes(fileName, data);
|
||||
|
||||
//43789 Now, also write the file to the Data folder because the copy in the current directory gets overwritten every test
|
||||
fileName = Path.Combine(testDirectory);
|
||||
if (!Directory.Exists(fileName))
|
||||
{
|
||||
Directory.CreateDirectory(fileName);
|
||||
}
|
||||
fileName = Path.Combine(fileName, $"{serialNumber}_TMT.txt");
|
||||
File.WriteAllBytes(fileName, data);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
try
|
||||
{
|
||||
var fileName = Path.Combine(testDirectory, dasConfigs);
|
||||
if (!Directory.Exists(fileName))
|
||||
{
|
||||
Directory.CreateDirectory(fileName);
|
||||
}
|
||||
fileName = Path.Combine(fileName, $"{serialNumber}_TMT.txt");
|
||||
File.WriteAllBytes(fileName, data);
|
||||
}
|
||||
catch (Exception ex) { APILogger.Log(ex); }
|
||||
}
|
||||
|
||||
private static bool DoesChannelStreamUnsigned(AnalogInputDASChannel aic)
|
||||
{
|
||||
if (null == aic) { return true; }
|
||||
if (null == aic.OwningModule) { return true; }
|
||||
if (null == aic.OwningModule.OwningDAS) { return true; }
|
||||
switch (aic.OwningModule.OwningDAS.GetHardwareType())
|
||||
{
|
||||
case Common.Enums.Hardware.HardwareTypes.TSR_AIR_RevB:
|
||||
case Common.Enums.Hardware.HardwareTypes.SLICE6_AIR_TC: return false;
|
||||
default: return true;
|
||||
}
|
||||
}
|
||||
private static HashSet<HardwareTypes> _signedDAS = new HashSet<HardwareTypes>() { HardwareTypes.TSR_AIR, HardwareTypes.TSR_AIR_RevB, HardwareTypes.SLICE6_AIR_TC };
|
||||
private static bool GetIsSignedData(AnalogInputDASChannel aic)
|
||||
{
|
||||
if ( null == aic || null == aic.OwningModule || aic == aic.OwningModule.OwningDAS)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var type = aic.OwningModule.OwningDAS.GetHardwareType();
|
||||
if (_signedDAS.Contains(type)) { return true; }
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// writes a channel to the template in memory
|
||||
/// </summary>
|
||||
protected void UpdateTMTChannel(ITMTTemplate template, int channelIndex, float[] scaleFactors = null, float[] ranges = null, float[] measuredOffset = null)
|
||||
{
|
||||
var channelKeys = Enum.GetValues(typeof(TMTChannelKeys)).Cast<TMTChannelKeys>()
|
||||
.ToArray();
|
||||
|
||||
var number = (1 + channelIndex).ToString();
|
||||
var moduleArrayIndex = DASInfo.MapDASChannelNumber2ModuleArrayIndex(channelIndex);
|
||||
var moduleChannelIndex = DASInfo.MapDASChannelNumber2ModuleChannelNumber(channelIndex);
|
||||
var aidc = ConfigData.Modules[moduleArrayIndex].Channels[moduleChannelIndex] as AnalogInputDASChannel;
|
||||
var diagnosticResult =
|
||||
(from dr in ChannelDiagnosticsResults where dr.DASChannelNumber == channelIndex select dr)
|
||||
.FirstOrDefault();
|
||||
//this was throwing an exception for SLICE-TC, but it doesn't really need a datascaler
|
||||
//as the scale factor is always 1, so just create a new default scaler
|
||||
//note that I fixed diagnostics which may have fixed the lack of scaler with thermo channels too
|
||||
DataScaler scaler = new DataScaler();
|
||||
try
|
||||
{
|
||||
scaler = aidc.GetDataScaler();
|
||||
}
|
||||
catch( Exception ex) { APILogger.Log(ex); }
|
||||
|
||||
var tempEU = scaler.GetEU(short.MinValue);
|
||||
var tempEU2 = scaler.GetEU(short.MaxValue);
|
||||
var minEU = Math.Min(tempEU, tempEU2);
|
||||
var maxEU = Math.Max(tempEU, tempEU2);
|
||||
var channelName2 = TmtBase.TMT_LimitString(aidc.ChannelName2);
|
||||
var eu = RunTestVariables.MaskEUMetaData ? "---" : aidc.EngineeringUnits?.Trim() ?? "";
|
||||
var offsetEU = GetOffsetEUString(aidc, scaler, measuredOffset, channelIndex, diagnosticResult);
|
||||
var keys2 = Enum.GetValues(typeof(TMTChannelKeysEx)).Cast<TMTChannelKeysEx>();
|
||||
var adcToEUScalingFactor = 1D;
|
||||
if (scaleFactors != null && !RunTestVariables.MaskEUMetaData)
|
||||
{
|
||||
adcToEUScalingFactor = scaleFactors[channelIndex];
|
||||
}
|
||||
else if (!RunTestVariables.MaskEUMetaData)
|
||||
{
|
||||
adcToEUScalingFactor = scaler.GetAdcToEuScalingFactor();
|
||||
}
|
||||
|
||||
var isSigned = GetIsSignedData(aidc);
|
||||
foreach ( var key2 in keys2)
|
||||
{
|
||||
TmtBase.UpdateChannelField(key2, template, channelIndex, ranges, minEU, maxEU,
|
||||
eu, scaleFactors, adcToEUScalingFactor, channelName2, offsetEU, isSigned);
|
||||
}
|
||||
|
||||
foreach (var key in channelKeys)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case TMTChannelKeys.HardwareChannelNumber:
|
||||
template.UpdateValue(key, number, 1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.ChannelName:
|
||||
template.UpdateValue(key, channelName2, 1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.CouplingMode:
|
||||
var couplingMode = "D";
|
||||
if (aidc.CouplingMode == SensorConstants.CouplingModes.AC && aidc.IEPEChannel)
|
||||
{
|
||||
couplingMode = "A";
|
||||
}
|
||||
template.UpdateValue(key, couplingMode, 1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.BridgeResistance:
|
||||
if (null != diagnosticResult.BridgeResistance)
|
||||
{
|
||||
template.UpdateValue(key, ((double)diagnosticResult.BridgeResistance).ToString("F0"),
|
||||
1 + channelIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
template.UpdateValue(key, "0", 1 + channelIndex);
|
||||
}
|
||||
break;
|
||||
case TMTChannelKeys.AAF:
|
||||
template.UpdateValue(key, ConfigData.Modules[0].AAFilterRateHz.ToString("F0"),
|
||||
1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.OffsetMV:
|
||||
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ?
|
||||
"0" : ((short)diagnosticResult.FinalOffsetADC * diagnosticResult.ScalefactorMilliVoltsPerADC)
|
||||
.ToString("F2"),
|
||||
1 + channelIndex);
|
||||
|
||||
break;
|
||||
case TMTChannelKeys.InputRangeMV:
|
||||
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" : (diagnosticResult.ScalefactorMilliVoltsPerADC * ushort.MaxValue).ToString("F0"),
|
||||
1 + channelIndex);
|
||||
break;
|
||||
// Additional Max Range EU needed for C-1/MOT1 entry for Max input range EU
|
||||
case TMTChannelKeys.MaxRangeEU:
|
||||
if (ranges != null)
|
||||
{
|
||||
template.UpdateValue(key, ranges[channelIndex].ToString("F0"), 1 + channelIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" :
|
||||
maxEU.ToString("F0"), 1 + channelIndex);
|
||||
}
|
||||
break;
|
||||
case TMTChannelKeys.MinRangeEU:
|
||||
|
||||
if (ranges != null)
|
||||
{
|
||||
template.UpdateValue(key, (-1 * ranges[channelIndex]).ToString("F0"), 1 + channelIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
template.UpdateValue(key, RunTestVariables.MaskEUMetaData ? "1" :
|
||||
minEU.ToString("F0"), 1 + channelIndex);
|
||||
}
|
||||
break;
|
||||
case TMTChannelKeys.EU:
|
||||
template.UpdateValue(key,
|
||||
eu,
|
||||
1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.ScaleFactorEU:
|
||||
template.UpdateValue(key, adcToEUScalingFactor.ToString("F11"), 1 + channelIndex);
|
||||
break;
|
||||
case TMTChannelKeys.OffsetEU:
|
||||
{
|
||||
template.UpdateValue(key, offsetEU, 1 + channelIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// returns a string suitable for the TMATS file for the EU offset for a channel
|
||||
/// </summary>
|
||||
public static string GetOffsetEUString(AnalogInputDASChannel aidc, Common.DAS.Concepts.DataScaler scaler,
|
||||
float [] measuredOffset, int channelIndex, IDiagnosticResult diagnosticResult)
|
||||
{
|
||||
var isUnsigned = DoesChannelStreamUnsigned(aidc);
|
||||
var adcToEU = scaler.GetAdcToEuScalingFactor();
|
||||
|
||||
var midPointRemoval = 0;
|
||||
//FB15339 take the final offset ADC value and normalize it to zero rather than the ADC midpoint before converting to EU
|
||||
var offset = (scaler.GetEU((short)diagnosticResult.FinalOffsetADC) - midPointRemoval).ToString("F11");
|
||||
|
||||
if (aidc.ZeroMethod == ZeroMethodType.None)
|
||||
{
|
||||
//18806 & 44255
|
||||
//the above offset takes into consideration midpoint, initial EU, AND final offset
|
||||
//with none we don't want the final offset, but we want the midpoint and initial EU
|
||||
offset = (-1D * midPointRemoval + aidc.InitialEU).ToString("F11");
|
||||
}
|
||||
|
||||
AdjustOffsetForEUAtMv(ref offset, aidc, midPointRemoval, scaler, diagnosticResult);
|
||||
if (measuredOffset != null)
|
||||
{
|
||||
//we _do_ have a measured offset, but in the case of TSR AIR that's actually the EU
|
||||
//AND if we set return it as the offset it's going to double the reading ... this could be the same problem with TC
|
||||
//so lets just return 0 for signed das ...
|
||||
return isUnsigned ? measuredOffset[channelIndex].ToString() : "0.00";
|
||||
}
|
||||
else
|
||||
{
|
||||
return RunTestVariables.MaskEUMetaData ? "0" : offset;
|
||||
}
|
||||
}
|
||||
private static void AdjustOffsetForEUAtMv(ref string offset, AnalogInputDASChannel aidc, double midPointRemoval, Common.DAS.Concepts.DataScaler scaler,
|
||||
IDiagnosticResult diagnosticResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (null == aidc) { return; }
|
||||
if (null == scaler) { return; }
|
||||
|
||||
if (string.IsNullOrWhiteSpace(aidc.InitialOffset)) { return; }
|
||||
|
||||
var io = new InitialOffset();
|
||||
io.FromDbSerializeString(aidc.InitialOffset);
|
||||
if (io.Form != InitialOffsetTypes.EUAtMV) { return; }
|
||||
//DataScaler should take care of most of the work here, if we feed it in the final offset ADC it should adjust that by the eu@mv difference
|
||||
var eu = scaler.GetEU((short)diagnosticResult.FinalOffsetADC);
|
||||
offset = ( eu - midPointRemoval).ToString("F11");
|
||||
}
|
||||
catch( Exception ex)
|
||||
{
|
||||
APILogger.Log(ex);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes the TMT file to the S6A
|
||||
/// 14531 Implement TMATS support for S6A stream on boot
|
||||
/// </summary>
|
||||
public virtual void WriteTmtFile(IDASCommunication das, Dictionary<IDASCommunication, ushort> dataChannelIds, Dictionary<IDASCommunication, ushort> timeChannelIds,
|
||||
Dictionary<IDASCommunication, ushort> uartChannelIds, int dasIndex, ICommunication communication,
|
||||
float[] scaleFactors = null, float[] ranges = null, float[] measuredOffset = null)
|
||||
{
|
||||
if ( das is EthernetSlice6AirThermocoupler)
|
||||
{
|
||||
//temporary hack to allow all TC channels
|
||||
MaxChannels = 24;
|
||||
}
|
||||
var template = GetTMTTemplate(Template);
|
||||
var globalKeys = Enum.GetValues(typeof(TMTGlobalKeys)).Cast<TMTGlobalKeys>()
|
||||
.ToArray();
|
||||
// FB 26736 Get time & data channel Ids from dictionary based on serial
|
||||
ushort? dataChannelId = null;
|
||||
ushort? timeChannelId = null;
|
||||
ushort? uartChannelId = null;
|
||||
var dataChannelIdPair = dataChannelIds.FirstOrDefault(p => p.Key.SerialNumber == SerialNumber);
|
||||
|
||||
var bitsPerFrame = 32 + 16 * MaxChannels;
|
||||
if (dataChannelIdPair.Key != null)
|
||||
{
|
||||
dataChannelId = dataChannelIdPair.Value;
|
||||
if (dataChannelIdPair.Key.IsTSRAIR()) { bitsPerFrame = Constants.BITS_PER_MINOR_FRAME_TSRAIR; }
|
||||
}
|
||||
|
||||
var timeChannelIdPair = timeChannelIds.FirstOrDefault(p => p.Key.SerialNumber == SerialNumber);
|
||||
if (timeChannelIdPair.Key != null)
|
||||
{
|
||||
timeChannelId = timeChannelIdPair.Value;
|
||||
}
|
||||
|
||||
//FB43761
|
||||
var uartChannelIdPair = uartChannelIds.FirstOrDefault(p => p.Key.SerialNumber == SerialNumber);
|
||||
if (uartChannelIdPair.Key != null)
|
||||
{
|
||||
uartChannelId = uartChannelIdPair.Value;
|
||||
}
|
||||
|
||||
foreach (var key in globalKeys)
|
||||
{
|
||||
TmtSingleFile.UpdateGlobalField(das, key, template, ConfigData, SerialNumber, timeChannelId, dataChannelId, uartChannelId, dasIndex, bitsPerFrame);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MaxChannels; i++)
|
||||
{
|
||||
UpdateTMTChannel(template, i, scaleFactors, ranges, measuredOffset);
|
||||
}
|
||||
WriteTMTFile((ICommunication)das, template.GetAllLines(), das.TestDirectory);
|
||||
}
|
||||
public static void WriteTMTFile(ICommunication communication, string [] allLines,
|
||||
string testDirectory)
|
||||
{
|
||||
var sfd = new SetFileData(communication);
|
||||
var byteData = Encoding.UTF8.GetBytes(string.Join("\n", allLines));
|
||||
var maxFileSize = InformationCommands.MAX_FILE_LENGTH_ID100;
|
||||
if (communication is ITMATSStreamingDevice tmatsStreamer)
|
||||
{
|
||||
maxFileSize = tmatsStreamer.GetMaxFileLengthTMATS();
|
||||
}
|
||||
if (byteData.Length >= maxFileSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"TMT File is too large, {byteData.Length} >= {maxFileSize}");
|
||||
}
|
||||
|
||||
//15241 store uploaded TMATS file to DASConfigs folder
|
||||
WriteTMTFilePC(byteData, testDirectory, communication.SerialNumber);
|
||||
sfd.StartByteCount = 0;
|
||||
sfd.FileID = SetFileData.TMT_FILE_ID;
|
||||
|
||||
sfd.Data = Constants.XML_STORE_MAGIC_BYTES;
|
||||
sfd.SyncExecute();
|
||||
|
||||
//Store Header - data length
|
||||
var maxLen = Convert.ToUInt32(byteData.Length);
|
||||
sfd.StartByteCount = Constants.XML_HEADER_LENGTH / 2;
|
||||
sfd.FileID = SetFileData.TMT_FILE_ID;
|
||||
sfd.Data = BitConverter.GetBytes(maxLen);
|
||||
sfd.SyncExecute();
|
||||
|
||||
//Store Data
|
||||
for (uint i = 0; i < maxLen; i += (uint)sfd.MaximumFileStreamBytes)
|
||||
{
|
||||
long array_size = sfd.MaximumFileStreamBytes;
|
||||
if ((i + sfd.MaximumFileStreamBytes) > maxLen)
|
||||
{
|
||||
array_size = maxLen - i;
|
||||
}
|
||||
|
||||
var dataToSend = new byte[array_size];
|
||||
Array.Copy(byteData, i, dataToSend, 0, array_size);
|
||||
|
||||
sfd.Data = dataToSend;
|
||||
sfd.FileID = SetFileData.TMT_FILE_ID;
|
||||
sfd.StartByteCount = i + Constants.XML_HEADER_LENGTH;
|
||||
sfd.SyncExecute();
|
||||
}
|
||||
}
|
||||
//FB 30035 Refactored to create TmtFile object and return it based on profile
|
||||
/// <summary>
|
||||
/// returns a new template file object given a udp stream profile
|
||||
/// 29430 Store TMAT file that corresponds to Stream Profile
|
||||
/// </summary>
|
||||
/// <param name="profile"></param>
|
||||
/// <param name="serialNumber"></param>
|
||||
/// <param name="dasInfo"></param>
|
||||
/// <param name="configData"></param>
|
||||
/// <param name="channelDiagnosticsResults"></param>
|
||||
/// <returns></returns>
|
||||
public static ITmtFile GetS6ATMATSFileTypeForProfile(UDPStreamProfile profile, string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults)
|
||||
{
|
||||
switch (profile)
|
||||
{
|
||||
case UDPStreamProfile.CH10_ANALOG:
|
||||
case UDPStreamProfile.CH10_ANALOG_2HDR:
|
||||
return new Slice6AirAnalogTmtFile(serialNumber, dasInfo, configData, channelDiagnosticsResults);
|
||||
case UDPStreamProfile.CH10_PCM128_MM:
|
||||
case UDPStreamProfile.CH10_PCM_128BIT_2HDR:
|
||||
case UDPStreamProfile.CH10_PCM_STANDARD:
|
||||
case UDPStreamProfile.CH10_PCM_STANDARD_2HDR:
|
||||
case UDPStreamProfile.CH10_PCM_SUPERCOM:
|
||||
case UDPStreamProfile.CH10_PCM_SUPERCOM_2HDR:
|
||||
return new Slice6AirPcmTmtFile(serialNumber, dasInfo, configData, channelDiagnosticsResults);
|
||||
//FB 28292 "TmNS 144 bit PCM" and "TmNS Supercom 4x ADC PCM" profiles
|
||||
case UDPStreamProfile.TMNS_PCM_STANDARD:
|
||||
return new Slice6AirTmNs144PcmTmtFile(serialNumber, dasInfo, configData, channelDiagnosticsResults);
|
||||
case UDPStreamProfile.TMNS_PCM_SUPERCOM:
|
||||
return new Slice6AirTmNsSuperCom4XPcmTmtFile(serialNumber, dasInfo, configData, channelDiagnosticsResults);
|
||||
default:
|
||||
APILogger.Log($"GetTMATSTypeForProfile unsupported profile type: {profile}");
|
||||
return new Slice6AirAnalogTmtFile(serialNumber, dasInfo, configData, channelDiagnosticsResults);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public class Slice6AirAnalogTmtFile : TmtFile
|
||||
{
|
||||
public Slice6AirAnalogTmtFile(string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults) :
|
||||
base(serialNumber, dasInfo, configData, channelDiagnosticsResults)
|
||||
{
|
||||
MaxChannels = 6;
|
||||
Template = TMAT_TEMPLATES.S6Air_ANALOG;
|
||||
}
|
||||
}
|
||||
|
||||
public class Slice6AirPcmTmtFile : TmtFile
|
||||
{
|
||||
public Slice6AirPcmTmtFile(string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults) :
|
||||
base(serialNumber, dasInfo, configData, channelDiagnosticsResults)
|
||||
{
|
||||
MaxChannels = 6;
|
||||
Template = TMAT_TEMPLATES.S6Air_PCM;
|
||||
}
|
||||
}
|
||||
|
||||
public class Slice6AirTmNs144PcmTmtFile : TmtFile
|
||||
{
|
||||
public Slice6AirTmNs144PcmTmtFile(string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults) :
|
||||
base(serialNumber, dasInfo, configData, channelDiagnosticsResults)
|
||||
{
|
||||
MaxChannels = 6;
|
||||
Template = TMAT_TEMPLATES.S6Air_TmNS_144PPCM;
|
||||
}
|
||||
}
|
||||
|
||||
public class Slice6AirTmNsSuperCom4XPcmTmtFile : TmtFile
|
||||
{
|
||||
public Slice6AirTmNsSuperCom4XPcmTmtFile(string serialNumber, IInfoResult dasInfo, IConfigurationData configData, IDiagnosticResult[] channelDiagnosticsResults) :
|
||||
base(serialNumber, dasInfo, configData, channelDiagnosticsResults)
|
||||
{
|
||||
MaxChannels = 6;
|
||||
Template = TMAT_TEMPLATES.S6Air_TmNS_SuperCom4xPCM;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
35
DataPRO/IService/Classes/TOMModule.cs
Normal file
35
DataPRO/IService/Classes/TOMModule.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using DTS.Common.Interface.DASFactory;
|
||||
using System;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// Digital output channel.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TOMModule : DASModule
|
||||
{
|
||||
public enum TomTriggerType
|
||||
{
|
||||
NONE = 0, //module trigger type not known
|
||||
BUS_ONLY, //TOM will only by triggered by rack bus
|
||||
PANEL_ONLY, //TOM will only be triggered by pannel trigger
|
||||
BUS_PANEL //TOM will only be triggered when both the rack bus and panel are triggered
|
||||
}
|
||||
private TomTriggerType _triggerType;
|
||||
public TomTriggerType TriggerType
|
||||
{
|
||||
get => _triggerType;
|
||||
set => _triggerType = value;
|
||||
}
|
||||
|
||||
public TOMModule()
|
||||
{
|
||||
}
|
||||
|
||||
public TOMModule(int moduleArrayIdx, IDASCommunication _OwningDAS)
|
||||
: base(moduleArrayIdx, _OwningDAS)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
33
DataPRO/IService/Classes/TriggerCheckResult.cs
Normal file
33
DataPRO/IService/Classes/TriggerCheckResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
using DTS.Common.Interface.DASFactory.Diagnostics;
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class TriggerCheckResult : ITriggerCheckResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Is the status good on the DAS?
|
||||
/// </summary>
|
||||
public bool IsStatusGood { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the start record line currently active on the DAS?
|
||||
/// </summary>
|
||||
public bool IsStartRecordActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has the start record line been active at any point after arm?
|
||||
/// </summary>
|
||||
public bool HasStartRecordBeenActive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the trigger currently active?
|
||||
/// </summary>
|
||||
public bool IsTriggered { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has the trigger line been active at any point after arm?
|
||||
/// </summary>
|
||||
public bool HasTriggered { get; set; }
|
||||
}
|
||||
}
|
||||
270
DataPRO/IService/Classes/XMLHelper.cs
Normal file
270
DataPRO/IService/Classes/XMLHelper.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
|
||||
|
||||
namespace DTS.DASLib.Service
|
||||
{
|
||||
public class XMLHelper
|
||||
{
|
||||
public static System.Globalization.CultureInfo InvariantCulture = new System.Globalization.CultureInfo("");
|
||||
|
||||
public static string GetString(XmlReader reader)
|
||||
{
|
||||
if (reader.NodeType != XmlNodeType.Element)
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadElement: current node isn't an Element");
|
||||
}
|
||||
if (reader.IsEmptyElement)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
var thisName = reader.Name;
|
||||
if (!reader.Read())
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadElement: EOF");
|
||||
}
|
||||
if (reader.NodeType == XmlNodeType.EndElement) { return string.Empty; }
|
||||
if (reader.NodeType != XmlNodeType.Text)
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadElement: current Element doesn't have text");
|
||||
}
|
||||
var value = reader.Value;
|
||||
if (!reader.Read())
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadElement: EOF");
|
||||
}
|
||||
if (reader.NodeType != XmlNodeType.EndElement)
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadElement: current Element doesn't have an EndElement");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string TryGetString(XmlReader reader, string defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetString(reader);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static double GetDouble(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
double result;
|
||||
if (!double.TryParse(value, System.Globalization.NumberStyles.Float, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double TryGetDouble(XmlReader reader, double defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
double result;
|
||||
if (!double.TryParse(GetString(reader), System.Globalization.NumberStyles.Float, InvariantCulture, out result))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetFloat(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
float result;
|
||||
if (!float.TryParse(value, System.Globalization.NumberStyles.Float, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int GetInt(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
int result;
|
||||
if (!int.TryParse(value, System.Globalization.NumberStyles.Integer, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int TryGetInt(XmlReader reader, int defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
int result;
|
||||
if (!int.TryParse(GetString(reader), System.Globalization.NumberStyles.Integer, InvariantCulture, out result))
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// reads a long from xmlreader, throws an exception if there's an issue
|
||||
/// </summary>
|
||||
public static long GetInt64(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
long result;
|
||||
if (!long.TryParse(value, System.Globalization.NumberStyles.Integer, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static uint GetUInt(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
uint result;
|
||||
if (!uint.TryParse(value, System.Globalization.NumberStyles.Integer, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static UInt64 GetUInt64(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
UInt64 result;
|
||||
if (!UInt64.TryParse(value, System.Globalization.NumberStyles.Integer, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double? GetOptionalDouble(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
if (reader.HasAttributes)
|
||||
{
|
||||
var attr = reader.GetAttribute("xsi:nil");
|
||||
if (!string.IsNullOrEmpty(attr) && attr == "true")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
attr = reader.GetAttribute("nil");
|
||||
if (!string.IsNullOrEmpty(attr) && attr == "true") { return null; }
|
||||
}
|
||||
var value = GetString(reader);
|
||||
double result;
|
||||
if (!double.TryParse(value, System.Globalization.NumberStyles.Float, InvariantCulture, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool GetBool(XmlReader reader)
|
||||
{
|
||||
var elemName = reader.Name;
|
||||
var value = GetString(reader);
|
||||
bool result;
|
||||
if (!bool.TryParse(value, out result))
|
||||
{
|
||||
throw new XmlException("XMLHelper.ReadXml: invalid " + elemName + " " + value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void PutString(XmlWriter writer, string tag, string value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
writer.WriteString(value);
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public static void PutInt(XmlWriter writer, string tag, int value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
//if(value != null)
|
||||
{
|
||||
writer.WriteString(value.ToString(InvariantCulture));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
///<summary>
|
||||
/// writes a long to xml writer
|
||||
/// can throw exceptions
|
||||
/// </summary>
|
||||
public static void PutInt64(XmlWriter writer, string tag, long value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
writer.WriteString(value.ToString(InvariantCulture));
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
public static void PutUInt(XmlWriter writer, string tag, uint value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
//if(value != null)
|
||||
{
|
||||
writer.WriteString(value.ToString(InvariantCulture));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public static void PutUInt64(XmlWriter writer, string tag, UInt64 value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
writer.WriteString(value.ToString(InvariantCulture));
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public static void PutDouble(XmlWriter writer, string tag, double value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
writer.WriteString(value.ToString("G17", InvariantCulture));
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public static void PutOptionalDouble(XmlWriter writer, string tag, double? value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteAttributeString("xsi", "nil", null, "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteString(((double)value).ToString("G17", InvariantCulture));
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public static void PutBool(XmlWriter writer, string tag, bool value)
|
||||
{
|
||||
writer.WriteStartElement(tag);
|
||||
writer.WriteString(value.ToString(InvariantCulture));
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user