Ejemplo n.º 1
0
        /// <summary>
        /// Creates a new <see cref="DataGapRecoverer"/>.
        /// </summary>
        public DataGapRecoverer()
        {
            Log = Logger.CreatePublisher(GetType(), MessageClass.Framework);
            Log.InitialStackMessages = Log.InitialStackMessages.Union("ComponentName", GetType().Name);

            m_dataGapRecoveryCompleted = new ManualResetEventSlim(true);

            m_recoveryStartDelay  = DefaultRecoveryStartDelay;
            m_minimumRecoverySpan = DefaultMinimumRecoverySpan;
            m_maximumRecoverySpan = DefaultMaximumRecoverySpan;
            StartRecoveryBuffer   = DefaultStartRecoveryBuffer;
            EndRecoveryBuffer     = DefaultEndRecoveryBuffer;

            string loggingPath = FilePath.GetDirectoryName(FilePath.GetAbsolutePath(DataSubscriber.DefaultLoggingPath));

            if (Directory.Exists(loggingPath))
            {
                m_loggingPath = loggingPath;
            }

            m_subscriptionInfo = new UnsynchronizedSubscriptionInfo(false);
            m_subscriptionInfo.FilterExpression         = DefaultFilterExpression;
            m_subscriptionInfo.ProcessingInterval       = DefaultRecoveryProcessingInterval;
            m_subscriptionInfo.UseMillisecondResolution = DefaultUseMillisecondResolution;

            m_dataStreamMonitor           = Common.TimerScheduler.CreateTimer((int)(DefaultDataMonitoringInterval * 1000.0D));
            m_dataStreamMonitor.Elapsed  += DataStreamMonitor_Elapsed;
            m_dataStreamMonitor.AutoReset = true;
            m_dataStreamMonitor.Enabled   = false;
        }
Ejemplo n.º 2
0
        public void SubscribeUnsynchronizedData(bool historical)
        {
            UnsynchronizedSubscriptionInfo info;

            if (m_unsynchronizedSubscriber == null)
            {
                InitializeUnsynchronizedSubscription();
            }

            if (m_subscribedUnsynchronized && !string.IsNullOrEmpty(m_allSignalIDs))
            {
                info = new UnsynchronizedSubscriptionInfo(true);

                info.UseCompactMeasurementFormat = true;
                info.FilterExpression            = m_allSignalIDs;
                info.IncludeTime     = true;
                info.LagTime         = 60.0D;
                info.LeadTime        = 60.0D;
                info.PublishInterval = m_refreshInterval;

                if (historical)
                {
                    info.StartTime          = StartTime;
                    info.StopTime           = StopTime;
                    info.ProcessingInterval = m_refreshInterval * 1000;
                }

                m_unsynchronizedSubscriber.Subscribe(info);
            }

            if (m_statistics == null)
            {
                Application.Current.Dispatcher.BeginInvoke(new Action(() => Statistics = new RealTimeStatistics(1, m_statisticRefreshInterval)));
            }
        }
Ejemplo n.º 3
0
        private void InitiateSubscribe()
        {
            bool hasInputIDs  = m_inputSignalIDs?.Length > 0;
            bool hasOutputIDs = m_outputSignalIDs?.Length > 0;

            if (!hasInputIDs && !hasOutputIDs)
            {
                return;
            }

            HashSet <Guid> signalIDs = new HashSet <Guid>();

            if (hasInputIDs)
            {
                signalIDs.UnionWith(m_inputSignalIDs);
            }

            if (hasOutputIDs)
            {
                signalIDs.UnionWith(m_outputSignalIDs);
            }

            UnsynchronizedSubscriptionInfo subscription = (UnsynchronizedSubscriptionInfo)m_throttledSubscription.Copy();

            subscription.FilterExpression = string.Join(";", signalIDs);

            QueueSubscriberOperation(() =>
            {
                m_lastRefresh = 0L;
                m_subscriber.UnsynchronizedSubscribe(subscription);
            });
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Creates a new <see cref="DataReceiver"/> instance with the specified <paramref name="connectionString"/>.
        /// </summary>
        /// <param name="connectionString">GEP connection string for openHistorian.</param>
        /// <param name="filterExpression">Filter expression defining measurements to query.</param>
        /// <param name="startTime">Temporal subscription start time.</param>
        /// <param name="stopTime">Temporal subscription stop time.</param>
        public DataReceiver(string connectionString, string filterExpression, DateTime startTime, DateTime stopTime)
        {
            m_subscriber = new DataSubscriber
            {
                ConnectionString = connectionString,
                OperationalModes = OperationalModes.UseCommonSerializationFormat | OperationalModes.CompressPayloadData,
                CompressionModes = CompressionModes.TSSC
            };

            m_subscriptionInfo = new UnsynchronizedSubscriptionInfo(false)
            {
                FilterExpression         = filterExpression,
                StartTime                = startTime.ToString(TimeTagBase.DefaultFormat),
                StopTime                 = stopTime.ToString(TimeTagBase.DefaultFormat),
                ProcessingInterval       = 0, // Zero value requests data as fast as possible
                UseMillisecondResolution = true
            };

            // Attach to needed subscriber events
            m_subscriber.ConnectionEstablished += m_subscriber_ConnectionEstablished;
            m_subscriber.NewMeasurements       += m_subscriber_NewMeasurements;
            m_subscriber.StatusMessage         += m_subscriber_StatusMessage;
            m_subscriber.ProcessException      += m_subscriber_ProcessException;
            m_subscriber.ProcessingComplete    += m_subscriber_ProcessingComplete;

            // Initialize the subscriber
            m_subscriber.Initialize();

            // Start subscriber connection cycle
            m_subscriber.Start();
        }
Ejemplo n.º 5
0
        private void InitializeDataSubscriber()
        {
            m_throttledSubscription = new UnsynchronizedSubscriptionInfo(true)
            {
                LagTime         = 10.0D,
                LeadTime        = 10.0D,
                PublishInterval = 0.5D
            };

            m_subscriber = new DataSubscriber
            {
                ConnectionString = $"server=localhost:{Program.GetGEPPort()}",
                CompressionModes = CompressionModes.TSSC | CompressionModes.GZip,
                OperationalModes = OperationalModes.UseCommonSerializationFormat | OperationalModes.CompressMetadata | OperationalModes.CompressSignalIndexCache | OperationalModes.CompressPayloadData
            };

            m_subscriber.StatusMessage              += Subscriber_StatusMessage;
            m_subscriber.ProcessException           += Subscriber_ProcessException;
            m_subscriber.ConnectionEstablished      += Subscriber_ConnectionEstablished;
            m_subscriber.ConnectionTerminated       += Subscriber_ConnectionTerminated;
            m_subscriber.NewMeasurements            += Subscriber_NewMeasurements;
            m_subscriber.ServerConfigurationChanged += Subscriber_ServerConfigurationChanged;

            m_subscriber.Initialize();
            m_subscriber.Start();
        }
Ejemplo n.º 6
0
        private void DataSubscriber_MetaDataReceived(object sender, EventArgs <DataSet> args)
        {
            UnsynchronizedSubscriptionInfo subscriptionInfo = new UnsynchronizedSubscriptionInfo(false);

            m_concentrator.Mapper.CrunchMetadata(args.Argument);
            subscriptionInfo.FilterExpression = m_concentrator.Mapper.FilterExpression;
            m_dataSubscriber.Subscribe(subscriptionInfo);
        }
 /// <summary>
 /// Creates a new <see cref="DataSubscriptionHubClient"/> instance.
 /// </summary>
 public DataSubscriptionHubClient()
 {
     m_statisticSubscriptionInfo = new UnsynchronizedSubscriptionInfo(false);
     m_dataSubscriptionInfo      = new UnsynchronizedSubscriptionInfo(false);
     m_measurements       = new List <MeasurementValue>();
     m_statistics         = new List <MeasurementValue>();
     m_statusLights       = new List <StatusLight>();
     m_deviceDetails      = new List <DeviceDetail>();
     m_measurementDetails = new List <MeasurementDetail>();
     m_phasorDetails      = new List <PhasorDetail>();
     m_schemaVersion      = new List <SchemaVersion>();
     m_measurementLock    = new object();
 }
Ejemplo n.º 8
0
        private void DataSubscriber_MetaDataReceived(object sender, EventArgs <DataSet> args)
        {
            UnsynchronizedSubscriptionInfo subscriptionInfo = new UnsynchronizedSubscriptionInfo(false);
            SignalLookup lookup = m_concentrator.Mapper.Lookup;

            m_concentrator.Mapper.CrunchMetadata(args.Argument);

            subscriptionInfo.FilterExpression = string.Join(";", SystemSettings.FilterExpressions
                                                            .SelectMany(expression => lookup.GetMeasurementKeys(expression))
                                                            .Select(key => key.SignalID)
                                                            .Distinct());

            m_dataSubscriber.Subscribe(subscriptionInfo);
        }
Ejemplo n.º 9
0
        static void Main()
        {
            Logger.Console.Verbose = VerboseLevel.All;
            Logger.FileWriter.SetPath(@"C:\temp\SttpLogs");
            Logger.FileWriter.Verbose = VerboseLevel.All;
            var subscriber = new DataSubscriber();

            subscriber.StatusMessage    += Subscriber_StatusMessage;
            subscriber.MetaDataReceived += SubscriberOnMetaDataReceived;
            subscriber.ProcessException += SubscriberOnProcessException;
            subscriber.NewMeasurements  += Subscriber_NewMeasurements;
            subscriber.ConnectionString  = "server=phasor2:6170";
            subscriber.OperationalModes |= OperationalModes.UseCommonSerializationFormat | OperationalModes.CompressMetadata | OperationalModes.CompressSignalIndexCache | OperationalModes.CompressPayloadData;
            subscriber.CompressionModes  = CompressionModes.TSSC | CompressionModes.GZip;
            subscriber.Initialize();
            subscriber.Start();
            subscriber.MeasurementReportingInterval = 1_000_000;
            subscriber.ConnectionEstablished       += Subscriber_ConnectionEstablished;
            m_wait.WaitOne();
            Thread.Sleep(1000);

            subscriber.RefreshMetadata();
            var si = new UnsynchronizedSubscriptionInfo(false);

            si.FilterExpression = "FILTER ActiveMeasurements WHERE ID IS NOT NULL";
            subscriber.Subscribe(si);

            m_wait.WaitOne();

            //var pub = new SttpPublisher();
            //pub.DataSource = m_metadata;
            //pub.Initialize();
            //pub.Start();
            //m_publisher = pub;

            throw new NotImplementedException();
            //var net = new CtpClient();
            //net.SetHost(GetMyIPV4(), 48294);
            //net.SetUserCredentials("TrialUser", "P@$$w0rd");
            //net.Connect();
            //var sub = new SttpClient(net);
            //Console.WriteLine(string.Join(Environment.NewLine, sub.GetMetaDataTableList()));

            //Console.ReadLine();
            //pub.Stop();
            //subscriber.Unsubscribe();
            //subscriber.Stop();
            //Console.ReadLine();
        }
Ejemplo n.º 10
0
        public void SubscribeUnsynchronizedData(bool historical)
        {
            UnsynchronizedSubscriptionInfo info;

            if (m_unsynchronizedSubscriber == null)
            {
                InitializeUnsynchronizedSubscription();
            }

            if (m_subscribedUnsynchronized && !string.IsNullOrEmpty(m_allSignalIDs))
            {
                double lagTime;
                double leadTime;

                if (!double.TryParse(IsolatedStorageManager.ReadFromIsolatedStorage("LagTime")?.ToString(), out lagTime))
                {
                    lagTime = 60.0D;
                }

                if (!double.TryParse(IsolatedStorageManager.ReadFromIsolatedStorage("LeadTime")?.ToString(), out leadTime))
                {
                    leadTime = 60.0D;
                }

                info = new UnsynchronizedSubscriptionInfo(true);

                info.UseCompactMeasurementFormat = true;
                info.FilterExpression            = m_allSignalIDs;
                info.IncludeTime             = true;
                info.UseLocalClockAsRealTime = IsolatedStorageManager.ReadFromIsolatedStorage("UseLocalClockAsRealTime").ToNonNullString("true").ParseBoolean();
                info.LagTime         = lagTime;
                info.LeadTime        = leadTime;
                info.PublishInterval = m_refreshInterval;

                if (historical)
                {
                    info.StartTime          = StartTime;
                    info.StopTime           = StopTime;
                    info.ProcessingInterval = m_refreshInterval * 1000;
                }

                m_unsynchronizedSubscriber.Subscribe(info);
            }

            if (m_statistics == null)
            {
                Application.Current.Dispatcher.BeginInvoke(new Action(() => Statistics = new RealTimeStatistics(1, m_statisticRefreshInterval)));
            }
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Creates a new <see cref="DataSubscriptionHubClient"/> instance.
 /// </summary>
 public DataSubscriptionHubClient()
 {
     m_statisticSubscriptionInfo = new UnsynchronizedSubscriptionInfo(false);
     m_dataSubscriptionInfo      = new UnsynchronizedSubscriptionInfo(false);
     m_measurements       = new List <MeasurementValue>();
     m_statistics         = new List <MeasurementValue>();
     m_statusLights       = new List <StatusLight>();
     m_deviceDetails      = new List <DeviceDetail>();
     m_measurementDetails = new List <MeasurementDetail>();
     m_phasorDetails      = new List <PhasorDetail>();
     m_schemaVersion      = new List <SchemaVersion>();
     m_measurementLock    = new object();
     using (AdoDataConnection conn = new AdoDataConnection("securityProvider"))
     {
         int index = conn.ExecuteScalar <int>("Select ID FROM ValueListGroup WHERE Name = 'ModbusSubscriptions'");
         m_connectionString = conn.ExecuteScalar <string>("Select Text FROM ValueList WHERE GroupID = {0} AND IsDefault = 1", index);
     }
 }
Ejemplo n.º 12
0
    // Subscribes or resubscribes to real-time or historical stream using current filter expression
    private void InitiateSubscription(bool historical)
    {
        if (m_subscribed || m_historicalSubscription)
        {
            m_subscriber.Unsubscribe();
            ClearSubscription();
        }

        m_historicalSubscription = historical;

        UnsynchronizedSubscriptionInfo subscriptionInfo;

        subscriptionInfo = new UnsynchronizedSubscriptionInfo(false);
        subscriptionInfo.FilterExpression = m_filterExpression;

        if (historical)
        {
            subscriptionInfo.StartTime          = m_startTime;
            subscriptionInfo.StopTime           = m_stopTime;
            subscriptionInfo.ProcessingInterval = m_processInterval;
            UpdateStatus("*** Starting historical replay at {0} playback speed ***", m_processInterval == 0 ? "fast as possible" : m_processInterval + "ms");
        }

        // Attempt to extract possible data channel setting from connection string.
        // For example, adding "; dataChannel={port=9191}" to the connection string
        // would request that the data publisher send data to the subscriber over
        // UDP on port 9191. Technically this is part of the subscription info but
        // we allow this definition in the connection string for this application.
        string dataChannel = null;

        if (!string.IsNullOrEmpty(m_connectionString))
        {
            Dictionary <string, string> settings = m_connectionString.ParseKeyValuePairs();
            settings.TryGetValue("dataChannel", out dataChannel);
        }

        if ((object)dataChannel != null)
        {
            subscriptionInfo.ExtraConnectionStringParameters = "dataChannel={" + dataChannel + "}";
        }

        m_subscriber.UnsynchronizedSubscribe(subscriptionInfo);
    }
Ejemplo n.º 13
0
        /// <summary>
        /// Creates a new instance of the <see cref="AlarmMonitor"/> class.
        /// </summary>
        /// <param name="singleton">Indicates whether this instance should update the global reference to become the singleton.</param>
        public AlarmMonitor(bool singleton = false)
        {
            object refreshInterval = IsolatedStorageManager.ReadFromIsolatedStorage("AlarmStatusRefreshInterval") ?? DefaultRefreshInterval;

            if (!int.TryParse(refreshInterval.ToString(), out m_refreshInterval))
            {
                m_refreshInterval = DefaultRefreshInterval;
            }

            m_currentAlarmsLock = new object();
            m_currentAlarms     = new HashSet <Alarm>();

            m_refreshTimer          = new Timer(m_refreshInterval * 1000);
            m_refreshTimer.Elapsed += RefreshTimer_Elapsed;

            m_alarmStatusQuery = new AlarmStatusQuery();
            m_alarmStatusQuery.RaisedAlarmStates += m_alarmStatusQuery_RaisedAlarmStates;
            m_alarmStatusQuery.ProcessException  += m_alarmStatusQuery_ProcessException;

            // Load all alarms defined in the database
            UpdateDefinedAlarms();

            // Setup subscription to subscribe to all alarm measurements
            m_subscriptionInfo = new UnsynchronizedSubscriptionInfo(false)
            {
                FilterExpression = "FILTER ActiveMeasurements WHERE SignalType='ALRM'"
            };

            m_dataSubscriber = new DataSubscriber();
            m_dataSubscriber.ConnectionEstablished  += m_dataSubscriber_ConnectionEstablished;
            m_dataSubscriber.ReceivedServerResponse += m_dataSubscriber_ReceivedServerResponse;
            m_dataSubscriber.NewMeasurements        += m_dataSubscriber_NewMeasurements;
            m_dataSubscriber.ProcessException       += m_dataSubscriber_ProcessException;
            m_dataSubscriber.ConnectionString        = GetDataPublisherConnectionString();
            m_dataSubscriber.OperationalModes       |= OperationalModes.UseCommonSerializationFormat | OperationalModes.CompressSignalIndexCache | OperationalModes.CompressPayloadData;
            m_dataSubscriber.DataLossInterval        = -1;
            m_dataSubscriber.Initialize();

            if (singleton)
            {
                Default = this;
            }
        }
Ejemplo n.º 14
0
        private void SubscribeUnsynchronizedData()
        {
            UnsynchronizedSubscriptionInfo info;

            if (m_unsynchronizedSubscriber == null)
            {
                InitializeUnsynchronizedSubscription();
            }

            if (m_subscribedUnsynchronized && !string.IsNullOrEmpty(m_allSignalIDs))
            {
                info = new UnsynchronizedSubscriptionInfo(false);

                info.UseCompactMeasurementFormat = true;
                info.FilterExpression            = m_allSignalIDs;
                info.IncludeTime     = true;
                info.LagTime         = 60.0D;
                info.LeadTime        = 60.0D;
                info.PublishInterval = m_statisticDataRefreshInterval;

                m_unsynchronizedSubscriber.UnsynchronizedSubscribe(info);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Subscribes (or re-subscribes) to a data publisher for an unsynchronized set of data points.
        /// </summary>
        /// <param name="info">Configuration object that defines the subscription.</param>
        /// <returns><c>true</c> if subscribe transmission was successful; otherwise <c>false</c>.</returns>
        public bool UnsynchronizedSubscribe(UnsynchronizedSubscriptionInfo info)
        {
            // Dispose of any previously established local concentrator
            DisposeLocalConcentrator();

            StringBuilder connectionString = new StringBuilder();
            AssemblyInfo assemblyInfo = AssemblyInfo.ExecutingAssembly;

            connectionString.AppendFormat("trackLatestMeasurements={0};", info.Throttled);
            connectionString.AppendFormat("publishInterval={0};", info.PublishInterval);
            connectionString.AppendFormat("includeTime={0};", info.IncludeTime);
            connectionString.AppendFormat("lagTime={0};", info.LagTime);
            connectionString.AppendFormat("leadTime={0};", info.LeadTime);
            connectionString.AppendFormat("useLocalClockAsRealTime={0};", info.UseLocalClockAsRealTime);
            connectionString.AppendFormat("processingInterval={0};", info.ProcessingInterval);
            connectionString.AppendFormat("useMillisecondResolution={0};", info.UseMillisecondResolution);
            connectionString.AppendFormat("assemblyInfo={{source={0};version={1}.{2}.{3};buildDate={4}}};", assemblyInfo.Name, assemblyInfo.Version.Major, assemblyInfo.Version.Minor, assemblyInfo.Version.Build, assemblyInfo.BuildDate.ToString("yyyy-MM-dd HH:mm:ss"));

            if (!string.IsNullOrWhiteSpace(info.FilterExpression))
                connectionString.AppendFormat("inputMeasurementKeys={{{0}}};", info.FilterExpression);

            if (info.UdpDataChannel)
                connectionString.AppendFormat("dataChannel={{localport={0}}};", info.DataChannelLocalPort);

            if (!string.IsNullOrWhiteSpace(info.StartTime))
                connectionString.AppendFormat("startTimeConstraint={0};", info.StartTime);

            if (!string.IsNullOrWhiteSpace(info.StopTime))
                connectionString.AppendFormat("stopTimeConstraint={0};", info.StopTime);

            if (!string.IsNullOrWhiteSpace(info.ConstraintParameters))
                connectionString.AppendFormat("timeConstraintParameters={0};", info.ConstraintParameters);

            if (!string.IsNullOrWhiteSpace(info.ExtraConnectionStringParameters))
                connectionString.AppendFormat("{0};", info.ExtraConnectionStringParameters);

            // Make sure not to monitor for data loss any faster than down-sample time on throttled connections - additionally
            // you will want to make sure data stream monitor is twice lag-time to allow time for initial points to arrive.
            if (info.Throttled && (object)m_dataStreamMonitor != null && m_dataStreamMonitor.Interval / 1000.0D < info.LagTime)
                m_dataStreamMonitor.Interval = 2.0D * info.LagTime * 1000.0D;

            // Set millisecond resolution member variable for compact measurement parsing
            m_useMillisecondResolution = info.UseMillisecondResolution;

            return Subscribe(false, info.UseCompactMeasurementFormat, connectionString.ToString());
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Opens the stream and starts playback.
        /// </summary>
        /// <param name="songName">The name of the song to be played.</param>
        public void Play(string songName)
        {
            if (m_dataSubscriber != null && m_metadata != null)
            {
                UnsynchronizedSubscriptionInfo info;

                StringBuilder filterExpression = new StringBuilder();
                DataTable     deviceTable      = m_metadata.Tables["DeviceDetail"];
                DataTable     measurementTable = m_metadata.Tables["MeasurementDetail"];

                Dictionary <string, string> uriSettings;
                string dataChannel = null;
                int    uriIndex    = ConnectionUri.IndexOf(URI_SEPARATOR);

                m_channelIndexes = new ConcurrentDictionary <Guid, int>();
                m_sampleRate     = DEFAULT_SAMPLE_RATE;
                m_numChannels    = DEFAULT_NUM_CHANNELS;

                // Get sample rate from metadata.
                if (deviceTable != null)
                {
                    string sampleRate = deviceTable.Rows.Cast <DataRow>()
                                        .Single(row => row["Acronym"].ToNonNullString() == songName)["FramesPerSecond"].ToNonNullString();

                    if (!string.IsNullOrEmpty(sampleRate))
                    {
                        m_sampleRate = int.Parse(sampleRate);
                    }
                }

                // Get measurements from metadata.
                if (measurementTable != null)
                {
                    IEnumerable <DataRow> measurementRows = measurementTable.Rows.Cast <DataRow>()
                                                            .Where(row => row["DeviceAcronym"].ToNonNullString() == songName)
                                                            .Where(row => row["SignalAcronym"].ToNonNullString() == "ALOG" || row["SignalAcronym"].ToNonNullString() == "VPHM")
                                                            .Where(row => row["Enabled"].ToNonNullString().ParseBoolean())
                                                            .OrderBy(row => row["ID"].ToNonNullString());

                    m_numChannels = 0;

                    foreach (DataRow row in measurementRows)
                    {
                        Guid measurementID = Guid.Parse(row["SignalID"].ToNonNullString());

                        if (m_numChannels > 0)
                        {
                            filterExpression.Append(';');
                        }

                        filterExpression.Append(measurementID);
                        m_channelIndexes[measurementID] = m_numChannels;
                        m_numChannels++;
                    }
                }

                // Create UDP data channel if specified.
                if (uriIndex >= 0)
                {
                    uriSettings = ConnectionUri.Substring(uriIndex + URI_SEPARATOR.Length).ParseKeyValuePairs('&');

                    if (uriSettings.ContainsKey("udp"))
                    {
                        dataChannel = string.Format("dataChannel={{port={0}; interface={1}}}", uriSettings["udp"], IPv6Enabled ? "::0" : "0.0.0.0");
                    }
                }

                m_buffer       = new ConcurrentQueue <IMeasurement>();
                m_dumpTimer    = CreateDumpTimer();
                m_statTimer    = CreateStatTimer();
                m_waveProvider = new BufferedWaveProvider(new WaveFormat(m_sampleRate < MINIMUM_SAMPLE_RATE ? MINIMUM_SAMPLE_RATE : m_sampleRate, m_numChannels));
                m_wavePlayer   = CreateWavePlayer(m_waveProvider);
                m_waveProvider.DiscardOnBufferOverflow = true;

                info = new UnsynchronizedSubscriptionInfo(false)
                {
                    FilterExpression = filterExpression.ToString(),
                    ExtraConnectionStringParameters = dataChannel
                };

                m_statTimer.Start();
                m_wavePlayer.Play();
                m_dataSubscriber.UnsynchronizedSubscribe(info);
                m_timeoutTimer.Start();
                OnStateChanged(PlaybackState.Buffering);
            }
        }