init
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user