// Static Methods // Delegate handler to create a new IEC 61850-90-5 data cell internal static IDataCell CreateNewCell(IChannelFrame parent, IChannelFrameParsingState <IDataCell> state, int index, byte[] buffer, int startIndex, out int parsedLength) { IDataFrameParsingState parsingState = state as IDataFrameParsingState; IConfigurationCell configurationCell = null; // With or without an associated configuration, we'll parse the data cell if (parsingState != null && parsingState.ConfigurationFrame != null) { configurationCell = parsingState.ConfigurationFrame.Cells[index]; } DataCell dataCell = new DataCell(parent as IDataFrame, configurationCell); parsedLength = dataCell.ParseBinaryImage(buffer, startIndex, 0); return(dataCell); }
/// <summary> /// Parses the binary image. /// </summary> /// <param name="buffer">Binary image to parse.</param> /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param> /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param> /// <returns>The length of the data that was parsed.</returns> /// <remarks> /// This method is overridden to ensure assignment of configuration frame. /// </remarks> public override int ParseBinaryImage(byte[] buffer, int startIndex, int length) { // Make sure configuration frame gets assigned before parsing begins... IDataFrameParsingState state = State; IConfigurationFrame configurationFrame = state.ConfigurationFrame; if (configurationFrame != null) { ConfigurationFrame = configurationFrame; // Handle normal parsing return(base.ParseBinaryImage(buffer, startIndex, length)); } // Otherwise we just skip parsing this frame... return(state.ParsedBinaryLength); }
/// <summary> /// Parses the binary header image. /// </summary> /// <param name="buffer">Binary image to parse.</param> /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param> /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param> /// <returns>The length of the data that was parsed.</returns> protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length) { IDataFrameParsingState state = State; ConfigurationFrame configurationFrame = state.ConfigurationFrame as ConfigurationFrame; // Check for unlikely occurrence of unexpected configuration frame type if ((object)configurationFrame == null) { throw new InvalidOperationException("Unexpected configuration frame encountered - BPA PDCstream configuration frame expected, cannot parse data frame."); } if (m_usePhasorDataFileFormat) { // Because in cases where PDCxchng is being used the data cell count will be smaller than the // configuration cell count - we save this count to calculate the offsets later state.CellCount = unchecked ((int)configurationFrame.CommonHeader.PmuCount); if (state.CellCount > configurationFrame.Cells.Count) { throw new InvalidOperationException("Stream/Config File Mismatch: PMU count (" + state.CellCount + ") in stream does not match defined count in configuration file (" + configurationFrame.Cells.Count + ")"); } return(CommonFrameHeader.FixedLength); } // Only need to parse what wasn't already parsed in common frame header int index = startIndex + CommonFrameHeader.FixedLength; // Parse frame timestamp uint secondOfCentury = BigEndian.ToUInt32(buffer, index); m_sampleNumber = BigEndian.ToUInt16(buffer, index + 4); index += 6; if (configurationFrame.RevisionNumber == RevisionNumber.Revision0) { Timestamp = (new NtpTimeTag(secondOfCentury, 0)).ToDateTime().Ticks + (long)((m_sampleNumber - 1) * configurationFrame.TicksPerFrame); } else { Timestamp = (new UnixTimeTag(secondOfCentury)).ToDateTime().Ticks + (long)((m_sampleNumber - 1) * configurationFrame.TicksPerFrame); } // Because in cases where PDCxchng is being used the data cell count will be smaller than the // configuration cell count - we save this count to calculate the offsets later state.CellCount = BigEndian.ToUInt16(buffer, index); index += 2; if (state.CellCount > configurationFrame.Cells.Count) { throw new InvalidOperationException("Stream/Config File Mismatch: PMU count (" + state.CellCount + ") in stream does not match defined count in configuration file (" + configurationFrame.Cells.Count + ")"); } // We'll at least retrieve legacy labels if defined (might be useful for debugging dynamic changes in data-stream) if (configurationFrame.StreamType == StreamType.Legacy) { m_legacyLabels = new string[state.CellCount]; for (int x = 0; x < state.CellCount; x++) { m_legacyLabels[x] = Encoding.ASCII.GetString(buffer, index, 4); // We don't need offsets, so we skip them... index += 8; } } return(index - startIndex); }