///// <summary> ///// Establish measurement key cache based on received meta-data. ///// </summary> ///// <param name="metadata">Meta-data received from a subscription.</param> ///// <param name="instanceName">Instance name of the historian.</param> ///// <remarks> ///// If you want the <see cref="IMeasurement.Key"/> values that are returned from a <see cref="GetHistorianData"/> query ///// to have properly assigned Guid based signal IDs, i.e., <see cref="MeasurementKey.SignalID"/>, establish the ///// measurement key cache as soon as you have received meta-data from a GEP subscription query. ///// </remarks> /// <summary> /// Reads interpolated 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="interval">The sampling interval for the interpolated data.</param> /// <param name="measurementIDs">Comma separated list of measurement IDs to 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 GetInterpolatedData(connection, DateTime.UtcNow.AddMinutes(-1.0D), DateTime.UtcNow, TimeSpan.FromSeconds(2.0D), "7,5,15")) /// 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> GetInterpolatedData(Connection connection, DateTime startTime, DateTime stopTime, TimeSpan interval, string measurementIDs) { if ((object)measurementIDs == null) { throw new ArgumentNullException(nameof(measurementIDs)); } // TODO: This was based on code that aligns data and fills time - this function will // need to be re-worked to provide data on an interval based on slopes and time... Measurement[] values = measurementIDs.Split(',').Select(uint.Parse).Select(id => new Measurement() { Metadata = MeasurementKey.LookUpBySource(connection.InstanceName, id).Metadata }).ToArray(); long tickInterval = interval.Ticks; long lastTimestamp = 0L; foreach (IMeasurement measurement in GetHistorianData(connection, startTime, stopTime, measurementIDs)) { long timestamp = measurement.Timestamp; // Start a new row for each encountered new timestamp if (timestamp != lastTimestamp) { if (lastTimestamp > 0) { foreach (IMeasurement value in values) { yield return(value); } } for (int i = 0; i < values.Length; i++) { values[i] = Measurement.Clone(values[i]); } if (lastTimestamp > 0 && timestamp > lastTimestamp) { long difference = timestamp - lastTimestamp; if (difference > tickInterval) { long interpolated = lastTimestamp; for (long i = 1; i < difference / tickInterval; i++) { interpolated = interpolated + tickInterval; foreach (IMeasurement value in values) { yield return(value); } } } } lastTimestamp = timestamp; } } }