// Attempts to cast given frame into an IEEE 1344 configuration frame - theoretically this will // allow the same configuration frame to be used for any protocol implementation internal static ConfigurationFrame CastToDerivedConfigurationFrame(IConfigurationFrame sourceFrame) { // See if frame is already an IEEE 1344 configuration frame (if so, we don't need to do any work) ConfigurationFrame derivedFrame = sourceFrame as ConfigurationFrame; if (derivedFrame == null) { // Create a new IEEE 1344 configuration frame converted from equivalent configuration information ConfigurationCell derivedCell; IFrequencyDefinition sourceFrequency; derivedFrame = new ConfigurationFrame(sourceFrame.IDCode, sourceFrame.Timestamp, sourceFrame.FrameRate); foreach (IConfigurationCell sourceCell in sourceFrame.Cells) { // Create new derived configuration cell derivedCell = new ConfigurationCell(derivedFrame, sourceCell.IDCode, sourceCell.NominalFrequency); // Create equivalent derived phasor definitions foreach (IPhasorDefinition sourcePhasor in sourceCell.PhasorDefinitions) { derivedCell.PhasorDefinitions.Add(new PhasorDefinition(derivedCell, sourcePhasor.Label, sourcePhasor.ScalingValue, sourcePhasor.Offset, sourcePhasor.PhasorType, null)); } // Create equivalent derived frequency definition sourceFrequency = sourceCell.FrequencyDefinition; if (sourceFrequency != null) { derivedCell.FrequencyDefinition = new FrequencyDefinition(derivedCell, sourceFrequency.Label); } // IEEE 1344 does not define analog values... // Create equivalent derived digital definitions foreach (IDigitalDefinition sourceDigital in sourceCell.DigitalDefinitions) { derivedCell.DigitalDefinitions.Add(new DigitalDefinition(derivedCell, sourceDigital.Label)); } // Add cell to frame derivedFrame.Cells.Add(derivedCell); // IEEE-1344 only supports one cell break; } } return(derivedFrame); }
/// <summary> /// Raises the <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event. /// </summary> /// <param name="frame"><see cref="IConfigurationFrame"/> to send to <see cref="FrameParserBase{TypeIndentifier}.ReceivedConfigurationFrame"/> event.</param> protected override void OnReceivedConfigurationFrame(IConfigurationFrame frame) { // IEEE 1344 configuration frames can span multiple frame images, so we don't allow base class to raise this event until all frames have been assembled... ISupportFrameImage <FrameType> frameImage = frame as ISupportFrameImage <FrameType>; if (frameImage != null) { CommonFrameHeader commonHeader = frameImage.CommonHeader as CommonFrameHeader; if (commonHeader != null && commonHeader.IsLastFrame) { base.OnReceivedConfigurationFrame(frame); // Cache new configuration frame for parsing subsequent data frames... ConfigurationFrame configurationFrame = frame as ConfigurationFrame; if (configurationFrame != null) { m_configurationFrame = configurationFrame; } } } }
/// <summary> /// Creates a new <see cref="CommonFrameHeader"/> from given <paramref name="buffer"/>. /// </summary> /// <param name="configurationFrame">IEEE 1344 <see cref="ConfigurationFrame"/> if already parsed.</param> /// <param name="buffer">Buffer that contains data to parse.</param> /// <param name="startIndex">Start index into buffer where valid data begins.</param> public CommonFrameHeader(ConfigurationFrame configurationFrame, byte[] buffer, int startIndex) { uint secondOfCentury = BigEndian.ToUInt32(buffer, startIndex); m_sampleCount = BigEndian.ToUInt16(buffer, startIndex + 4); // We go ahead and pre-grab cell's status flags so we can determine framelength - we // leave startindex at 6 so that cell will be able to parse flags as needed - note // this increases needed common frame header size by 2 (i.e., BinaryLength + 2) m_statusFlags = BigEndian.ToUInt16(buffer, startIndex + FixedLength); // NTP timestamps based on NtpTimeTag class are designed to work for dates between // 1968-01-20 and 2104-02-26 based on recommended bit interpretation in RFC-2030. NtpTimeTag timetag = new NtpTimeTag(secondOfCentury, 0); // Data frames have subsecond time information, so we add this fraction of time to current seconds value if (TypeID == IEEE1344.FrameType.DataFrame && configurationFrame != null) { timetag.Value += SampleCount / Math.Truncate((double)Common.MaximumSampleCount / (double)configurationFrame.Period) / (double)configurationFrame.FrameRate; } // Cache timestamp value m_timestamp = timetag.ToDateTime().Ticks; }
/// <summary> /// Creates a new <see cref="ConfigurationCell"/> from specified parameters. /// </summary> /// <param name="parent">The reference to parent <see cref="ConfigurationFrame"/> of this <see cref="ConfigurationCell"/>.</param> /// <param name="idCode">The numeric ID code for this <see cref="ConfigurationCell"/>.</param> /// <param name="nominalFrequency">The nominal <see cref="LineFrequency"/> of the <see cref="FrequencyDefinition"/> of this <see cref="ConfigurationCell"/>.</param> public ConfigurationCell(ConfigurationFrame parent, ulong idCode, LineFrequency nominalFrequency) : this(parent) { IDCode = idCode; NominalFrequency = nominalFrequency; }
/// <summary> /// Creates a new <see cref="DataFrame"/> from specified parameters. /// </summary> /// <param name="timestamp">The exact timestamp, in <see cref="Ticks"/>, of the data represented by this <see cref="DataFrame"/>.</param> /// <param name="configurationFrame">The <see cref="ConfigurationFrame"/> associated with this <see cref="DataFrame"/>.</param> /// <remarks> /// This constructor is used by a consumer to generate an IEEE 1344 data frame. /// </remarks> public DataFrame(Ticks timestamp, ConfigurationFrame configurationFrame) : base(new DataCellCollection(), timestamp, configurationFrame) { }