/// <summary> /// Parses a common header instance that implements <see cref="ICommonHeader{TTypeIdentifier}"/> for the output type represented /// in the binary image. /// </summary> /// <param name="buffer">Buffer containing data to parse.</param> /// <param name="offset">Offset index into buffer that represents where to start parsing.</param> /// <param name="length">Maximum length of valid data from offset.</param> /// <returns>The <see cref="ICommonHeader{TTypeIdentifier}"/> which includes a type ID for the <see cref="Type"/> to be parsed.</returns> /// <remarks> /// <para> /// Derived classes need to provide a common header instance (i.e., class that implements <see cref="ICommonHeader{TTypeIdentifier}"/>) /// for the output types; this will primarily include an ID of the <see cref="Type"/> that the data image represents. This parsing is /// only for common header information, actual parsing will be handled by output type via its <see cref="ISupportBinaryImage.ParseBinaryImage"/> /// method. This header image should also be used to add needed complex state information about the output type being parsed if needed. /// </para> /// <para> /// If there is not enough buffer available to parse common header (as determined by <paramref name="length"/>), return null. Also, if /// the protocol allows frame length to be determined at the time common header is being parsed and there is not enough buffer to parse /// the entire frame, it will be optimal to prevent further parsing by returning null. /// </para> /// </remarks> protected override ICommonHeader <int> ParseCommonHeader(byte[] buffer, int offset, int length) { // See if there is enough data in the buffer to parse the common frame header. if (length > CommonFrameHeader.FixedLength) { // Parse common frame header CommonFrameHeader parsedFrameHeader = new CommonFrameHeader(buffer, offset); // Derive frame length from common frame header int frameLength = (int)parsedFrameHeader.FrameSize; // We also make sure entire frame buffer image is available to be parsed if (length >= frameLength) { // Create configuration frame if it doesn't exist or frame size has changed if (m_configurationFrame == null || m_configurationFrame.FrameSize != parsedFrameHeader.FrameSize) { // Create virtual configuration frame m_configurationFrame = new ConfigurationFrame(parsedFrameHeader.FrameSize, m_messagePeriod, parsedFrameHeader.IDCode); // Notify clients of new configuration frame OnReceivedChannelFrame(m_configurationFrame); } if (m_configurationFrame != null) { // Assign common header and data frame parsing state parsedFrameHeader.State = new DataFrameParsingState(frameLength, m_configurationFrame, DataCell.CreateNewCell, TrustHeaderLength, ValidateDataFrameCheckSum); // Expose the frame buffer image in case client needs this data for any reason OnReceivedFrameBufferImage(FundamentalFrameType.DataFrame, buffer, offset, frameLength); return(parsedFrameHeader); } } } return(null); }
/// <summary> /// Creates a new <see cref="ConfigurationCell"/> from specified parameters. /// </summary> /// <param name="parent">The parent <see cref="ConfigurationFrame"/>.</param> public ConfigurationCell(ConfigurationFrame parent) : base(parent, 0, Common.MaximumPhasorValues, Common.MaximumAnalogValues, Common.MaximumDigitalValues) { }