225 lines · 8.8 KB · C#
RawDownload
//******************************************************************************************************//  CommonFrameHeader.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://  ----------------------------------------------------------------------------------------------------//  04/26/2009 - J. Ritchie Carroll//       Generated original version of source code.//  09/15/2009 - Stephen C. Wills//       Added new header and license agreement.//  12/17/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Runtime.Serialization;using GSF.Parsing; namespace GSF.PhasorProtocols.SelFastMessage{    /// <summary>    /// Represents the common header for all SEL Fast Message frames of data.    /// </summary>    [Serializable]    public class CommonFrameHeader : CommonHeaderBase<int>, ISerializable    {        #region [ Members ]         // Constants         /// <summary>        /// Total fixed length of <see cref="CommonFrameHeader"/>.        /// </summary>        public const ushort FixedLength = 24;         /// <summary>        /// Total header length of <see cref="CommonFrameHeader"/>.        /// </summary>        public const ushort HeaderLength = 18;         // Fields        private FrameSize m_frameSize;        private uint m_idCode;        private Ticks m_timestamp;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="CommonFrameHeader"/> from specified parameters.        /// </summary>        /// <param name="frameSize">The <see cref="SelFastMessage.FrameSize"/> of this frame.</param>        /// <param name="timestamp">The timestamp of this frame.</param>        public CommonFrameHeader(FrameSize frameSize, Ticks timestamp)        {            m_frameSize = frameSize;            m_timestamp = timestamp;        }         /// <summary>        /// Creates a new <see cref="CommonFrameHeader"/> from given <paramref name="buffer"/>.        /// </summary>        /// <param name="buffer">Buffer that contains data to parse.</param>        /// <param name="startIndex">Start index into buffer where valid data begins.</param>        public CommonFrameHeader(byte[] buffer, int startIndex)        {            // Validate SEL Fast Message data image            if (buffer[startIndex] != Common.HeaderByte1 || buffer[startIndex + 1] != Common.HeaderByte2)                throw new InvalidOperationException($"Bad data stream, expected header bytes 0xA546 as first bytes in SEL Fast Message frame, got 0x{buffer[startIndex].ToString("X").PadLeft(2, '0')}{buffer[startIndex + 1].ToString("X").PadLeft(2, '0')}");             ushort sampleCount;            uint secondOfCentury;            NtpTimeTag timetag;             // Parse relevant common header values            m_frameSize = (FrameSize)buffer[startIndex + 2];            m_idCode = BigEndian.ToUInt32(buffer, startIndex + 12);            sampleCount = BigEndian.ToUInt16(buffer, startIndex + 18);            secondOfCentury = BigEndian.ToUInt32(buffer, startIndex + 20);             // We use an NTP time tag since SEL Fast Message SOC also starts at 1/1/1900            timetag = new NtpTimeTag(secondOfCentury, 0);             // Data frames have subsecond time information, so we add this fraction of time to current seconds value            timetag = new NtpTimeTag(timetag.Value + sampleCount * 50.0M / 1000.0M);             // Cache timestamp value            m_timestamp = timetag.ToDateTime().Ticks;        }         /// <summary>        /// Creates a new <see cref="CommonFrameHeader"/> from serialization parameters.        /// </summary>        /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>        /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>        protected CommonFrameHeader(SerializationInfo info, StreamingContext context)        {            // Deserialize common frame header            m_frameSize = (FrameSize)info.GetValue("frameSize", typeof(FrameSize));            m_idCode = info.GetUInt32("idCode32Bit");        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets the timestamp of this frame in NTP format.        /// </summary>        public NtpTimeTag TimeTag => new(m_timestamp);         /// <summary>        /// Gets or sets timestamp of this <see cref="CommonFrameHeader"/>.        /// </summary>        public Ticks Timestamp        {            get => m_timestamp;            set => m_timestamp = value;        }         /// <summary>        /// Gets or sets the SEL Fast Message destination address (PMADDR setting) of this <see cref="CommonFrameHeader"/>.        /// </summary>        public uint IDCode        {            get => m_idCode;            set => m_idCode = value;        }         /// <summary>        /// Gets the SEL Fast Message second of century of this <see cref="CommonFrameHeader"/>.        /// </summary>        public uint SecondOfCentury => (uint)Math.Truncate(TimeTag.Value);         /// <summary>        /// Gets the SEL Fast Message sample number of this <see cref="CommonFrameHeader"/>.        /// </summary>        public ushort SampleNumber => (ushort)(m_timestamp.DistanceBeyondSecond().ToMilliseconds() / 50);         /// <summary>        /// Gets or sets the SEL Fast Message frame size of this <see cref="CommonFrameHeader"/>.        /// </summary>        public FrameSize FrameSize        {            get => m_frameSize;            set => m_frameSize = value;        }         /// <summary>        /// Gets the SEL Fast Message register count of this <see cref="CommonFrameHeader"/>.        /// </summary>        public ushort RegisterCount => (ushort)(DataLength / 2);         /// <summary>        /// Gets the length of the data in the SEL Fast Message frame (i.e., the <see cref="FrameSize"/> minus the <see cref="HeaderLength"/> and checksum) of this <see cref="CommonFrameHeader"/>.        /// </summary>        public ushort DataLength =>            // Data length will be frame length minus common header length minus crc16            (ushort)((ushort)m_frameSize - HeaderLength - 2);          /// <summary>        /// Gets the binary image of the common header portion of this <see cref="CommonFrameHeader"/>.        /// </summary>        public byte[] BinaryImage        {            get            {                byte[] buffer = new byte[FixedLength];                 buffer[0] = Common.HeaderByte1;                buffer[1] = Common.HeaderByte2;                buffer[2] = (byte)m_frameSize;                buffer[9] = 0x20;   // Function code                buffer[10] = 0xC0;  // Sequence byte                 // Include destination address (PMADDR setting)                BigEndian.CopyBytes(m_idCode, buffer, 12);                 // Include register count                BigEndian.CopyBytes(RegisterCount, buffer, 16);                 // Include sample number                BigEndian.CopyBytes(SampleNumber, buffer, 18);                 // Include second of century                BigEndian.CopyBytes(SecondOfCentury, buffer, 20);                 return buffer;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Populates a <see cref="SerializationInfo"/> with the data needed to serialize the target object.        /// </summary>        /// <param name="info">The <see cref="SerializationInfo"/> to populate with data.</param>        /// <param name="context">The destination <see cref="StreamingContext"/> for this serialization.</param>        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)        {            // Serialize unique common frame header values            info.AddValue("frameSize", m_frameSize, typeof(FrameSize));            info.AddValue("idCode32Bit", m_idCode);        }         #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