コード例 #1
0
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="connection">openHistorian connection.</param>
        /// <param name="startTime">Start time of query.</param>
        /// <param name="stopTime">Stop time of query.</param>
        /// <param name="measurementIDs">Array of measurement IDs to query - or <c>null</c> for all available points.</param>
        /// <param name="resolution">Resolution for data query.</param>
        /// <returns>Enumeration of <see cref="IMeasurement"/> values read for time range.</returns>
        /// <remarks>
        /// <example>
        /// <code>
        /// using (var connection = new Connection("127.0.0.1", "PPA"))
        ///     foreach(var measurement in GetHistorianData(connection, DateTime.UtcNow.AddMinutes(-1.0D), DateTime.UtcNow))
        ///         Console.WriteLine("{0}:{1} @ {2} = {3}, quality: {4}", measurement.Key.Source, measurement.Key.ID, measurement.Timestamp, measurement.Value, measurement.StateFlags);
        /// </code>
        /// </example>
        /// </remarks>
        public static IEnumerable <IMeasurement> GetHistorianData(Connection connection, DateTime startTime, DateTime stopTime, IEnumerable <ulong> measurementIDs = null, Resolution resolution = Resolution.Full)
        {
            SeekFilterBase <HistorianKey> timeFilter;
            MatchFilterBase <HistorianKey, HistorianValue> pointFilter = null;
            HistorianKey   key   = new HistorianKey();
            HistorianValue value = new HistorianValue();

            // Set data scan resolution
            if (resolution == Resolution.Full)
            {
                timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
            }
            else
            {
                TimeSpan             resolutionInterval = resolution.GetInterval();
                BaselineTimeInterval interval           = BaselineTimeInterval.Second;

                if (resolutionInterval.Ticks < Ticks.PerMinute)
                {
                    interval = BaselineTimeInterval.Second;
                }
                else if (resolutionInterval.Ticks < Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Minute;
                }
                else if (resolutionInterval.Ticks == Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Hour;
                }

                startTime = startTime.BaselinedTimestamp(interval);
                stopTime  = stopTime.BaselinedTimestamp(interval);

                timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolutionInterval, new TimeSpan(TimeSpan.TicksPerMillisecond));
            }

            // Setup point ID selections
            if (measurementIDs != null)
            {
                pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(measurementIDs);
            }

            // Start stream reader for the provided time window and selected points
            using (Database database = connection.OpenDatabase())
            {
                TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter);

                while (stream.Read(key, value))
                {
                    yield return new Measurement
                           {
                               Metadata   = MeasurementKey.LookUpOrCreate(connection.InstanceName, (uint)key.PointID).Metadata,
                               Timestamp  = key.TimestampAsDate,
                               Value      = value.AsSingle,
                               StateFlags = (MeasurementStateFlags)value.Value3
                           }
                }
                ;
            }
        }
コード例 #2
0
ファイル: TrendValueAPI.cs プロジェクト: jikk/openHistorian
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="server">The server to use for the query.</param>
        /// <param name="instanceName">Name of the archive to be queried.</param>
        /// <param name="startTime">Start time of query.</param>
        /// <param name="stopTime">Stop time of query.</param>
        /// <param name="measurementIDs">Measurement IDs to query - or <c>null</c> for all available points.</param>
        /// <param name="resolution">Resolution for data query.</param>
        /// <param name="seriesLimit">Maximum number of points per series.</param>
        /// <param name="forceLimit">Flag that determines if series limit should be strictly enforced.</param>
        /// <param name="cancellationToken">Cancellation token for query.</param>
        /// <returns>Enumeration of <see cref="TrendValue"/> instances read for time range.</returns>
        public static IEnumerable <TrendValue> GetHistorianData(SnapServer server, string instanceName, DateTime startTime, DateTime stopTime, ulong[] measurementIDs, Resolution resolution, int seriesLimit, bool forceLimit, ICancellationToken cancellationToken = null)
        {
            if (cancellationToken == null)
            {
                cancellationToken = new CancellationToken();
            }

            if (server == null)
            {
                yield break;
            }

            // Setting series limit to zero requests full resolution data, which overrides provided parameter
            if (seriesLimit < 1)
            {
                resolution = Resolution.Full;
            }

            TimeSpan resolutionInterval = resolution.GetInterval();
            SeekFilterBase <HistorianKey> timeFilter;
            MatchFilterBase <HistorianKey, HistorianValue> pointFilter = null;
            HistorianKey   key   = new HistorianKey();
            HistorianValue value = new HistorianValue();

            // Set data scan resolution
            if (resolution == Resolution.Full)
            {
                timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
            }
            else
            {
                BaselineTimeInterval interval = BaselineTimeInterval.Second;

                if (resolutionInterval.Ticks < Ticks.PerMinute)
                {
                    interval = BaselineTimeInterval.Second;
                }
                else if (resolutionInterval.Ticks < Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Minute;
                }
                else if (resolutionInterval.Ticks == Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Hour;
                }

                startTime = startTime.BaselinedTimestamp(interval);
                stopTime  = stopTime.BaselinedTimestamp(interval);

                timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolutionInterval, new TimeSpan(TimeSpan.TicksPerMillisecond));
            }

            Dictionary <ulong, DataRow> metadata = null;

            using (SnapClient connection = SnapClient.Connect(server))
                using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(instanceName))
                {
                    if (database == null)
                    {
                        yield break;
                    }

                    if (LocalOutputAdapter.Instances.TryGetValue(database.Info?.DatabaseName ?? DefaultInstanceName, out LocalOutputAdapter historianAdapter))
                    {
                        metadata = historianAdapter?.Measurements;
                    }

                    if (metadata == null)
                    {
                        yield break;
                    }

                    // Setup point ID selections
                    if (measurementIDs != null)
                    {
                        pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(measurementIDs);
                    }
                    else
                    {
                        measurementIDs = metadata.Keys.ToArray();
                    }

                    // Start stream reader for the provided time window and selected points
                    Dictionary <ulong, long>  pointCounts = new Dictionary <ulong, long>(measurementIDs.Length);
                    Dictionary <ulong, long>  intervals   = new Dictionary <ulong, long>(measurementIDs.Length);
                    Dictionary <ulong, ulong> lastTimes   = new Dictionary <ulong, ulong>(measurementIDs.Length);
                    double range = (stopTime - startTime).TotalSeconds;
                    ulong  pointID, timestamp, resolutionSpan = (ulong)resolutionInterval.Ticks, baseTicks = (ulong)UnixTimeTag.BaseTicks.Value;
                    long   pointCount;

                    if (resolutionSpan <= 1UL)
                    {
                        resolutionSpan = Ticks.PerSecond;
                    }

                    if (seriesLimit < 1)
                    {
                        seriesLimit = 1;
                    }

                    // Estimate total measurement counts per point so decimation intervals for each series can be calculated
                    foreach (ulong measurementID in measurementIDs)
                    {
                        if (resolution == Resolution.Full)
                        {
                            pointCounts[measurementID] = metadata.TryGetValue(measurementID, out DataRow row) ? (long)(int.Parse(row["FramesPerSecond"].ToString()) * range) : 2;
                        }
                        else
                        {
                            pointCounts[measurementID] = (long)(range / resolutionInterval.TotalSeconds.NotZero(1.0D));
                        }
                    }

                    foreach (ulong measurementID in pointCounts.Keys)
                    {
                        intervals[measurementID] = (pointCounts[measurementID] / seriesLimit).NotZero(1L);
                    }

                    using (TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter))
                    {
                        while (stream.Read(key, value) && !cancellationToken.IsCancelled)
                        {
                            pointID    = key.PointID;
                            timestamp  = key.Timestamp;
                            pointCount = pointCounts[pointID];

                            if (pointCount++ % intervals[pointID] == 0 || !forceLimit && timestamp - lastTimes.GetOrAdd(pointID, 0UL) > resolutionSpan)
                            {
                                yield return new TrendValue
                                       {
                                           ID        = (long)pointID,
                                           Timestamp = (timestamp - baseTicks) / (double)Ticks.PerMillisecond,
                                           Value     = value.AsSingle
                                       }
                            }
                            ;

                            pointCounts[pointID] = pointCount;
                            lastTimes[pointID]   = timestamp;
                        }
                    }
                }
        }
    }
コード例 #3
0
ファイル: DateTimeExtensions.cs プロジェクト: avs009/gsf
 /// <summary>Creates a baselined timestamp which begins at the specified time interval.</summary>
 /// <param name="timestamp">Timestamp to baseline.</param>
 /// <param name="interval">
 /// <see cref="BaselineTimeInterval"/> to which <paramref name="timestamp"/> should be baselined.
 /// </param>
 /// <returns>
 /// A new <see cref="DateTime"/> value that represents a baselined timestamp that begins at the
 /// specified <see cref="BaselineTimeInterval"/>.
 /// </returns>
 /// <remarks>
 /// Baselining to the <see cref="BaselineTimeInterval.Second"/> would return the <see cref="DateTime"/>
 /// value starting at zero milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Minute"/> would return the <see cref="DateTime"/>
 /// value starting at zero seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Hour"/> would return the <see cref="DateTime"/>
 /// value starting at zero minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Day"/> would return the <see cref="DateTime"/>
 /// value starting at zero hours, minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Month"/> would return the <see cref="DateTime"/>
 /// value starting at day one, zero hours, minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Year"/> would return the <see cref="DateTime"/>
 /// value starting at month one, day one, zero hours, minutes, seconds and milliseconds.
 /// </remarks>
 public static DateTime BaselinedTimestamp(this DateTime timestamp, BaselineTimeInterval interval)
 {
     return ((Ticks)timestamp).BaselinedTimestamp(interval);
 }
コード例 #4
0
            /// <summary>
            /// Starts a query that will read data source values, given a set of point IDs and targets, over a time range.
            /// </summary>
            /// <param name="startTime">Start-time for query.</param>
            /// <param name="stopTime">Stop-time for query.</param>
            /// <param name="interval">Interval from Grafana request.</param>
            /// <param name="includePeaks">Flag that determines if decimated data should include min/max interval peaks over provided time range.</param>
            /// <param name="targetMap">Set of IDs with associated targets to query.</param>
            /// <returns>Queried data source data in terms of value and time.</returns>
            protected override IEnumerable <DataSourceValue> QueryDataSourceValues(DateTime startTime, DateTime stopTime, string interval, bool includePeaks, Dictionary <ulong, string> targetMap)
            {
                SnapServer server = GetAdapterInstance(InstanceName)?.Server?.Host;

                if (server == null)
                {
                    yield break;
                }

                using (SnapClient connection = SnapClient.Connect(server))
                    using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(InstanceName))
                    {
                        if (database == null)
                        {
                            yield break;
                        }

                        if (!TryParseInterval(interval, out TimeSpan resolutionInterval))
                        {
                            Resolution resolution = TrendValueAPI.EstimatePlotResolution(InstanceName, startTime, stopTime, targetMap.Keys);
                            resolutionInterval = resolution.GetInterval();
                        }

                        BaselineTimeInterval timeInterval = BaselineTimeInterval.Second;

                        if (resolutionInterval.Ticks < Ticks.PerMinute)
                        {
                            timeInterval = BaselineTimeInterval.Second;
                        }
                        else if (resolutionInterval.Ticks < Ticks.PerHour)
                        {
                            timeInterval = BaselineTimeInterval.Minute;
                        }
                        else if (resolutionInterval.Ticks == Ticks.PerHour)
                        {
                            timeInterval = BaselineTimeInterval.Hour;
                        }

                        startTime = startTime.BaselinedTimestamp(timeInterval);
                        stopTime  = stopTime.BaselinedTimestamp(timeInterval);

                        if (startTime == stopTime)
                        {
                            stopTime = stopTime.AddSeconds(1.0D);
                        }

                        SeekFilterBase <HistorianKey> timeFilter;

                        // Set timestamp filter resolution
                        if (includePeaks || resolutionInterval == TimeSpan.Zero)
                        {
                            // Full resolution query
                            timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
                        }
                        else
                        {
                            // Interval query
                            timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolutionInterval, new TimeSpan(TimeSpan.TicksPerMillisecond));
                        }

                        // Setup point ID selections
                        MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(targetMap.Keys);
                        Dictionary <ulong, ulong> lastTimes = new Dictionary <ulong, ulong>(targetMap.Count);
                        Dictionary <ulong, Peak>  peaks     = new Dictionary <ulong, Peak>(targetMap.Count);
                        ulong resolutionSpan = (ulong)resolutionInterval.Ticks;

                        if (includePeaks)
                        {
                            resolutionSpan *= 2UL;
                        }

                        // Start stream reader for the provided time window and selected points
                        using (TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter))
                        {
                            HistorianKey   key   = new HistorianKey();
                            HistorianValue value = new HistorianValue();
                            Peak           peak  = Peak.Default;

                            while (stream.Read(key, value))
                            {
                                ulong pointID    = key.PointID;
                                ulong timestamp  = key.Timestamp;
                                float pointValue = value.AsSingle;

                                if (includePeaks)
                                {
                                    peak = peaks.GetOrAdd(pointID, _ => new Peak());
                                    peak.Set(pointValue, timestamp);
                                }

                                if (resolutionSpan > 0UL && timestamp - lastTimes.GetOrAdd(pointID, 0UL) < resolutionSpan)
                                {
                                    continue;
                                }

                                // New value is ready for publication
                                string target = targetMap[pointID];
                                MeasurementStateFlags flags = (MeasurementStateFlags)value.Value3;

                                if (includePeaks)
                                {
                                    if (peak.MinTimestamp > 0UL)
                                    {
                                        yield return(new DataSourceValue
                                        {
                                            Target = target,
                                            Value = peak.Min,
                                            Time = (peak.MinTimestamp - m_baseTicks) / (double)Ticks.PerMillisecond,
                                            Flags = flags
                                        });
                                    }

                                    if (peak.MaxTimestamp != peak.MinTimestamp)
                                    {
                                        yield return(new DataSourceValue
                                        {
                                            Target = target,
                                            Value = peak.Max,
                                            Time = (peak.MaxTimestamp - m_baseTicks) / (double)Ticks.PerMillisecond,
                                            Flags = flags
                                        });
                                    }

                                    peak.Reset();
                                }
                                else
                                {
                                    yield return(new DataSourceValue
                                    {
                                        Target = target,
                                        Value = pointValue,
                                        Time = (timestamp - m_baseTicks) / (double)Ticks.PerMillisecond,
                                        Flags = flags
                                    });
                                }

                                lastTimes[pointID] = timestamp;
                            }
                        }
                    }
            }
コード例 #5
0
            /// <summary>
            /// Starts a query that will read data source values, given a set of point IDs and targets, over a time range.
            /// </summary>
            /// <param name="startTime">Start-time for query.</param>
            /// <param name="stopTime">Stop-time for query.</param>
            /// <param name="interval">Interval from Grafana request.</param>
            /// <param name="decimate">Flag that determines if data should be decimated over provided time range.</param>
            /// <param name="targetMap">Set of IDs with associated targets to query.</param>
            /// <returns>Queried data source data in terms of value and time.</returns>
            protected override IEnumerable <DataSourceValue> QueryDataSourceValues(DateTime startTime, DateTime stopTime, string interval, bool decimate, Dictionary <ulong, string> targetMap)
            {
                SnapServer server = GetAdapterInstance(InstanceName)?.Server?.Host;

                if ((object)server == null)
                {
                    yield break;
                }

                using (SnapClient connection = SnapClient.Connect(server))
                    using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(InstanceName))
                    {
                        if ((object)database == null)
                        {
                            yield break;
                        }

                        Resolution resolution = TrendValueAPI.EstimatePlotResolution(InstanceName, startTime, stopTime, targetMap.Keys);
                        SeekFilterBase <HistorianKey> timeFilter;

                        // Set data scan resolution
                        if (!decimate || resolution == Resolution.Full)
                        {
                            timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
                        }
                        else
                        {
                            TimeSpan             resolutionInterval = resolution.GetInterval();
                            BaselineTimeInterval timeInterval       = BaselineTimeInterval.Second;

                            if (resolutionInterval.Ticks < Ticks.PerMinute)
                            {
                                timeInterval = BaselineTimeInterval.Second;
                            }
                            else if (resolutionInterval.Ticks < Ticks.PerHour)
                            {
                                timeInterval = BaselineTimeInterval.Minute;
                            }
                            else if (resolutionInterval.Ticks == Ticks.PerHour)
                            {
                                timeInterval = BaselineTimeInterval.Hour;
                            }

                            startTime = startTime.BaselinedTimestamp(timeInterval);
                            stopTime  = stopTime.BaselinedTimestamp(timeInterval);

                            int milliseconds = 1;
                            try
                            {
                                ConfigurationFile                    configFile          = ConfigurationFile.Open(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
                                CategorizedSettingsSection           categorizedSettings = configFile.Settings;
                                CategorizedSettingsElementCollection systemSettings      = categorizedSettings["systemSettings"];
                                string val = systemSettings["HistoryTolerance"].Value;
                            }
                            catch { } // something went wrong, so just use original default

                            timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolutionInterval, new TimeSpan(TimeSpan.TicksPerMillisecond * milliseconds));
                        }

                        // Setup point ID selections
                        MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(targetMap.Keys);

                        // Start stream reader for the provided time window and selected points
                        using (TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter))
                        {
                            HistorianKey   key   = new HistorianKey();
                            HistorianValue value = new HistorianValue();

                            while (stream.Read(key, value))
                            {
                                yield return(new DataSourceValue
                                {
                                    Target = targetMap[key.PointID],
                                    Time = (key.Timestamp - m_baseTicks) / (double)Ticks.PerMillisecond,
                                    Value = value.AsSingle,
                                    Flags = (MeasurementStateFlags)value.Value3
                                });
                            }
                        }
                    }
            }
コード例 #6
0
        /// <summary>
        /// Updates the chart after changes have been made to the chart boundaries or the data displayed in the chart.
        /// </summary>
        public void UpdateChart()
        {
            if ((object)m_archiveReader == null)
            {
                return;
            }

            Cursor windowCursor = Cursor;

            Cursor = Cursors.Wait;

            int      colorIndex = 0;
            DateTime startTime  = m_xAxis.Minimum.GetValueOrDefault(DateTime.MinValue);
            DateTime endTime    = m_xAxis.Maximum.GetValueOrDefault(DateTime.MaxValue);

            m_chart.Series.Clear();

            SeekFilterBase <HistorianKey> timeFilter;

            if (m_chartResolution.Ticks != 0)
            {
                BaselineTimeInterval interval = BaselineTimeInterval.Second;

                if (m_chartResolution.Ticks < Ticks.PerMinute)
                {
                    interval = BaselineTimeInterval.Second;
                }
                else if (m_chartResolution.Ticks < Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Minute;
                }
                else if (m_chartResolution.Ticks == Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Hour;
                }

                startTime = startTime.BaselinedTimestamp(interval);
                endTime   = endTime.BaselinedTimestamp(interval);

                timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, endTime, m_chartResolution, new TimeSpan(TimeSpan.TicksPerMillisecond));
            }
            else
            {
                timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, endTime);
            }

            MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(m_visiblePoints.Select(point => point.Value.PointID));
            TreeStream <HistorianKey, HistorianValue>      stream;

            HistorianKey   key   = new HistorianKey();
            HistorianValue value = new HistorianValue();
            Dictionary <ulong, List <DataPointWrapper> > data = new Dictionary <ulong, List <DataPointWrapper> >(m_visiblePoints.Count);
            Dictionary <ulong, long> pointCounts = new Dictionary <ulong, long>();
            Dictionary <ulong, long> intervals   = new Dictionary <ulong, long>();
            List <DataPointWrapper>  values;
            long pointCount;

            if (m_sampleSize > 1)
            {
                // Count total data points to reduce total points to chart
                stream = m_archiveReader.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter);

                while (stream.Read(key, value))
                {
                    pointCounts[key.PointID] = pointCounts.GetOrAdd(key.PointID, 0L) + 1;
                }

                foreach (ulong pointID in pointCounts.Keys)
                {
                    intervals[pointID] = (pointCounts[pointID] / m_sampleSize) + 1;
                }
            }

            // Load data into dictionary
            stream = m_archiveReader.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter);

            while (stream.Read(key, value))
            {
                values     = data.GetOrAdd(key.PointID, id => new List <DataPointWrapper>());
                pointCount = pointCounts[key.PointID];

                if (m_sampleSize < 2 || pointCount++ % intervals[key.PointID] == 0)
                {
                    values.Add(new DataPointWrapper(key, value));
                }

                pointCounts[key.PointID] = pointCount;
            }

            foreach (KeyValuePair <ulong, Metadata> measurement in m_visiblePoints)
            {
                if (data.TryGetValue(measurement.Key, out values))
                {
                    LineSeries series = new LineSeries();

                    // Change how data points are displayed.
                    series.DataPointStyle = new Style(typeof(LineDataPoint));
                    series.DataPointStyle.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(m_lineColors[colorIndex])));
                    series.DataPointStyle.Setters.Add(new Setter(TemplateProperty, new ControlTemplate()));

                    colorIndex++;

                    if (colorIndex >= m_lineColors.Count)
                    {
                        colorIndex = 0;
                    }

                    // Set the title of the series as it will appear in the legend.
                    series.Title = measurement.Value.SignalReference;

                    // Set chart data
                    series.ItemsSource          = values;
                    series.IndependentValuePath = "Time";
                    series.DependentValuePath   = "Value";

                    // Add the series to the chart.
                    m_chart.Series.Add(series);
                }
            }

            UpdateLayout();
            Cursor = windowCursor;
            OnChartUpdated();
        }
コード例 #7
0
 /// <summary>Creates a baselined timestamp which begins at the specified time interval.</summary>
 /// <param name="timestamp">Timestamp to baseline.</param>
 /// <param name="interval">
 /// <see cref="BaselineTimeInterval"/> to which <paramref name="timestamp"/> should be baselined.
 /// </param>
 /// <returns>
 /// A new <see cref="DateTime"/> value that represents a baselined timestamp that begins at the
 /// specified <see cref="BaselineTimeInterval"/>.
 /// </returns>
 /// <remarks>
 /// Baselining to the <see cref="BaselineTimeInterval.Second"/> would return the <see cref="DateTime"/>
 /// value starting at zero milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Minute"/> would return the <see cref="DateTime"/>
 /// value starting at zero seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Hour"/> would return the <see cref="DateTime"/>
 /// value starting at zero minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Day"/> would return the <see cref="DateTime"/>
 /// value starting at zero hours, minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Month"/> would return the <see cref="DateTime"/>
 /// value starting at day one, zero hours, minutes, seconds and milliseconds.<br/>
 /// Baselining to the <see cref="BaselineTimeInterval.Year"/> would return the <see cref="DateTime"/>
 /// value starting at month one, day one, zero hours, minutes, seconds and milliseconds.
 /// </remarks>
 public static DateTime BaselinedTimestamp(this DateTime timestamp, BaselineTimeInterval interval)
 {
     return(((Ticks)timestamp).BaselinedTimestamp(interval));
 }
コード例 #8
0
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="server">The server to use for the query.</param>
        /// <param name="instanceName">Name of the archive to be queried.</param>
        /// <param name="startTime">Start time of query.</param>
        /// <param name="stopTime">Stop time of query.</param>
        /// <param name="measurementIDs">Measurement IDs to query - or <c>null</c> for all available points.</param>
        /// <param name="resolution">Resolution for data query.</param>
        /// <param name="seriesLimit">Maximum number of points per series.</param>
        /// <param name="forceLimit">Flag that determines if series limit should be strictly enforced.</param>
        /// <param name="cancellationToken">Cancellation token for query.</param>
        /// <returns>Enumeration of <see cref="TrendValue"/> instances read for time range.</returns>
        public static IEnumerable <TrendValue> GetHistorianData(SnapServer server, string instanceName, DateTime startTime, DateTime stopTime, ulong[] measurementIDs, Resolution resolution, int seriesLimit, bool forceLimit, ICancellationToken cancellationToken = null)
        {
            if (cancellationToken == null)
            {
                cancellationToken = new CancellationToken();
            }

            if (server == null)
            {
                yield break;
            }

            // Setting series limit to zero requests full resolution data, which overrides provided parameter
            if (seriesLimit < 1)
            {
                resolution = Resolution.Full;
                forceLimit = false;
            }

            TimeSpan resolutionInterval = resolution.GetInterval();
            MatchFilterBase <HistorianKey, HistorianValue> pointFilter = null;
            HistorianKey   key               = new HistorianKey();
            HistorianValue value             = new HistorianValue();
            bool           subFullResolution = false;

            // Set data scan resolution
            if (resolution != Resolution.Full)
            {
                subFullResolution = true;

                BaselineTimeInterval interval = BaselineTimeInterval.Second;

                if (resolutionInterval.Ticks < Ticks.PerMinute)
                {
                    interval = BaselineTimeInterval.Second;
                }
                else if (resolutionInterval.Ticks < Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Minute;
                }
                else if (resolutionInterval.Ticks == Ticks.PerHour)
                {
                    interval = BaselineTimeInterval.Hour;
                }

                startTime = startTime.BaselinedTimestamp(interval);
                stopTime  = stopTime.BaselinedTimestamp(interval);
            }

            SeekFilterBase <HistorianKey> timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);

            Dictionary <ulong, DataRow> metadata = null;

            using (SnapClient connection = SnapClient.Connect(server))
                using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(instanceName))
                {
                    if (database == null)
                    {
                        yield break;
                    }

                    if (LocalOutputAdapter.Instances.TryGetValue(database.Info?.DatabaseName ?? DefaultInstanceName, out LocalOutputAdapter historianAdapter))
                    {
                        metadata = historianAdapter?.Measurements;
                    }

                    if (metadata == null)
                    {
                        yield break;
                    }

                    // Setup point ID selections
                    if (measurementIDs != null)
                    {
                        pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(measurementIDs);
                    }
                    else
                    {
                        measurementIDs = metadata.Keys.ToArray();
                    }

                    Dictionary <ulong, long>  pointCounts = new Dictionary <ulong, long>(measurementIDs.Length);
                    Dictionary <ulong, ulong> lastTimes   = new Dictionary <ulong, ulong>(measurementIDs.Length);
                    Dictionary <ulong, Tuple <float, float> > extremes = new Dictionary <ulong, Tuple <float, float> >(measurementIDs.Length);
                    ulong pointID, timestamp, resolutionSpan = (ulong)resolutionInterval.Ticks, baseTicks = (ulong)UnixTimeTag.BaseTicks.Value;
                    long  pointCount;
                    float pointValue, min = 0.0F, max = 0.0F;

                    foreach (ulong measurementID in measurementIDs)
                    {
                        pointCounts[measurementID] = 0L;
                    }

                    // Start stream reader for the provided time window and selected points
                    using (TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter))
                    {
                        while (stream.Read(key, value) && !cancellationToken.IsCancelled)
                        {
                            pointID    = key.PointID;
                            timestamp  = key.Timestamp;
                            pointCount = pointCounts[pointID];
                            pointValue = value.AsSingle;

                            if (subFullResolution)
                            {
                                Tuple <float, float> stats = extremes.GetOrAdd(pointID, _ => new Tuple <float, float>(float.MaxValue, float.MinValue));

                                min = stats.Item1;
                                max = stats.Item2;

                                if (pointValue < min)
                                {
                                    min = pointValue;
                                }

                                if (pointValue > max)
                                {
                                    max = pointValue;
                                }

                                if (min != float.MaxValue && max != float.MinValue)
                                {
                                    pointValue = Math.Abs(max) > Math.Abs(min) ? max : min;
                                }
                                else if (min != float.MaxValue)
                                {
                                    pointValue = min;
                                }
                                else if (max != float.MinValue)
                                {
                                    pointValue = max;
                                }
                            }

                            if (timestamp - lastTimes.GetOrAdd(pointID, 0UL) > resolutionSpan)
                            {
                                pointCount++;

                                if (forceLimit && pointCount > seriesLimit)
                                {
                                    break;
                                }

                                yield return(new TrendValue
                                {
                                    ID = (long)pointID,
                                    Timestamp = (timestamp - baseTicks) / (double)Ticks.PerMillisecond,
                                    Value = pointValue
                                });

                                lastTimes[pointID] = timestamp;

                                // Reset extremes at each point publication
                                if (subFullResolution)
                                {
                                    extremes[pointID] = new Tuple <float, float>(float.MaxValue, float.MinValue);
                                }
                            }
                            else if (subFullResolution)
                            {
                                // Track extremes over interval
                                extremes[pointID] = new Tuple <float, float>(min, max);
                            }

                            pointCounts[pointID] = pointCount;
                        }
                    }
                }
        }
コード例 #9
0
ファイル: DateTimeExtensionsTest.cs プロジェクト: avs009/gsf
 public DateTime BaselinedTimestamp(DateTime timestamp, BaselineTimeInterval interval)
 {
     DateTime result = DateTimeExtensions.BaselinedTimestamp(timestamp, interval);
     return result;
     // TODO: add assertions to method DateTimeExtensionsTest.BaselinedTimestamp(DateTime, BaselineTimeInterval)
 }
コード例 #10
0
            protected override IEnumerable <DataSourceValue> QueryDataSourceValues(DateTime startTime, DateTime stopTime, string interval, bool decimate, Dictionary <ulong, string> targetMap)
            {
                SnapServer server = GetAdapterInstance(InstanceName)?.Server?.Host;

                if ((object)server == null)
                {
                    yield break;
                }

                using (SnapClient connection = SnapClient.Connect(server))
                    using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(InstanceName))
                    {
                        if ((object)database == null)
                        {
                            yield break;
                        }

                        Resolution resolution = TrendValueAPI.EstimatePlotResolution(InstanceName, startTime, stopTime, targetMap.Keys);
                        SeekFilterBase <HistorianKey> timeFilter;

                        // Set data scan resolution
                        if (!decimate || resolution == Resolution.Full)
                        {
                            timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, stopTime);
                        }
                        else
                        {
                            TimeSpan             resolutionInterval = resolution.GetInterval();
                            BaselineTimeInterval timeInterval       = BaselineTimeInterval.Second;

                            if (resolutionInterval.Ticks < Ticks.PerMinute)
                            {
                                timeInterval = BaselineTimeInterval.Second;
                            }
                            else if (resolutionInterval.Ticks < Ticks.PerHour)
                            {
                                timeInterval = BaselineTimeInterval.Minute;
                            }
                            else if (resolutionInterval.Ticks == Ticks.PerHour)
                            {
                                timeInterval = BaselineTimeInterval.Hour;
                            }

                            startTime = startTime.BaselinedTimestamp(timeInterval);
                            stopTime  = stopTime.BaselinedTimestamp(timeInterval);

                            timeFilter = TimestampSeekFilter.CreateFromIntervalData <HistorianKey>(startTime, stopTime, resolutionInterval, new TimeSpan(TimeSpan.TicksPerMillisecond));
                        }

                        // Setup point ID selections
                        MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(targetMap.Keys);

                        // Start stream reader for the provided time window and selected points
                        using (TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter))
                        {
                            HistorianKey   key   = new HistorianKey();
                            HistorianValue value = new HistorianValue();

                            while (stream.Read(key, value))
                            {
                                yield return(new DataSourceValue
                                {
                                    Target = targetMap[key.PointID],
                                    Time = (key.Timestamp - m_baseTicks) / (double)Ticks.PerMillisecond,
                                    Value = value.AsSingle
                                });
                            }
                        }
                    }
            }
コード例 #11
0
ファイル: DateTimeExtensions.cs プロジェクト: avs009/gsf
 /// <summary>Creates a baselined timestamp which begins at the specified time interval.</summary>
 /// <param name="timestamp">Timestamp to baseline.</param>
 /// <param name="baselineTo">Time interval to which timestamp should be baselined.</param>
 /// <returns>Baselined timestamp which begins at the specified time interval.</returns>
 /// <remarks>
 /// <para>Baselining to the second would return the timestamp starting at zero milliseconds.</para>
 /// <para>Baselining to the minute would return the timestamp starting at zero seconds and milliseconds.</para>
 /// <para>Baselining to the hour would return the timestamp starting at zero minutes, seconds and
 /// milliseconds.</para>
 /// <para>Baselining to the day would return the timestamp starting at zero hours, minutes, seconds and
 /// milliseconds.</para>
 /// <para>Baselining to the month would return the timestamp starting at day one, zero hours, minutes,
 /// seconds and milliseconds.</para>
 /// <para>Baselining to the year would return the timestamp starting at month one, day one, zero hours,
 /// minutes, seconds and milliseconds.</para>
 /// </remarks>
 public static DateTime BaselinedTimestamp(this DateTime timestamp, BaselineTimeInterval baselineTo)
 {
     return new DateTime(timestamp.Ticks.BaselinedTimestamp(baselineTo));
 }
コード例 #12
0
ファイル: DateTimeExtensions.cs プロジェクト: avs009/gsf
 /// <summary>Creates a baselined timestamp which begins at the specified time interval.</summary>
 /// <param name="ticks">Ticks of timestamp to baseline.</param>
 /// <param name="baselineTo">Time interval to which timestamp should be baselined.</param>
 /// <returns>Baselined timestamp, in ticks, which begins at the specified time interval.</returns>
 /// <remarks>
 /// <para>Baselining to the second would return the timestamp starting at zero milliseconds.</para>
 /// <para>Baselining to the minute would return the timestamp starting at zero seconds and milliseconds.</para>
 /// <para>Baselining to the hour would return the timestamp starting at zero minutes, seconds and
 /// milliseconds.</para>
 /// <para>Baselining to the day would return the timestamp starting at zero hours, minutes, seconds and
 /// milliseconds.</para>
 /// <para>Baselining to the month would return the timestamp starting at day one, zero hours, minutes,
 /// seconds and milliseconds.</para>
 /// <para>Baselining to the year would return the timestamp starting at month one, day one, zero hours,
 /// minutes, seconds and milliseconds.</para>
 /// </remarks>
 public static long BaselinedTimestamp(this long ticks, BaselineTimeInterval baselineTo)
 {
     switch (baselineTo)
     {
         case BaselineTimeInterval.Second:
             return ticks - ticks % Ticks.PerSecond;
         case BaselineTimeInterval.Minute:
             return ticks - ticks % Ticks.PerMinute;
         case BaselineTimeInterval.Hour:
             return ticks - ticks % Ticks.PerHour;
         case BaselineTimeInterval.Day:
             return ticks - ticks % Ticks.PerDay;
         case BaselineTimeInterval.Month:
             DateTime toMonth = new DateTime(ticks);
             return new DateTime(toMonth.Year, toMonth.Month, 1, 0, 0, 0, 0).Ticks;
         case BaselineTimeInterval.Year:
             DateTime toYear = new DateTime(ticks);
             return new DateTime(toYear.Year, 1, 1, 0, 0, 0, 0).Ticks;
         default:
             return ticks;
     }
 }