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

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