private void ReceivedS7PlcBlocksOfTypeAckDatagram(Memory <byte> buffer) { var data = S7PlcBlocksOfTypeAckDatagram.TranslateFromMemory(buffer); if (_blocksOfTypeHandler.TryGetValue(data.UserData.Header.ProtocolDataUnitReference, out var cbh)) { if (data.UserData.Parameter.ParamErrorCode != 0) { _logger?.LogError("Error while reading blocks count for reference {0}. ParamErrorCode: {1}", data.UserData.Header.ProtocolDataUnitReference, data.UserData.Parameter.ParamErrorCode); cbh.Exception = new Dacs7ParameterException(data.UserData.Parameter.ParamErrorCode); cbh.Event.Set(null); } if (data.UserData.Data == null) { _logger?.LogWarning("No data from blocks count ack received for reference {0}", data.UserData.Header.ProtocolDataUnitReference); } cbh.Event.Set(data); } else { _logger?.LogWarning("No blocks data handler found for received read ack reference {0}", data.UserData.Header.ProtocolDataUnitReference); } }
public async Task <IEnumerable <IPlcBlock> > ReadBlocksOfTypesAsync(PlcBlockType type) { if (ConnectionState != ConnectionState.Opened) { ThrowHelper.ThrowNotConnectedException(); } var id = GetNextReferenceId(); var sequenceNumber = (byte)0x00; var blocks = new List <IPlcBlock>(); IMemoryOwner <byte> memoryOwner = null; var currentPosition = 0; var totalLength = 0; try { S7PlcBlocksOfTypeAckDatagram blocksOfTypeResults = null; do { using (var dg = S7UserDataDatagram.TranslateToMemory(S7UserDataDatagram.BuildBlocksOfTypeRequest(_s7Context, id, type, sequenceNumber), out var memoryLength)) { using (var sendData = _transport.Build(dg.Memory.Slice(0, memoryLength), out var sendLength)) { CallbackHandler <S7PlcBlocksOfTypeAckDatagram> cbh; using (await SemaphoreGuard.Async(_concurrentJobs).ConfigureAwait(false)) { cbh = new CallbackHandler <S7PlcBlocksOfTypeAckDatagram>(id); _blocksOfTypeHandler.TryAdd(cbh.Id, cbh); try { if (await _transport.Connection.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false) != SocketError.Success) { return(null); } blocksOfTypeResults = await cbh.Event.WaitAsync(_s7Context.Timeout).ConfigureAwait(false); } finally { _blocksOfTypeHandler.TryRemove(cbh.Id, out _); } } HandlerErrorResult(id, cbh, blocksOfTypeResults); if (blocksOfTypeResults.UserData.Data.UserDataLength > 0) { totalLength += blocksOfTypeResults.UserData.Data.UserDataLength; // 6 is the header if (memoryOwner == null) { memoryOwner = MemoryPool <byte> .Shared.Rent(totalLength); } else { var newMem = MemoryPool <byte> .Shared.Rent(totalLength); memoryOwner.Memory.CopyTo(newMem.Memory); memoryOwner?.Dispose(); memoryOwner = newMem; } blocksOfTypeResults.UserData.Data.Data.CopyTo(memoryOwner.Memory.Slice(currentPosition, blocksOfTypeResults.UserData.Data.UserDataLength)); currentPosition += blocksOfTypeResults.UserData.Data.UserDataLength; sequenceNumber = blocksOfTypeResults.UserData.Parameter.SequenceNumber; } else { totalLength = 0; } } } } while (blocksOfTypeResults.UserData.Parameter.LastDataUnit == 0x01); if (memoryOwner != null) { blocks = S7PlcBlocksOfTypeAckDatagram.TranslateFromSslData(memoryOwner.Memory, totalLength); } } finally { memoryOwner?.Dispose(); } return(blocks); }