public bool TryReadFrame(ref ReadOnlySequence <byte> buffer, out Frame frame) { var sequenceReader = new SequenceReader <byte>(buffer); frame = Frame.InvalidFrame; if (!headerReader.TryReadHeader(ref sequenceReader, out var header)) { return(false); } var frameSizeIncludingOpeningAndEndingFlags = header.FrameSize + 2; // Ensure that we have a complete frame. if (sequenceReader.Remaining < (frameSizeIncludingOpeningAndEndingFlags - sequenceReader.Consumed)) { return(false); } /// Check var frameBody = sequenceReader.Sequence.Slice(header.StartPosition, header.FrameSize - FRAME_CHECK_SEQUENCE_LENGTH).ToArray(); var frameCheckSequenceBytes = sequenceReader.Sequence.Slice((header.StartPosition + header.FrameSize) - 2, FRAME_CHECK_SEQUENCE_LENGTH).ToArray(); var frameCheckSequence = (ushort)(frameCheckSequenceBytes[1] << 8 | frameCheckSequenceBytes[0]); if (!cyclicRedundancyChecker.Check(frameCheckSequence, frameBody)) { return(false); } // Advance past the LLC PDU section. Nothing relevant here. sequenceReader.Advance(8); // Skip reading this byte since not all meters sends this byte // 09 which indicates the COSEM datatype "octet-string" is propably found to be redundant as we will always have a timestamp here. if (sequenceReader.TryPeek(out var dataType)) { if (dataType == 0x09) { sequenceReader.Advance(1); } } var timeStamp = dateTimeReader.Read(ref sequenceReader); var payload = payLoadReader.Read(ref sequenceReader); frame = new Frame(header, timeStamp, payload); // Advance past the frame check sequence bytes and the end flag; sequenceReader.Advance(3); return(true); }