Defines an API for publishing TrendValue instances from the openHistorian.
예제 #1
0
            protected override List <TimeSeriesValues> QueryTimeSeriesValues(DateTime startTime, DateTime stopTime, int maxDataPoints, Dictionary <ulong, string> targetMap, CancellationToken cancellationToken)
            {
                Dictionary <ulong, TimeSeriesValues> queriedTimeSeriesValues = new Dictionary <ulong, TimeSeriesValues>();

                if (targetMap.Count > 0)
                {
                    SnapServer server = GetAdapterInstance(InstanceName)?.Server?.Host;

                    if ((object)server != null)
                    {
                        ulong[]    measurementIDs = targetMap.Keys.ToArray();
                        Resolution resolution     = TrendValueAPI.EstimatePlotResolution(InstanceName, startTime, stopTime, measurementIDs);

                        using (SnapClient connection = SnapClient.Connect(server))
                            using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(InstanceName))
                            {
                                foreach (TrendValue trendValue in TrendValueAPI.GetHistorianData(database, startTime, stopTime, measurementIDs, resolution, maxDataPoints, false, (CompatibleCancellationToken)cancellationToken))
                                {
                                    queriedTimeSeriesValues.GetOrAdd((ulong)trendValue.ID, id => new TimeSeriesValues {
                                        target = targetMap[id], datapoints = new List <double[]>()
                                    })
                                    .datapoints.Add(new[] { trendValue.Value, trendValue.Timestamp });
                                }
                            }
                    }
                }

                return(queriedTimeSeriesValues.Values.ToList());
            }
예제 #2
0
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="instanceName">Historian instance name.</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="timestampType">Type of timestamps.</param>
        /// <returns>Enumeration of <see cref="TrendValue"/> instances read for time range.</returns>
        public IEnumerable <TrendValue> GetHistorianData(string instanceName, DateTime startTime, DateTime stopTime, ulong[] measurementIDs, Resolution resolution, int seriesLimit, bool forceLimit, TimestampType timestampType = TimestampType.UnixMilliseconds)
        {
            // Cancel any running operation
            CancellationToken cancellationToken = new CancellationToken();

            Interlocked.Exchange(ref m_readCancellationToken, cancellationToken)?.Cancel();

            SnapServer server = GetServer(instanceName)?.Host;
            IEnumerable <TrendValue> values = TrendValueAPI.GetHistorianData(server, instanceName, startTime, stopTime, measurementIDs, resolution, seriesLimit, forceLimit, cancellationToken);

            switch (timestampType)
            {
            case TimestampType.Ticks:
                return(values.Select(value =>
                {
                    value.Timestamp = value.Timestamp * 10000.0D + 621355968000000000.0D;
                    return value;
                }));

            case TimestampType.UnixSeconds:
                return(values.Select(value =>
                {
                    value.Timestamp = value.Timestamp / 1000.0D;
                    return value;
                }));

            default:
                return(values);
            }
        }
        /// <summary>
        /// Read historian data from server.
        /// </summary>
        /// <param name="instanceName">Historian instance name.</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>
        /// <returns>Enumeration of <see cref="TrendValue"/> instances read for time range.</returns>
        public IEnumerable <TrendValue> GetHistorianData(string instanceName, DateTime startTime, DateTime stopTime, ulong[] measurementIDs, Resolution resolution, int seriesLimit, bool forceLimit)
        {
            // Cancel any running query
            CancellationToken cancellationToken = new CancellationToken();

            Interlocked.Exchange(ref m_cancellationToken, cancellationToken)?.Cancel();

            return(TrendValueAPI.GetHistorianData(GetDatabase(instanceName), startTime, stopTime, measurementIDs, resolution, seriesLimit, forceLimit, cancellationToken));
        }
예제 #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;
                            }
                        }
                    }
            }
            /// <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
                                });
                            }
                        }
                    }
            }
        public async Task <IEnumerable <TrendValue> > GetHistorianData(CancellationToken cancellationToken)
        {
            QueryParameters queryParameters;

            using (Stream contentStream = await Request.Content.ReadAsStreamAsync())
                using (StreamReader contentReader = new StreamReader(contentStream))
                    using (JsonTextReader jsonReader = new JsonTextReader(contentReader))
                    {
                        JObject jsonObject = await JObject.LoadAsync(jsonReader);

                        queryParameters = jsonObject.ToObject <QueryParameters>();
                    }

            string   instanceName = queryParameters.instanceName;
            DateTime startTime    = queryParameters.startTime;
            DateTime stopTime     = queryParameters.stopTime;

            ulong[]    measurementIDs = queryParameters.measurementIDs;
            Resolution resolution     = queryParameters.resolution;
            int        seriesLimit    = queryParameters.seriesLimit;
            bool       forceLimit     = queryParameters.forceLimit;

            // Try to ensure another linked cancellation token is not created after dispose,
            // because another call to Dispose() won't clean it up
            if (m_disposed)
            {
                throw new ObjectDisposedException(nameof(HistorianQueryController));
            }

            // Cancel any running operation
            CancellationTokenSource linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);

            using (CancellationTokenSource oldTokenSource = Interlocked.Exchange(ref m_linkedTokenSource, linkedTokenSource))
            {
                oldTokenSource?.Cancel();
            }

            SnapServer               server          = GetServer(instanceName)?.Host;
            ICancellationToken       compatibleToken = new CompatibleCancellationToken(linkedTokenSource);
            IEnumerable <TrendValue> values          = TrendValueAPI.GetHistorianData(server, instanceName, startTime, stopTime, measurementIDs, resolution, seriesLimit, forceLimit, compatibleToken);

            switch (queryParameters.timestampType)
            {
            case TimestampType.Ticks:
                return(values.Select(value =>
                {
                    value.Timestamp = value.Timestamp * 10000.0D + 621355968000000000.0D;
                    return value;
                }));

            case TimestampType.UnixSeconds:
                return(values.Select(value =>
                {
                    value.Timestamp = value.Timestamp / 1000.0D;
                    return value;
                }));

            default:
                return(values);
            }
        }
예제 #7
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
                                });
                            }
                        }
                    }
            }
예제 #8
0
 /// <summary>
 /// Gets loaded historian adapter instance names.
 /// </summary>
 /// <returns>Historian adapter instance names.</returns>
 public IEnumerable <string> GetInstanceNames() => TrendValueAPI.GetInstanceNames();