public async Task <IEnumerable <IPlcAlarm> > ReadPendingAlarmsAsync() { if (ConnectionState != ConnectionState.Opened) { ThrowHelper.ThrowNotConnectedException(); } var id = GetNextReferenceId(); var sequenceNumber = (byte)0x00; var alarms = new List <IPlcAlarm>(); IMemoryOwner <byte> memoryOwner = null; var currentPosition = 0; var totalLength = 0; try { S7PendingAlarmAckDatagram alarmResults = null; do { using (var dg = S7UserDataDatagram.TranslateToMemory(S7UserDataDatagram.BuildPendingAlarmRequest(_s7Context, id, sequenceNumber), out var memoryLength)) { using (var sendData = _transport.Build(dg.Memory.Slice(0, memoryLength), out var sendLength)) { CallbackHandler <S7PendingAlarmAckDatagram> cbh; using (await SemaphoreGuard.Async(_concurrentJobs).ConfigureAwait(false)) { cbh = new CallbackHandler <S7PendingAlarmAckDatagram>(id); _alarmHandler.TryAdd(cbh.Id, cbh); try { if (await _transport.Client.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false) != SocketError.Success) { return(null); } alarmResults = await cbh.Event.WaitAsync(_s7Context.Timeout).ConfigureAwait(false); } finally { _alarmHandler.TryRemove(cbh.Id, out _); } } HandleErrorResult(id, cbh, alarmResults); if (alarmResults.UserData.Data.UserDataLength > 4) { if (memoryOwner == null) { totalLength = BinaryPrimitives.ReadUInt16BigEndian(alarmResults.UserData.Data.Data.Span.Slice(4, 2)) + 6; // 6 is the header memoryOwner = MemoryPool <byte> .Shared.Rent(totalLength); } alarmResults.UserData.Data.Data.CopyTo(memoryOwner.Memory.Slice(currentPosition, alarmResults.UserData.Data.Data.Length)); currentPosition += alarmResults.UserData.Data.Data.Length; sequenceNumber = alarmResults.UserData.Parameter.SequenceNumber; } else { totalLength = 0; } } } } while (alarmResults.UserData.Parameter.LastDataUnit == 0x01); if (memoryOwner != null) { alarms = S7PendingAlarmAckDatagram.TranslateFromSslData(memoryOwner.Memory, totalLength); } } finally { memoryOwner?.Dispose(); } return(alarms); }
public async Task <IEnumerable <IPlcAlarm> > ReadPendingAlarmsAsync() { if (_closeCalled || ConnectionState != ConnectionState.Opened) { ThrowHelper.ThrowNotConnectedException(); } var id = GetNextReferenceId(); var sequenceNumber = (byte)0x00; var alarms = new List <IPlcAlarm>(); IMemoryOwner <byte> memoryOwner = null; var currentPosition = 0; var totalLength = 0; try { S7PendingAlarmAckDatagram alarmResults = null; do { using (var dg = S7UserDataDatagram.TranslateToMemory(S7UserDataDatagram.BuildPendingAlarmRequest(_s7Context, id, sequenceNumber), out var memoryLength)) { using (var sendData = _transport.Build(dg.Memory.Slice(0, memoryLength), out var sendLength)) { CallbackHandler <S7PendingAlarmAckDatagram> cbh = null; try { using (await SemaphoreGuard.Async(_concurrentJobs).ConfigureAwait(false)) { cbh = new CallbackHandler <S7PendingAlarmAckDatagram>(id); if (_alarmHandler.TryAdd(id, cbh)) { _logger?.LogTrace("Alarmhandler with id {id} was added.", id); try { if (await _transport.Connection.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false) != SocketError.Success) { // we return false, because if one send faild we expect also all other ones failed. _logger?.LogWarning("Could not send read pending alarm package with reference <{id}>.", id); return(null); } alarmResults = await cbh.Event.WaitAsync(_s7Context.Timeout).ConfigureAwait(false); } finally { _alarmHandler.TryRemove(id, out _); _logger?.LogTrace("Alarmhandler with id {id} was removed.", id); } } else { _logger?.LogWarning("Could not add pending alarm handler with reference <{id}>.", id); } } } catch (ObjectDisposedException) { if (cbh == null) { return(alarms); // client was shut down without any result, so we return an empty list. } // if we have a result we could handle it. } HandleErrorResult(id, cbh, alarmResults); if (alarmResults.UserData.Data.UserDataLength > 4) { if (memoryOwner == null) { totalLength = BinaryPrimitives.ReadUInt16BigEndian(alarmResults.UserData.Data.Data.Span.Slice(4, 2)) + 6; // 6 is the header memoryOwner = MemoryPool <byte> .Shared.Rent(totalLength); } alarmResults.UserData.Data.Data.CopyTo(memoryOwner.Memory.Slice(currentPosition, alarmResults.UserData.Data.Data.Length)); currentPosition += alarmResults.UserData.Data.Data.Length; sequenceNumber = alarmResults.UserData.Parameter.SequenceNumber; } else { totalLength = 0; } } } } while (alarmResults.UserData.Parameter.LastDataUnit == 0x01); if (memoryOwner != null) { alarms = S7PendingAlarmAckDatagram.TranslateFromSslData(memoryOwner.Memory, totalLength); } } finally { memoryOwner?.Dispose(); } return(alarms); }