Exemple #1
0
        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);
        }