//******************************************************************************************************
// TemporalMeasurement.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 09/02/2010 - J. Ritchie Carroll
// Generated original version of source code.
// 12/20/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
namespace GSF.TimeSeries
{
///
/// Represents a time constrained measured value.
///
public class TemporalMeasurement : Measurement
{
#region [ Members ]
// Fields
private double m_lagTime; // Allowed past time deviation tolerance
private double m_leadTime; // Allowed future time deviation tolerance
#endregion
#region [ Constructors ]
///
/// Constructs a new given the specified parameters.
///
/// Past time deviation tolerance, in seconds - this becomes the amount of time to wait before publishing begins.
/// Future time deviation tolerance, in seconds - this becomes the tolerated +/- accuracy of the local clock to real-time.
public TemporalMeasurement(double lagTime, double leadTime)
: this(null, lagTime, leadTime)
{
}
///
/// Constructs a new given the specified parameters.
///
/// Source value.
/// Past time deviation tolerance, in seconds - this becomes the amount of time to wait before publishing begins.
/// Future time deviation tolerance, in seconds - this becomes the tolerated +/- accuracy of the local clock to real-time.
public TemporalMeasurement(IMeasurement measurement, double lagTime, double leadTime)
{
if (measurement != null)
{
Metadata = measurement.Metadata;
Value = measurement.Value;
Timestamp = measurement.Timestamp;
StateFlags = measurement.StateFlags;
}
if (lagTime <= 0)
throw new ArgumentOutOfRangeException(nameof(lagTime), "lagTime must be greater than zero, but it can be less than one");
if (leadTime <= 0)
throw new ArgumentOutOfRangeException(nameof(leadTime), "leadTime must be greater than zero, but it can be less than one");
m_lagTime = lagTime;
m_leadTime = leadTime;
}
#endregion
#region [ Properties ]
/// Allowed past time deviation tolerance in seconds (can be sub-second).
///
/// This value defines the time sensitivity to past measurement timestamps.
/// Defined the number of seconds allowed before assuming a measurement timestamp is too old.
///
/// LagTime must be greater than zero, but it can be less than one.
public double LagTime
{
get => m_lagTime;
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException(nameof(value), "LagTime must be greater than zero, but it can be less than one");
m_lagTime = value;
}
}
/// Allowed future time deviation tolerance in seconds (can be sub-second).
///
/// This value defines the time sensitivity to future measurement timestamps.
/// Defined the number of seconds allowed before assuming a measurement timestamp is too advanced.
///
/// LeadTime must be greater than zero, but it can be less than one.
public double LeadTime
{
get => m_leadTime;
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException(nameof(value), "LeadTime must be greater than zero, but it can be less than one");
m_leadTime = value;
}
}
#endregion
#region [ Methods ]
/// Gets numeric adjusted value of this , constrained within specified ticks.
///
/// Operation will return NaN if ticks are outside of time deviation tolerances.
/// Note that returned value will be offset by adder and multiplier.
///
/// Timestamp used to constrain (typically set to real-time, i.e. "now").
/// Value offset by adder and multiplier (i.e., Value * Multiplier + Adder).
public double GetAdjustedValue(Ticks timestamp)
{
// We only return a measurement value that is up-to-date...
return Timestamp.TimeIsValid(timestamp, m_lagTime, m_leadTime) ? base.AdjustedValue : double.NaN;
}
/// Gets numeric value of this , constrained within specified ticks.
///
/// Operation will return NaN if ticks are outside of time deviation tolerances.
///
/// Timestamp, in ticks, used to constrain (typically set to real-time, i.e. "now").
/// Raw value of this measurement (i.e., value that is not offset by adder and multiplier).
public double GetValue(Ticks timestamp)
{
// We only return a measurement value that is up-to-date...
return Timestamp.TimeIsValid(timestamp, m_lagTime, m_leadTime) ? base.Value : double.NaN;
}
/// Sets numeric value and timestamp, as ticks, of this .
///
/// Operation will only store a value that is newer than the cached value.
///
/// New timestamp, in ticks, for .
/// New value for , only stored if are newer than current .
/// true if value was updated; otherwise false.
public bool SetValue(Ticks timestamp, double value)
{
// We only store a value that is newer than the current value
if (timestamp > Timestamp && timestamp.UtcTimeIsValid(m_lagTime, m_leadTime))
{
base.Value = value;
Timestamp = timestamp;
return true;
}
return false;
}
#endregion
}
}