Files
DP44/DataPRO/IService/Classes/SLICEService/SLICE Service.Realtime.cs
2026-04-17 14:55:32 -04:00

924 lines
44 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using DTS.Common.ICommunication;
using DTS.DASLib.Command.SLICE;
using DTS.Common.Utilities.Logging;
using DTS.DASLib.Command;
using DTS.DASLib.Command.SLICE.RealtimeCommands;
using DTS.Common.Interface.Connection;
using DTS.Common.Enums.DASFactory;
using DTS.Common.Interface.DASFactory;
using System.Threading.Tasks;
using DTS.Common.Enums;
using DTS.Common.Classes.DASFactory;
namespace DTS.DASLib.Service
{
public partial class Slice<T> : Communication<T>,
IDASCommunication,
IConfigurationActions,
IDiagnosticsActions,
ITriggerCheckActions,
IRealTimeActions,
IArmActions,
IDownloadActions where T : IConnection, new()
{
#region Real time
public virtual bool ControlsDAQ() { return true; }
public virtual bool SupportsRealtime()
{
return !IsTOM();
}
public virtual bool SupportsMultipleEvents() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MultipleAndHybridEvents); }
public virtual bool SupportsMultipleConfigurations() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.MultipleConfigurations); }
public virtual bool SupportsAutoArm() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.AutoArm); }
public virtual bool SupportsLevelTrigger() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.LevelTrigger); }
public bool SupportsHardwareInputCheck() { return IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines); }
protected bool _bSupportsMultipleSampleRealtime = true;
public bool SupportsMultipleSampleRealtime() { return _bSupportsMultipleSampleRealtime; }
protected class RealTimeAsyncPacket
{
public SliceServiceAsyncInfo Info { get; set; }
public Timer Timer { get; set; }
public int SamplesPerSecond { get; set; }
public int MillisecBetweenSamples { get; set; }
public bool AllowMultipleSampleRealtime { get; set; }
public ManualResetEvent StopEvent { get; set; }
public byte[] Channels { get; set; }
public double AAF { get; set; }
public int minCallbackUpdateTimeMs { get; set; }
public bool UseUDPStreaming { get; set; } = false;
public int StreamPortOffset { get; set; }
public string HostIPAddress { get; set; } = IPAddress.Any.ToString();
}
protected class RealTimeTiltAsyncPacket
{
public SliceServiceAsyncInfo Info { get; set; }
public double[] TiltInDegrees { get; set; }
public ManualResetEvent StopEvent { get; set; }
}
// FB15313: Add UDP streaming options
protected class RealTimeUDPStreamProfileAsyncPacket
{
public SliceServiceAsyncInfo Info { get; set; }
public UDPStreamProfile Profile { get; set; }
public string UDPAddress { get; set; }
public ushort TimeDataChannelId { get; set; }
public uint[] TMNSConfig { get; set; }
public ushort DataChannelId { get; set; }
public ushort IRIGTimeDataPacketIntervalMs { get; set; }
}
void IRealTimeActions.RealTime(int samplesPerSecond,
int millisecBetweenSamples,
ServiceCallback callback,
object userData,
bool allowMultipleSampleRealtime,
int moduleIndex,
ManualResetEvent stopEvent,
byte[] channels,
double aaf,
int minCallbackUpdateTimeMs,
bool UseUDPStreaming,
string hostIPAddress)
{
var packet = new RealTimeAsyncPacket();
packet.StopEvent = stopEvent;
packet.Info = new SliceServiceAsyncInfo(callback, userData);
packet.MillisecBetweenSamples = millisecBetweenSamples;
packet.SamplesPerSecond = samplesPerSecond;
packet.AllowMultipleSampleRealtime = allowMultipleSampleRealtime;
packet.Channels = channels;
packet.AAF = aaf;
packet.minCallbackUpdateTimeMs = minCallbackUpdateTimeMs;
packet.UseUDPStreaming = UseUDPStreaming;
packet.StreamPortOffset = moduleIndex; // FB15388: udp ports must be unique, start index-0 unit at the default and iterate offset from there
packet.HostIPAddress = hostIPAddress;
LaunchAsyncWorker("Slice.RealTime", AsyncRealTime, packet);
}
void IRealTimeActions.RealTimePolling(ServiceCallback callback,
object userData,
ManualResetEvent stopEvent,
byte[] channels)
{
var packet = new RealTimeAsyncPacket
{
StopEvent = stopEvent,
Info = new SliceServiceAsyncInfo(callback, userData),
Channels = channels
};
LaunchAsyncWorker("Slice.RealtimePolling", AsyncRealTimePolling, packet);
}
/// <summary>
/// returns an object implementing IGetRealtimeSamples capable of returning realtime samples
/// </summary>
/// <param name="iCommunication"></param>
/// <param name="bPolling">whether realtime is polling or not</param>
/// <returns></returns>
protected virtual IGetRealtimeSamples GetRealtimeSamplesClass(DTS.Common.Interface.DASFactory.ICommunication iCommunication, bool bPolling = false)
{
return new GetRealtimeSamples(iCommunication, 2000, bPolling);
}
/// <summary>
/// indicates whether the DAS supports streaming
/// 10572 implement SW side for single command streaming realtime
/// </summary>
public virtual bool SupportsIndividualChannelRealtimeStreaming => false;
/// <summary>
/// indicates whether the das supports udp streaming
/// 15160 Port UDP Realtime Stream from FWTU
/// </summary>
public virtual bool SupportsUDPRealtimeStreaming => false;
/// <summary>
/// depending on firmware, some devices will send back all channels even if you request less while others will send back what's requested.
/// DataPRO is always expecting all channels to be returned. fix for these models is to always request all
/// 31829 Datapro s6air br shows noise in realtime view chart that is not real noise and does not show up in fwtu realtime or recorded
/// </summary>
/// <param name="packet"></param>
/// <returns></returns>
protected virtual byte[] GetRTChannelIndices(RealTimeAsyncPacket packet)
{
return packet.Channels;
}
/// <summary>
/// this is the minimum of time between data callbacks for realtime
/// this should be moved to the settings file, but it is fine here
/// for now since there is the ms between samples setting and
/// only the g8 and older firmware need to request samples at a fast rate
/// </summary>
//protected const int MIN_CALLBACK_UPDATE_TIME = 20;
private void AsyncRealTime(object asyncInfo)
{
var packet = asyncInfo as RealTimeAsyncPacket;
try
{
var ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.TriggerPolarity, (byte)(InvertTrigger ? 1 : 0), true);
ssaPolarity.SyncExecute();
ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.StartRecordPolarity, (byte)(InvertStart ? 1 : 0), true);
ssaPolarity.SyncExecute();
// Set sample rate and adjustable anti-alias filter frequency in the
// hardware based on the milliseconds between samples parameter that
// was passed in via the RealTimeAsyncPacket object. Keep the filter
// -3dB point at 1/5 the frequency of the sample rate.
// number of samples per second
var rtSampleRate = Convert.ToUInt32(packet.SamplesPerSecond);
var uiMillisecondsBetweenSamples = packet.MillisecBetweenSamples;
var setSampleRate = new SetRealtimeSampleRate(this);
setSampleRate.SetValue(rtSampleRate);
setSampleRate.SyncExecute();
var lastUpdate = DateTime.MinValue;
StreamReaderUDP streamReader = null;
if (SupportsIndividualChannelRealtimeStreaming)
{
try
{
var saa = new SetArmAttribute(this);
saa.SetValue(AttributeTypes.ArmAndEventAttributes.RealtimeAAFilterFrequencyHz,
Convert.ToSingle(packet.AAF), true);
saa.SyncExecute();
if (packet.UseUDPStreaming && SupportsUDPRealtimeStreaming)
{
//FB 18152 find the host ip
string dasIp;
string hostIpAddress = "";
if (Common.Utils.NetworkUtils.TryParseConnectionString(ConnectString, out dasIp))
{
hostIpAddress = Common.Utils.PingUtils.DasToHost[dasIp].HostIpAddress;
}
else
{ // We should not get here since SupportsUDPRealtimeStreaming is false for USB devices but just in case have a guard
APILogger.Log("Streaming realtime with UDP is not supported for USB devices.");
return;
}
var udpAddress = new UriBuilder(DFConstantsAndEnums.RealtimeUDPAddress);
udpAddress.Port += packet.StreamPortOffset;
streamReader = new StreamReaderUDP(udpAddress.Uri.AbsoluteUri, hostIpAddress, UDPStreamProfile.DTS_UDP, packet.Channels);
var startTimeStampRealtime = new StartTimeStampStreamMode(this);
startTimeStampRealtime.ParamsToSend = streamReader.cmdline.ToArray();
startTimeStampRealtime.SyncExecute();
}
else
{
var startRT = new StartRealtimeStreamingMode(this, GetRTChannelIndices(packet));
startRT.SyncExecute();
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
else
{
var startRT = new StartRealtimeMode(this);
startRT.SupportsMultipleSampleRealtime =
packet.AllowMultipleSampleRealtime && SupportsMultipleSampleRealtime();
startRT.SyncExecute();
}
var sampleNumbers = new List<ulong>(100);
var timeStamps = new List<ulong>(100);
var sequenceNumbers = new List<ulong>(100);
var data = new List<short[][]>(100);
// start calling for RT data
var getRTdata = GetRealtimeSamplesClass(this);
getRTdata.LogCommands = false;
var numChannels = 0;
foreach (var mod in DASInfo.Modules)
{
switch (mod.TypeOfModule)
{
case DFConstantsAndEnums.ModuleType.EmbeddedMicrophone:
case DFConstantsAndEnums.ModuleType.EmbeddedMagnetometer:
case DFConstantsAndEnums.ModuleType.EmbeddedMagnetInput:
case DFConstantsAndEnums.ModuleType.UART:
case DFConstantsAndEnums.ModuleType.StreamOut:
case DFConstantsAndEnums.ModuleType.StreamIn:
continue;
default:
numChannels += (int)mod.NumberOfChannels;
break;
}
}
getRTdata.Channels = (ushort)numChannels;
if (SerialNumber.StartsWith("SPD") || SerialNumber.StartsWith("SLD"))
{
if (getRTdata is RealtimeStreamingNextSamples cmd)
{
cmd.DigitalInput = true;
var transitions = new List<bool>();
foreach (var mod in ConfigData.Modules)
{
foreach (var channel in mod.Channels)
{
var aic = (AnalogInputDASChannel)channel;
switch (aic.DigitalMode)
{
case DigitalInputModes.CCNC:
case DigitalInputModes.CCNO:
transitions.Add(false);
break;
case DigitalInputModes.THL:
case DigitalInputModes.TLH:
transitions.Add(true);
break;
}
}
}
cmd.TransitionMode = transitions.ToArray();
}
}
while (!packet.StopEvent.WaitOne(0, false))
{
if (null != streamReader)
{
try
{
var udpPacket = streamReader.Read();
if (null != udpPacket)
{
data.Add(udpPacket.ChannelData);
sampleNumbers.Add(udpPacket.SampleNumber);
timeStamps.Add( /*Convert.ToUInt64(udpPacket.TimeStamp)*/0);
sequenceNumbers.Add(udpPacket.SequenceNumber);
var newData = new NewDataData(data.ToArray(), sampleNumbers.ToArray(),
timeStamps.ToArray(),
sequenceNumbers.ToArray());
Task.Run(() => { packet.Info.NewData(newData); });
sampleNumbers.Clear();
timeStamps.Clear();
sequenceNumbers.Clear();
data.Clear();
}
}
catch (SocketException sox) //FB15531: Don't silently consume realtime errors
{
//if it's a timeout it could just be that there's no data yet,
//give the device a chance to send data
if (sox.SocketErrorCode != SocketError.TimedOut)
{
throw sox;
}
}
catch (CommandException ce)
{
if (ce.Error == CommandErrorReason.ReceiveFailed ||
ce.Error == CommandErrorReason.SendFailed)
{
packet.Info.Error(ce.Message, new Common.Classes.Connection.NotConnectedException(ce.Message));
return;
}
//15909 Crash in Realtime when connection is lost
//in the case of a communication error in start realtime, notify consumer
packet.Info.Error(ce.Message, ce);
return;
}
catch (Common.Classes.Connection.NotConnectedException nce)
{
//15909 Crash in Realtime when connection is lost
//in the case of a communication error in start realtime, notify consumer
packet.Info.Error(nce.Message, nce);
return;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
else
{
// call HW to get RT samples
try
{
getRTdata.SyncExecute();
}
catch (CommandException ce)
{
if (ce.Error == CommandErrorReason.ReceiveFailed ||
ce.Error == CommandErrorReason.SendFailed)
{
packet.Info.Error(ce.Message, new Common.Classes.Connection.NotConnectedException(ce.Message));
return;
}
//15909 Crash in Realtime when connection is lost
//in the case of a communication error in start realtime, notify consumer
packet.Info.Error(ce.Message, ce);
return;
}
catch (Common.Classes.Connection.NotConnectedException nce)
{
//15909 Crash in Realtime when connection is lost
//in the case of a communication error in start realtime, notify consumer
packet.Info.Error(nce.Message, nce);
return;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
if (getRTdata.SamplesReturned > 0)
{
var rtData = new short[getRTdata.Channels][];
for (int idx = 0; idx < getRTdata.Channels; idx++)
{
rtData[idx] = getRTdata.GetChannelData(idx);
}
sampleNumbers.Add(getRTdata.SampleNumber);
timeStamps.Add(getRTdata.TimeStamp);
sequenceNumbers.Add(getRTdata.SequenceNumber);
data.Add(rtData);
}
if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds >= packet.minCallbackUpdateTimeMs)
{
lastUpdate = DateTime.Now;
if (!IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.StartRealtimeStream))
{
var ihl =
new InitializeHardwareLines(this, AbstractCommandBase.Default_IO_Timeout);
ihl.LogCommands = false;
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands
.InitHardwareInputLines) &&
!packet.StopEvent.WaitOne(0, false))
{
ihl.SyncExecute();
}
}
catch (Exception)
{
} //TODO: Where is an Exception?
var d1 = new short[1][];
d1[0] = new short[2];
d1[0][0] = (short)(ihl.StartRecordShorted ? 1 : 0);
d1[0][1] = (short)(ihl.TriggerInputShorted ? 1 : 0);
data.Add(d1);
sampleNumbers.Add(ulong.MaxValue);
timeStamps.Add(ulong.MinValue);
sequenceNumbers.Add(ulong.MinValue);
}
else
{
//Thread.Sleep(50);
}
ThreadPool.QueueUserWorkItem(packet.Info.NewData,
new NewDataData(data.ToArray(), sampleNumbers.ToArray(), timeStamps.ToArray(),
sequenceNumbers.ToArray()));
sampleNumbers.Clear();
timeStamps.Clear();
sequenceNumbers.Clear();
data.Clear();
}
}
Thread.Sleep(uiMillisecondsBetweenSamples);
}
var endRealtime = new EndRealtimeMode(this);
endRealtime.SyncExecute();
packet.Info.Success();
}
catch (CanceledException)
{
packet.Info.Cancel();
}
catch (Exception ex)
{
packet.Info.Error(ex.Message, ex);
}
}
private void AsyncRealTimePolling(object asyncInfo)
{
var packet = asyncInfo as RealTimeAsyncPacket;
try
{
var ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.TriggerPolarity, (byte)(InvertTrigger ? 1 : 0), true);
ssaPolarity.SyncExecute();
ssaPolarity = new SetSystemAttribute(this, AbstractCommandBase.Default_IO_Timeout);
ssaPolarity.SetValue(AttributeTypes.SystemAttributes.StartRecordPolarity, (byte)(InvertStart ? 1 : 0), true);
ssaPolarity.SyncExecute();
// Set sample rate and adjustable anti-alias filter frequency in the
// hardware based on the milliseconds between samples parameter that
// was passed in via the RealTimeAsyncPacket object. Keep the filter
// -3dB point at 1/5 the frequency of the sample rate.
// number of samples per second
var rtSampleRate = Convert.ToUInt32(50);
const int uiMillisecondsBetweenSamples = 200;
var setSampleRate = new SetRealtimeSampleRate(this);
setSampleRate.SetValue(rtSampleRate);
setSampleRate.SyncExecute();
DateTime lastUpdate = DateTime.MinValue;
// set RT mode in HW
var startRT = new StartRealtimeMode(this);
startRT.SupportsMultipleSampleRealtime = true;
startRT.SyncExecute();
var sampleNumbers = new List<ulong>(100);
var timeStamps = new List<ulong>(100);
var sequenceNumbers = new List<ulong>(100);
var data = new List<short[][]>(100);
// start calling for RT data
var getRTdata = GetRealtimeSamplesClass(this, true);
getRTdata.LogCommands = false;
getRTdata.Channels = (ushort)DASInfo.Modules.Sum(m => m.NumberOfChannels);
while (!packet.StopEvent.WaitOne(0, false))
{
// call HW to get RT samples
try
{
getRTdata.SyncExecute();
}
catch (Exception ex) { APILogger.Log(ex); }
if (getRTdata.SamplesReturned > 0)
{
var rtData = new short[getRTdata.Channels][];
for (var idx = 0; idx < getRTdata.Channels; idx++)
{
rtData[idx] = getRTdata.GetChannelData(idx);
}
sampleNumbers.Add(getRTdata.SampleNumber);
timeStamps.Add(getRTdata.TimeStamp);
sequenceNumbers.Add(getRTdata.SequenceNumber);
data.Add(rtData);
}
if (DateTime.Now.Subtract(lastUpdate).TotalMilliseconds >= packet.minCallbackUpdateTimeMs)
{
lastUpdate = DateTime.Now;
var ihl = new InitializeHardwareLines(this, AbstractCommandBase.Default_IO_Timeout);
ihl.LogCommands = false;
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.InitHardwareInputLines) && !packet.StopEvent.WaitOne(0, false))
{
ihl.SyncExecute();
}
}
catch (Exception ex) { APILogger.Log(ex); }
if (Common.Constants.CheckStatusLinesInRealtime)
{
var d1 = new short[1][];
d1[0] = new short[2];
d1[0][0] = (short)(ihl.StartRecordShorted ? 1 : 0);
d1[0][1] = (short)(ihl.TriggerInputShorted ? 1 : 0);
data.Add(d1);
sampleNumbers.Add(ulong.MaxValue);
}
//15244 Cannot run meter mode in realtime
timeStamps.Add(ulong.MinValue);
ThreadPool.QueueUserWorkItem(packet.Info.NewData, new NewDataData(data.ToArray(), sampleNumbers.ToArray(), timeStamps.ToArray(), sequenceNumbers.ToArray()));
sampleNumbers.Clear();
timeStamps.Clear();
sequenceNumbers.Clear();
data.Clear();
}
Thread.Sleep(uiMillisecondsBetweenSamples);
}
var exitRT = new EndRealtimeMode(this);
exitRT.SyncExecute();
packet.Info.Success();
}
catch (CanceledException)
{
packet.Info.Cancel();
}
catch (Exception ex)
{
packet.Info.Error(ex.Message, ex);
}
}
void IRealTimeActions.ExitRealTimeMode(ServiceCallback callback, object userData)
{
var info = new SliceServiceAsyncInfo(callback, userData);
LaunchAsyncWorker("Slice.ExitRealTimeMode", new WaitCallback(AsyncExitRealTimeMode), info);
}
private void AsyncExitRealTimeMode(object asyncInfo)
{
var info = asyncInfo as SliceServiceAsyncInfo;
if (!SupportsRealtime())
{
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false;// FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
info.Success();
return;
}
try
{
var exitRT = new EndRealtimeMode(this);
exitRT.SyncExecute();
if (null != DASArmStatus && RecordingModeExtensions.IsAStreamMode((DFConstantsAndEnums.RecordingMode)DASArmStatus.RecordingMode))
{
//for safety unset the auto arm flag in case the user reboots ...
DisAutoArm();
}
if (null != DASArmStatus) DASArmStatus.IsInRealtime = false; // FB15550: Update IsInRealtime flag if we exit RT so DataPRO is aware
info.Success();
}
catch (CanceledException)
{
info.Cancel();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
}
}
void IRealTimeActions.RealTimeTiltPolling(ServiceCallback callback,
object userData,
ManualResetEvent stopEvent)
{
var packet = new RealTimeTiltAsyncPacket();
packet.StopEvent = stopEvent;
packet.Info = new SliceServiceAsyncInfo(callback, userData);
LaunchAsyncWorker("Slice.RealTimeTiltPolling", AsyncRealTimeTiltPolling, packet);
}
private void AsyncRealTimeTiltPolling(object asyncInfo)
{
var packet = asyncInfo as RealTimeTiltAsyncPacket;
try
{
while (!packet.StopEvent.WaitOne(0, false))
{
var axisADCData = new short[3] { 0, 0, 0 };
var calFactor = new double[3] { 1, 1, 1 };
var zeroData = new double[3] { 0, 0, 0 };
// Get raw tilt ADC
var qtsd = new QueryTiltSensorData(this);
qtsd.DeviceID = 1;
qtsd.SyncExecute();
axisADCData[0] = qtsd.Channel1ValueAdc;
axisADCData[1] = qtsd.Channel2ValueAdc;
axisADCData[2] = qtsd.Channel3ValueAdc;
//Get tilt sensor scale factors
var scaleFactorGPerADC = new float[3] { 1, 1, 1 };
if (RunTestVariables.InRunTest && RunTestVariables.TiltSensorScaleFactor > 0)
{
scaleFactorGPerADC = new[]
{
RunTestVariables.TiltSensorScaleFactor, RunTestVariables.TiltSensorScaleFactor,
RunTestVariables.TiltSensorScaleFactor
};
}
else
{
try
{
var scaleFactorQuery = new QueryArmAttribute(this)
{
Key = AttributeTypes.ArmAndEventAttributes.InSliceTiltSensorScaleFactorGPerADC
};
scaleFactorQuery.SyncExecute();
scaleFactorGPerADC = scaleFactorQuery.Value as float[];
}
catch (Exception)
{
}
}
int dominantAxis = (axisADCData.Max() < Math.Abs(axisADCData.Min())) ?
Array.IndexOf(axisADCData, axisADCData.Min()) : Array.IndexOf(axisADCData, axisADCData.Max());
var query = new QuerySystemAttribute_BridgeSlice6(this);
query.DeviceID = 1;
try
{
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_1;
query.SyncExecute();
calFactor[0] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_7;
query.SyncExecute();
calFactor[1] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_13;
query.SyncExecute();
calFactor[2] = Convert.ToDouble(query.Value) == 0D ? 1D : Convert.ToDouble(query.Value);
}
catch { }
// Calculate Accel Data
var accelData = new double[3];
for (int i = 0; i < accelData.Length; i++)
{
var channel_2G = (axisADCData[i] / calFactor[i]) * scaleFactorGPerADC[i];
if (channel_2G > 1)
{
channel_2G = 1;
}
else if (channel_2G < -1)
{
channel_2G = -1;
}
accelData[i] = channel_2G;
}
bool positivePolarity = (axisADCData[dominantAxis] > 0);
switch (dominantAxis)
{
case 0:
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_2;
break;
case 1:
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_8;
break;
case 2:
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_14;
break;
default:
query.Key = AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_2;
break;
}
try
{
query.SyncExecute();
zeroData[dominantAxis] = Convert.ToDouble(query.Value);
}
catch { }
var query2 = new QuerySystemAttribute_BridgeSlice6(this);
query2.DeviceID = 1;
switch (dominantAxis)
{
case 0:
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_9 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_10;
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_15 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_16;
break;
case 1:
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_3 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_4;
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_17 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_18;
break;
case 2:
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_5 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_6;
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_11 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_12;
break;
default:
query.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_9 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_10;
query2.Key = positivePolarity ? AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_15 : AttributeTypes.SystemAttributes_BridgeSlice6.TILTSENSOR_CAL_16;
break;
}
try
{
query.SyncExecute();
query2.SyncExecute();
switch (dominantAxis)
{
case 0:
zeroData[1] = Convert.ToDouble(query.Value);
zeroData[2] = Convert.ToDouble(query2.Value);
break;
case 1:
zeroData[0] = Convert.ToDouble(query.Value);
zeroData[2] = Convert.ToDouble(query2.Value);
break;
case 2:
zeroData[0] = Convert.ToDouble(query.Value);
zeroData[1] = Convert.ToDouble(query2.Value);
break;
}
}
catch { }
// Calculate Tilt Data
var Sx = (axisADCData[0] - zeroData[0]) / calFactor[0];
var Sy = (axisADCData[1] - zeroData[1]) / calFactor[1];
var Sz = (axisADCData[2] - zeroData[2]) / calFactor[2];
var SG = Math.Sqrt(Math.Pow(Sx, 2) + Math.Pow(Sy, 2) + Math.Pow(Sz, 2));
var tiltInDegrees = new double[3];
tiltInDegrees[0] = (180.0 / Math.PI) * Math.Asin(Sx / SG);
tiltInDegrees[1] = (180.0 / Math.PI) * Math.Asin(Sy / SG);
tiltInDegrees[2] = (180.0 / Math.PI) * Math.Asin(Sz / SG);
TiltAxisData = tiltInDegrees.ToList();
ThreadPool.QueueUserWorkItem(packet.Info.NewData, new ServiceCallbackData.TiltNewData()
{
TiltData = tiltInDegrees,
AccelData = accelData,
});
}
packet.Info.Success();
}
catch (CanceledException)
{
packet.Info.Cancel();
}
catch (Exception ex)
{
packet.Info.Error(ex.Message, ex);
}
}
public string UDPStreamAddress
{
get;
private set;
}
// FB15313: Add UDP Streaming options
void IRealTimeActions.SetUDPStreamProfile(ServiceCallback callback, object userData,
UDPStreamProfile streamProfile, string udpAddress, ushort timeChannelId, ushort dataChannelId,
uint[] tmnsConfig, ushort irigTimeDataPacketIntervalMs)
{
var packet = new RealTimeUDPStreamProfileAsyncPacket()
{
Info = new SliceServiceAsyncInfo(callback, userData),
Profile = streamProfile,
UDPAddress = udpAddress,
TimeDataChannelId = timeChannelId,
DataChannelId = dataChannelId,
TMNSConfig = tmnsConfig,
IRIGTimeDataPacketIntervalMs = irigTimeDataPacketIntervalMs
};
LaunchAsyncWorker("Slice.SetUDPStreamProfile", AsyncSetUDPStreamProfile, packet);
}
private void AsyncSetUDPStreamProfile(object asyncInfo)
{
var packet = asyncInfo as RealTimeUDPStreamProfileAsyncPacket;
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream))
{
var rtUDPAddress = packet.UDPAddress;
var profile = (byte)packet.Profile;
var timeChannelId = packet.TimeDataChannelId;
var dataChannelId = packet.DataChannelId;
var tmnsConfig = new TMNSConfig(packet.TMNSConfig);
var udpAddress = new UriBuilder(rtUDPAddress);
byte[] tmp = Encoding.ASCII.GetBytes(udpAddress.Uri.AbsoluteUri.TrimEnd('/'));
byte[] ipport = new byte[28];
for (int i = 0; i < tmp.Length; i++)
{
ipport[i] = tmp[i];
}
var ssaUDPStreamProfile = new StreamConfigUDPSet(this, AbstractCommandBase.Default_IO_Timeout)
{
Stream_Profile_Number = profile,
Irig106Config0 = timeChannelId,
Irig106Config1 = dataChannelId,
TMNS_PCMSubFrameId = tmnsConfig.TMNS_PCMSubFrameId,
TMNS_MsgId = tmnsConfig.TMNS_MsgId,
TMNS_PCMMinorPerMajor = tmnsConfig.TMNS_PCMMinorPerMajor,
TMNS_TMATSPortNumber = tmnsConfig.TMNS_TMATSPortNumber,
IENAUDP_PortNumber = tmnsConfig.IENAUDP_PortNumber,
TMNS5 = tmnsConfig.TMNS5,
TMNS6 = tmnsConfig.TMNS6,
TMNS7 = tmnsConfig.TMNS7,
UdpIpPort = ipport
};
ssaUDPStreamProfile.SyncExecute();
UDPStreamAddress = udpAddress.Uri.AbsoluteUri.TrimEnd('/');
// FB15354: Enforce IRIG Time Data Packet Interval in order to read streaming data in NetView, etc.
var ssaIRIGTimeData = new SetSystemAttributeSLICE2(this, AbstractCommandBase.Default_IO_Timeout);
ssaIRIGTimeData.SetValue(AttributeTypes.SystemAttributesSLICE2.S6A_IrigTimeDataPacketIntervalMsec, packet.IRIGTimeDataPacketIntervalMs.ToString(), true);
ssaIRIGTimeData.SyncExecute();
}
packet.Info.Success();
}
catch (CanceledException)
{
packet.Info.Cancel();
}
catch (Exception ex)
{
packet.Info.Error(ex.Message, ex);
}
}
void IRealTimeActions.GetUDPStreamProfile(ServiceCallback callback, object userData)
{
var info = new SliceServiceAsyncInfo(callback, userData);
LaunchAsyncWorker("Slice.GetUDPStreamProfile", AsyncGetUDPStreamProfile, info);
}
private void AsyncGetUDPStreamProfile(object asyncInfo)
{
var info = asyncInfo as SliceServiceAsyncInfo;
try
{
if (IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands.UDPRealtimeStream))
{
var qsaUDPStreamProfile = new StreamConfigUDPGet(this, AbstractCommandBase.Default_IO_Timeout);
qsaUDPStreamProfile.SyncExecute();
var len = Array.IndexOf(qsaUDPStreamProfile.UdpIpPort, (byte)0x00);
UDPStreamAddress = Encoding.ASCII.GetString(qsaUDPStreamProfile.UdpIpPort, 0, len < 0 ? qsaUDPStreamProfile.UdpIpPort.Length : len);
}
info.Success();
}
catch (CanceledException)
{
info.Cancel();
}
catch (Exception ex)
{
info.Error(ex.Message, ex);
}
}
#endregion
}
}