//****************************************************************************************************** // DataFrame.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/27/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.Collections.Generic; using System.ComponentModel; using System.Runtime.Serialization; using GSF.IO.Checksums; using GSF.Parsing; namespace GSF.PhasorProtocols.SelFastMessage { /// /// Represents the SEL Fast Message implementation of a that can be sent or received. /// [Serializable] public class DataFrame : DataFrameBase, ISupportSourceIdentifiableFrameImage { #region [ Members ] // Fields private CommonFrameHeader m_frameHeader; #endregion #region [ Constructors ] /// /// Creates a new . /// /// /// This constructor is used by to parse a SEL Fast Message data frame. /// [EditorBrowsable(EditorBrowsableState.Never)] public DataFrame() : base(new DataCellCollection(), 0, null) { } /// /// Creates a new from specified parameters. /// /// The exact timestamp, in , of the data represented by this . /// The SEL Fast Message frame size of this . /// The SEL Fast Message destination address (PMADDR setting) for this /// /// This constructor is used by a consumer to generate a SEL Fast Message data frame. /// public DataFrame(Ticks timestamp, FrameSize frameSize, uint idCode) : base(new DataCellCollection(), timestamp, null) { IDCode = idCode; FrameSize = frameSize; } /// /// Creates a new from serialization parameters. /// /// The with populated with data. /// The source for this deserialization. protected DataFrame(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize data frame m_frameHeader = (CommonFrameHeader)info.GetValue("frameHeader", typeof(CommonFrameHeader)); } #endregion #region [ Properties ] /// /// Gets reference to the for this . /// public new DataCellCollection Cells => base.Cells as DataCellCollection; /// /// Gets or sets associated with this . /// public new ConfigurationFrame ConfigurationFrame { get => base.ConfigurationFrame as ConfigurationFrame; set => base.ConfigurationFrame = value; } /// /// Gets or sets the SEL Fast Message destination address (PMADDR setting) for this . /// public new uint IDCode { get => CommonHeader.IDCode; set => CommonHeader.IDCode = value; } /// /// Gets or sets the SEL Fast Message frame size of this . /// public FrameSize FrameSize { get => CommonHeader.FrameSize; set { CommonHeader.FrameSize = value; // We dynamically define the configuration based on frame size, SEL Fast Message // defines three distinct configurations (one per frame size) if (ConfigurationFrame is null || ConfigurationFrame.FrameSize != value) ConfigurationFrame = new ConfigurationFrame(value, MessagePeriod.DefaultRate, CommonHeader.IDCode); } } /// /// Gets or sets exact timestamp, in ticks, of the data represented by this . /// /// /// The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// public override Ticks Timestamp { get => CommonHeader.Timestamp; set { // Keep timestamp updates synchronized... CommonHeader.Timestamp = value; base.Timestamp = value; } } /// /// Gets the timestamp of this frame in NTP format. /// public new NtpTimeTag TimeTag => CommonHeader.TimeTag; /// /// Gets the identifier that is used to identify the SEL Fast Message frame. /// public int TypeID => // SEL Fast Message only defines a single frame type... 0; /// /// Gets or sets current . /// public CommonFrameHeader CommonHeader { // Make sure frame header exists - using base class timestamp to // prevent recursion (m_frameHeader doesn't exist yet) get => m_frameHeader ??= new CommonFrameHeader(FrameSize.A, base.Timestamp); set { m_frameHeader = value; if (m_frameHeader is null) return; State = m_frameHeader.State as IDataFrameParsingState; base.Timestamp = m_frameHeader.Timestamp; } } // This interface implementation satisfies ISupportFrameImage.CommonHeader ICommonHeader ISupportFrameImage.CommonHeader { get => CommonHeader; set => CommonHeader = value as CommonFrameHeader; } /// /// Gets the length of the . /// protected override int HeaderLength => CommonFrameHeader.FixedLength; /// /// Gets the binary header image of the object. /// protected override byte[] HeaderImage => CommonHeader.BinaryImage; /// /// of string based property names and values for the object. /// public override Dictionary Attributes { get { Dictionary baseAttributes = base.Attributes; baseAttributes.Add("Frame Size", $"{(byte)FrameSize}: {FrameSize}"); baseAttributes.Add("32-Bit ID Code", IDCode.ToString()); baseAttributes.Add("Register Count", CommonHeader.RegisterCount.ToString()); baseAttributes.Add("Sample Number", CommonHeader.SampleNumber.ToString()); baseAttributes.Add("Second of Century", CommonHeader.SecondOfCentury.ToString()); return baseAttributes; } } #endregion #region [ Methods ] /// /// Parses the binary header image. /// /// Binary image to parse. /// Start index into to begin parsing. /// Length of valid data within . /// The length of the data that was parsed. protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length) { // We already parsed the frame header, so we just skip past it... return CommonFrameHeader.FixedLength; } /// /// Calculates checksum of given . /// /// Buffer image over which to calculate checksum. /// Start index into to calculate checksum. /// Length of data within to calculate checksum. /// Checksum over specified portion of . protected override ushort CalculateChecksum(byte[] buffer, int offset, int length) { // SEL Fast Message uses CRC Modbus to calculate checksum for frames return buffer.ModBusCrcChecksum(offset, length); } /// /// Populates a with the data needed to serialize the target object. /// /// The to populate with data. /// The destination for this serialization. public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); // Serialize data frame info.AddValue("frameHeader", m_frameHeader, typeof(CommonFrameHeader)); } #endregion } }