/// <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; }
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))); } }
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); }); }
/// <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(); }
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(); }
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(); }
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); }
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(); }
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))); } }
/// <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); } }
// 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); }
/// <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; } }
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); } }
/// <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()); }
/// <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); } }