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 : Communication, 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 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); } /// /// returns an object implementing IGetRealtimeSamples capable of returning realtime samples /// /// /// whether realtime is polling or not /// protected virtual IGetRealtimeSamples GetRealtimeSamplesClass(DTS.Common.Interface.DASFactory.ICommunication iCommunication, bool bPolling = false) { return new GetRealtimeSamples(iCommunication, 2000, bPolling); } /// /// indicates whether the DAS supports streaming /// 10572 implement SW side for single command streaming realtime /// public virtual bool SupportsIndividualChannelRealtimeStreaming => false; /// /// indicates whether the das supports udp streaming /// 15160 Port UDP Realtime Stream from FWTU /// public virtual bool SupportsUDPRealtimeStreaming => false; /// /// 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 /// /// /// protected virtual byte[] GetRTChannelIndices(RealTimeAsyncPacket packet) { return packet.Channels; } /// /// 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 /// //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(100); var timeStamps = new List(100); var sequenceNumbers = new List(100); var data = new List(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(); 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(100); var timeStamps = new List(100); var sequenceNumbers = new List(100); var data = new List(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 } }