protected override async Task <IModbusResponse> ReadResponseAsync <TResponse>(CancellationToken token = default) { var buffer = await PipeResource.ReadAsync(MbapHeaderSizeOnResponse, token).ConfigureAwait(false); var frameDataLength = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt16(buffer.Slice(4, 2).ToSpan())); var totalLength = MbapHeaderSizeOnResponse + frameDataLength; if (buffer.Length < totalLength) { PipeResource.MarkExamined(buffer); buffer = await PipeResource.ReadAsync(totalLength, token).ConfigureAwait(false); } var processedSequence = buffer.Slice(0, MbapHeaderSizeOnResponse + frameDataLength); var response = ModbusResponseFactory.CreateResponse <TResponse>( processedSequence .Slice(MbapHeaderSizeOnResponse, processedSequence.Length - MbapHeaderSizeOnResponse) .ToSpan()); response.TransactionId = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(processedSequence.Slice(0, 2).ToSpan())); PipeResource.MarkConsumed(processedSequence); return(response); }
protected override async Task <IModbusResponse> ReadResponseAsync <TResponse>(CancellationToken token = default) { var buffer = await PipeResource.ReadAsync(ResponseFrameStartSize, token).ConfigureAwait(false); var lengthSequence = buffer.Slice(0, ResponseFrameStartSize); var frameDataLength = GetResponseDataSize(lengthSequence.ToSpan()); var totalLength = ResponseFrameStartSize + frameDataLength + CrcSize; if (buffer.Length < totalLength) { PipeResource.MarkExamined(lengthSequence); buffer = await PipeResource.ReadAsync(totalLength, token).ConfigureAwait(false); } var processedSequence = buffer.Slice(0, totalLength); var expectedCrc = crcCalculator.Calculate(processedSequence.Slice(0, totalLength - CrcSize).ToMemory()); var actualCrc = BitConverter.ToUInt16(processedSequence.Slice(totalLength - CrcSize, CrcSize).ToSpan()); if (actualCrc != expectedCrc) { PipeResource.MarkConsumed(processedSequence); throw new IOException($"Received unexpected CRC. Expected: {expectedCrc}. Received: {actualCrc}."); } var response = ModbusResponseFactory.CreateResponse <TResponse>(processedSequence.ToSpan()); PipeResource.MarkConsumed(processedSequence); return(response); }