494 lines · 20.3 KB · C#
RawDownload
//******************************************************************************************************//  ArchiveDataPoint.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://  ----------------------------------------------------------------------------------------------------//  02/23/2007 - Pinal C. Patel//       Generated original version of code based on DatAWare system specifications by Brian B. Fox, GSF.//  04/20/2009 - Pinal C. Patel//       Converted to C#.//  09/10/2009 - Pinal C. Patel//       Added constructor that takes in IMeasurement.//  09/15/2009 - Stephen C. Wills//       Added new header and license agreement.//  03/15/2010 - Pinal C. Patel//       Implemented IFormattable.ToString() overloads.//  04/20/2010 - J. Ritchie Carroll//       Added construction overload for IMeasurement that accepts specific quality.//  09/16/2010 - J. Ritchie Carroll//       Modified formatted time to include milliseconds.//  10/11/2010 - Mihir Brahmbhatt//       Updated header and license agreement.//  11/30/2011 - J. Ritchie Carroll//       Modified to support buffer optimized ISupportBinaryImage.//  12/14/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Globalization;using GSF.TimeSeries; // ReSharper disable VirtualMemberCallInConstructor// ReSharper disable NonReadonlyMemberInGetHashCodenamespace GSF.Historian.Files{    /// <summary>    /// Represents time-series data stored in <see cref="ArchiveFile"/>.    /// </summary>    /// <seealso cref="ArchiveFile"/>    /// <seealso cref="ArchiveFileAllocationTable"/>    /// <seealso cref="ArchiveDataBlock"/>    /// <seealso cref="ArchiveDataBlockPointer"/>    public class ArchiveDataPoint : IDataPoint    {        // **************************************************************************************************        // *                                        Binary Structure                                        *        // **************************************************************************************************        // * # Of Bytes Byte Index Data Type  Property Name                                                 *        // * ---------- ---------- ---------- --------------------------------------------------------------*        // * 4          0-3        Int32      Time                                                          *        // * 2          4-5        Int16      Flags (Quality & Milliseconds)                                *        // * 4          6-9        Single     Value                                                         *        // **************************************************************************************************         #region [ Members ]         // Constants         /// <summary>        /// Specifies the number of bytes in the binary image of <see cref="ArchiveDataPoint"/>.        /// </summary>        public const int FixedLength = 10;         /// <summary>        /// Specifies the bit-mask for <see cref="Quality"/> stored in <see cref="Flags"/>.        /// </summary>        protected const Bits QualityMask = Bits.Bit00 | Bits.Bit01 | Bits.Bit02 | Bits.Bit03 | Bits.Bit04;         /// <summary>        /// Specifies the bit-mask for <see cref="TimeTag"/> milliseconds stored in <see cref="Flags"/>.        /// </summary>        protected const Bits MillisecondMask = Bits.Bit05 | Bits.Bit06 | Bits.Bit07 | Bits.Bit08 | Bits.Bit09 | Bits.Bit10 | Bits.Bit11 | Bits.Bit12 | Bits.Bit13 | Bits.Bit14 | Bits.Bit15;         // Fields        private int m_historianID;        private TimeTag m_time;        private float m_value;        private int m_flags;        private MetadataRecord m_metadata;         #endregion         #region [ Constructors ]         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class.        /// </summary>        /// <param name="historianID">Historian identifier of <see cref="ArchiveDataPoint"/>.</param>        public ArchiveDataPoint(int historianID)        {            m_time = TimeTag.MinValue;            this.HistorianID = historianID;        }         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class.        /// </summary>        /// <param name="dataPoint">A time-series data point.</param>        public ArchiveDataPoint(IDataPoint dataPoint)            : this(dataPoint.HistorianID, dataPoint.Time, dataPoint.Value, dataPoint.Quality)        {        }         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class from a <see cref="IMeasurement"/> value.        /// </summary>        /// <param name="measurement">Object that implements the <see cref="IMeasurement"/> interface.</param>        public ArchiveDataPoint(IMeasurement measurement)            : this(measurement, measurement.HistorianQuality())        {        }         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class from a <see cref="IMeasurement"/> value.        /// </summary>        /// <param name="measurement">Object that implements the <see cref="IMeasurement"/> interface.</param>        /// <param name="quality">Specific <see cref="Quality"/> value to apply to new <see cref="ArchiveDataPoint"/>.</param>        public ArchiveDataPoint(IMeasurement measurement, Quality quality)            : this((int)measurement.Key.ID)        {            this.Time = new TimeTag((DateTime)measurement.Timestamp);            this.Value = (float)measurement.AdjustedValue;            this.Quality = quality;        }         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class.        /// </summary>        /// <param name="historianID">Historian identifier of <see cref="ArchiveDataPoint"/>.</param>        /// <param name="time"><see cref="TimeTag"/> of <see cref="ArchiveDataPoint"/>.</param>        /// <param name="value">Floating-point value of <see cref="ArchiveDataPoint"/>.</param>        /// <param name="quality"><see cref="Quality"/> of <see cref="ArchiveDataPoint"/>.</param>        public ArchiveDataPoint(int historianID, TimeTag time, float value, Quality quality)            : this(historianID)        {            this.Time = time;            this.Value = value;            this.Quality = quality;        }         /// <summary>        /// Initializes a new instance of the <see cref="ArchiveDataPoint"/> class.        /// </summary>        /// <param name="historianID">Historian identifier of <see cref="ArchiveDataPoint"/>.</param>        /// <param name="buffer">Binary image to be used for initializing <see cref="ArchiveDataPoint"/>.</param>        /// <param name="startIndex">0-based starting index of initialization data in the <paramref name="buffer"/>.</param>        /// <param name="length">Valid number of bytes in <paramref name="buffer"/> from <paramref name="startIndex"/>.</param>        public ArchiveDataPoint(int historianID, byte[] buffer, int startIndex, int length)            : this(historianID)        {            ParseBinaryImage(buffer, startIndex, length);        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets the historian identifier of <see cref="ArchiveDataPoint"/>.        /// </summary>        /// <exception cref="ArgumentException">The value being assigned is not positive or -1.</exception>        public int HistorianID        {            get            {                return m_historianID;            }            set            {                if (value < 1 && value != -1)                    throw new ArgumentException("Value must be positive or -1");                 m_historianID = value;            }        }         /// <summary>        /// Gets or sets the <see cref="TimeTag"/> of <see cref="ArchiveDataPoint"/>.        /// </summary>        /// <exception cref="ArgumentException">The value being assigned is not between 01/01/1995 and 01/19/2063.</exception>        public virtual TimeTag Time        {            get            {                return m_time;            }            set            {                if (value.CompareTo(TimeTag.MinValue) < 0 || value.CompareTo(TimeTag.MaxValue) > 0)                    throw new TimeTagException("Value must between 01/01/1995 and 01/19/2063");                 m_time = value;                Flags = Flags.SetMaskedValue(MillisecondMask, m_time.ToDateTime().Millisecond << 5);            }        }         /// <summary>        /// Gets or sets the floating-point value of <see cref="ArchiveDataPoint"/>.        /// </summary>        public virtual float Value        {            get            {                return m_value;            }            set            {                m_value = value;            }        }         /// <summary>        /// Gets or sets the <see cref="Quality"/> of <see cref="ArchiveDataPoint"/>.        /// </summary>        public virtual Quality Quality        {            get            {                return (Quality)Flags.GetMaskedValue(QualityMask);            }            set            {                Flags = Flags.SetMaskedValue(QualityMask, (int)value);            }        }         /// <summary>        /// Gets or sets the associated <see cref="MetadataRecord"/> with this <see cref="ArchiveDataPoint"/>.        /// </summary>        public virtual MetadataRecord Metadata        {            get            {                return m_metadata;            }            set            {                m_metadata = value;            }        }         /// <summary>        /// Gets a boolean value that indicates whether <see cref="ArchiveDataPoint"/> contains any data.        /// </summary>        public virtual bool IsEmpty        {            get            {                return ((m_time.CompareTo(TimeTag.MinValue) == 0) &&                        (m_value == default(float)) &&                        (Quality == Quality.Unknown));            }        }         /// <summary>        /// Gets the length of the <see cref="ArchiveDataPoint"/>.        /// </summary>        public virtual int BinaryLength        {            get            {                return FixedLength;            }        }         /// <summary>        /// Gets or sets the 32-bit word used for storing data of <see cref="ArchiveDataPoint"/>.        /// </summary>        protected virtual int Flags        {            get            {                return m_flags;            }            set            {                m_flags = value;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Initializes <see cref="ArchiveDataPoint"/> from the specified <paramref name="buffer"/>.        /// </summary>        /// <param name="buffer">Binary image to be used for initializing <see cref="ArchiveDataPoint"/>.</param>        /// <param name="startIndex">0-based starting index of initialization data in the <paramref name="buffer"/>.</param>        /// <param name="length">Valid number of bytes in <paramref name="buffer"/> from <paramref name="startIndex"/>.</param>        /// <returns>Number of bytes used from the <paramref name="buffer"/> for initializing <see cref="ArchiveDataPoint"/>.</returns>        public virtual int ParseBinaryImage(byte[] buffer, int startIndex, int length)        {            if (length >= FixedLength)            {                // Binary image has sufficient data.                Flags = LittleEndian.ToInt16(buffer, startIndex + 4);                Value = LittleEndian.ToSingle(buffer, startIndex + 6);                 TimeTag value = new TimeTag(LittleEndian.ToInt32(buffer, startIndex) +       // Seconds                        ((decimal)(m_flags.GetMaskedValue(MillisecondMask) >> 5) / 1000));   // Milliseconds                 // Make sure to properly validate timestamps for newly initialized or possibly corrupted blocks                if (value.CompareTo(TimeTag.MinValue) < 0 || value.CompareTo(TimeTag.MaxValue) > 0)                    value = TimeTag.MinValue;                 Time = value;                 return FixedLength;            }                        // Binary image does not have sufficient data.            return 0;        }         /// <summary>        /// Generates binary image of the <see cref="ArchiveDataPoint"/> and copies it into the given buffer, for <see cref="BinaryLength"/> bytes.        /// </summary>        /// <param name="buffer">Buffer used to hold generated binary image of the source object.</param>        /// <param name="startIndex">0-based starting index in the <paramref name="buffer"/> to start writing.</param>        /// <returns>The number of bytes written to the <paramref name="buffer"/>.</returns>        /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception>        /// <exception cref="ArgumentOutOfRangeException">        /// <paramref name="startIndex"/> or <see cref="BinaryLength"/> is less than 0 -or-         /// <paramref name="startIndex"/> and <see cref="BinaryLength"/> will exceed <paramref name="buffer"/> length.        /// </exception>        public virtual int GenerateBinaryImage(byte[] buffer, int startIndex)        {            int length = BinaryLength;             buffer.ValidateParameters(startIndex, length);             Buffer.BlockCopy(LittleEndian.GetBytes((int)m_time.Value), 0, buffer, startIndex, 4);            Buffer.BlockCopy(LittleEndian.GetBytes((short)m_flags), 0, buffer, startIndex + 4, 2);            Buffer.BlockCopy(LittleEndian.GetBytes(m_value), 0, buffer, startIndex + 6, 4);             return length;        }         /// <summary>        /// Compares the current <see cref="ArchiveDataPoint"/> object to <paramref name="obj"/>.        /// </summary>        /// <param name="obj">Object against which the current <see cref="ArchiveDataPoint"/> object is to be compared.</param>        /// <returns>        /// Negative value if the current <see cref="ArchiveDataPoint"/> object is less than <paramref name="obj"/>,         /// Zero if the current <see cref="ArchiveDataPoint"/> object is equal to <paramref name="obj"/>,         /// Positive value if the current <see cref="ArchiveDataPoint"/> object is greater than <paramref name="obj"/>.        /// </returns>        public virtual int CompareTo(object obj)        {            ArchiveDataPoint other = obj as ArchiveDataPoint;            if (other == null)            {                return 1;            }            else            {                int result = m_historianID.CompareTo(other.HistorianID);                if (result != 0)                    return result;                else                    return m_time.CompareTo(other.Time);            }        }         /// <summary>        /// Determines whether the current <see cref="ArchiveDataPoint"/> object is equal to <paramref name="obj"/>.        /// </summary>        /// <param name="obj">Object against which the current <see cref="ArchiveDataPoint"/> object is to be compared for equality.</param>        /// <returns>true if the current <see cref="ArchiveDataPoint"/> object is equal to <paramref name="obj"/>; otherwise false.</returns>        public override bool Equals(object obj)        {            return (CompareTo(obj) == 0);        }         /// <summary>        /// Returns the text representation of <see cref="ArchiveDataPoint"/> object.        /// </summary>        /// <returns>A <see cref="string"/> value.</returns>        public override string ToString()        {            return ToString(null, null);        }         /// <summary>        /// Returns the text representation of <see cref="ArchiveDataPoint"/> object in the specified <paramref name="format"/>.        /// </summary>        /// <param name="format">Format of text output (I for ID, T for Time, V for Value, Q for Quality).</param>        /// <returns>A <see cref="string"/> value.</returns>        public virtual string ToString(string format)        {            return ToString(format, null);        }         /// <summary>        /// Returns the text representation of <see cref="ArchiveDataPoint"/> object using the specified <paramref name="provider"/>.        /// </summary>        /// <param name="provider">An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.</param>        /// <returns>A <see cref="string"/> value.</returns>        public virtual string ToString(IFormatProvider provider)        {            return ToString("", provider);        }         /// <summary>        /// Returns the text representation of <see cref="ArchiveDataPoint"/> object in the specified <paramref name="format"/>         /// using the specified <paramref name="provider"/>.        /// </summary>        /// <param name="format">Format of text output (I for ID, T for Time, V for Value, Q for Quality).</param>        /// <param name="provider">An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.</param>        /// <returns>A <see cref="string"/> value.</returns>        public virtual string ToString(string format, IFormatProvider provider)        {            if (provider == null)                provider = CultureInfo.InvariantCulture;             switch (format.ToUpperInvariant())            {                case "I":                case "ID":                    return m_historianID.ToString(provider);                case "T":                case "TIME":                    return m_time.ToString();                case "U":                case "UNIXTIME":                    return (new UnixTimeTag(m_time.ToDateTime())).Value.ToString("0.000", provider);                case "V":                case "VALUE":                    return m_value.ToString(provider);                case "Q":                case "QUALITY":                    return Quality.ToString();                case "N":                case "NAME":                    if (Metadata != null)                        return Metadata.Name;                    return "";                case "D":                case "DESCRIPTION":                    if (Metadata != null)                        return Metadata.Description;                    return "";                case "S":                case "SOURCE":                    if (Metadata != null)                        return Metadata.PlantCode;                    return "";                case "S1":                case "SYNONYM1":                    if (Metadata != null)                        return Metadata.Synonym1;                    return "";                case "S2":                case "SYNONYM2":                    if (Metadata != null)                        return Metadata.Synonym2;                    return "";                case "S3":                case "SYNONYM3":                    if (Metadata != null)                        return Metadata.Synonym3;                    return "";                default:                    throw new FormatException("Invalid format identifier specified for ArchiveDataPoint: " + format);            }        }         /// <summary>        /// Returns the hash code for the current <see cref="ArchiveDataPoint"/> object.        /// </summary>        /// <returns>A 32-bit signed integer value.</returns>        public override int GetHashCode()        {            return m_historianID.GetHashCode();        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t