This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View 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;
}
}
}

View 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; }
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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();
}
}
}

View 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
}
}
}

View 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();
}
}
}

View 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();
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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();
}
}
}

View 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()
{
}
}
}

View 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;
}
}
}
}
}

View 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; } = "";
}
}

View 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()
{
}
}
}

View 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()
{
}
}
}

View 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()
{
}
}
}

View 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
}
}

View 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);
}
}
}

View 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;
}
}
}
}
}

View 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;
}
}
}
}
}

View 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();
}
}
}

View 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;
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
namespace DTS.DASLib.Service
{
public abstract class ConfigurationConstants
{
public enum VerifyConfig_Errors
{
DefaultHardwareFilterRateOutOfRange
}
}
}

View 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";
}
}

View 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;
}
}
}

View 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);
}
}
}
}

View 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; }
}
}

View 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
}
}
}
}

View 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; }
}
}

View 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);
}
}
}
}

View 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);
}
}
}
}

View 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);
}
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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) { }
}
}

View 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; }
}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}

View 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; }
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}
}

File diff suppressed because it is too large Load Diff

View 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;
}
}
}

View 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; } }
}
}

View 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;
}
}
}
}

View 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];
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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;
}
}
}

View 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 };
}
}
}
}

File diff suppressed because it is too large Load Diff

View 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
}
}

View 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;
}
}
}

View 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
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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
}

View 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
}
}

View File

@@ -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
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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; }
}
}

View File

@@ -0,0 +1,13 @@
namespace DTS.DASLib.Service
{
public class StaticInformation
{
public readonly double[] NominalRanges;
public StaticInformation(double[] _NominalRanges)
{
NominalRanges = _NominalRanges;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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
}
*/
}
}

File diff suppressed because it is too large Load Diff

View 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
}
}

View 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
}

View 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
}
}

View 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();
}
}
}

View 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
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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)
{
}
}
}

View 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; }
}
}

View 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();
}
}
}