private async Task <bool> WritePackage(Dictionary <WriteItem, ItemResponseRetValue> result, WritePackage normalized) { var id = GetNextReferenceId(); CallbackHandler <IEnumerable <S7DataItemWriteResult> > cbh; using (var dg = S7WriteJobDatagram.TranslateToMemory(S7WriteJobDatagram.BuildWrite(_s7Context, id, normalized.Items), out var memoryLegth)) { using (var sendData = _transport.Build(dg.Memory.Slice(0, memoryLegth), out var sendLength)) { try { IEnumerable <S7DataItemWriteResult> writeResults = null; using (await SemaphoreGuard.Async(_concurrentJobs).ConfigureAwait(false)) { cbh = new CallbackHandler <IEnumerable <S7DataItemWriteResult> >(id); _writeHandler.TryAdd(cbh.Id, cbh); try { if (await _transport.Client.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false) != SocketError.Success) { return(false); } writeResults = await cbh.Event.WaitAsync(_s7Context.Timeout).ConfigureAwait(false); } finally { _writeHandler.TryRemove(cbh.Id, out _); } } HandlerErrorResult(id, cbh, writeResults); BildResults(result, normalized, writeResults); } catch (TaskCanceledException) { ThrowHelper.ThrowTimeoutException(); } } } return(true); }
private static void BildResults(Dictionary <WriteItem, ItemResponseRetValue> result, WritePackage normalized, IEnumerable <S7DataItemWriteResult> writeResults) { var items = normalized.Items.GetEnumerator(); foreach (var item in writeResults) { if (items.MoveNext()) { var current = items.Current; if (current.IsPart) { if (result.TryGetValue(current.Parent, out var retCode) && retCode == ItemResponseRetValue.Success) { result[current.Parent] = (ItemResponseRetValue)item.ReturnCode; } } else { result[current] = (ItemResponseRetValue)item.ReturnCode; } } } }
private static IEnumerable <WritePackage> CreateWritePackages(SiemensPlcProtocolContext s7Context, IEnumerable <WriteItem> vars) { var result = new List <WritePackage>(); foreach (var item in vars.OrderByDescending(x => x.NumberOfItems).ToList()) { var currentPackage = result.FirstOrDefault(package => package.TryAdd(item)); if (currentPackage == null) { if (item.NumberOfItems > s7Context.WriteItemMaxLength) { var bytesToWrite = item.NumberOfItems; ushort processed = 0; while (bytesToWrite > 0) { var slice = Math.Min(s7Context.WriteItemMaxLength, bytesToWrite); var child = WriteItem.CreateChild(item, (ushort)(item.Offset + processed), slice); if (slice < s7Context.WriteItemMaxLength) { currentPackage = result.FirstOrDefault(package => package.TryAdd(child)); } if (currentPackage == null) { currentPackage = new WritePackage(s7Context.PduSize); if (currentPackage.TryAdd(child)) { if (currentPackage.Full) { yield return(currentPackage.Return()); if (currentPackage.Handled) { currentPackage = null; } } else { result.Add(currentPackage); } } else { ThrowHelper.ThrowCouldNotAddPackageException(nameof(WritePackage)); } } processed += slice; bytesToWrite -= slice; } } else { currentPackage = new WritePackage(s7Context.PduSize); result.Add(currentPackage); if (!currentPackage.TryAdd(item)) { ThrowHelper.ThrowCouldNotAddPackageException(nameof(WritePackage)); } } } if (currentPackage != null) { if (currentPackage.Full) { yield return(currentPackage.Return()); } if (currentPackage.Handled) { result.Remove(currentPackage); } } } foreach (var package in result) { yield return(package.Return()); } }
private async Task <bool> WritePackage(Dictionary <WriteItem, ItemResponseRetValue> result, WritePackage normalized) { var id = GetNextReferenceId(); CallbackHandler <IEnumerable <S7DataItemWriteResult> > cbh = null; using (var dg = S7WriteJobDatagram.TranslateToMemory(S7WriteJobDatagram.BuildWrite(_s7Context, id, normalized.Items), out var memoryLegth)) { using (var sendData = _transport.Build(dg.Memory.Slice(0, memoryLegth), out var sendLength)) { try { IEnumerable <S7DataItemWriteResult> writeResults = null; try { if (_concurrentJobs == null) { return(false); } using (await SemaphoreGuard.Async(_concurrentJobs).ConfigureAwait(false)) { cbh = new CallbackHandler <IEnumerable <S7DataItemWriteResult> >(id); if (_writeHandler.TryAdd(id, cbh)) { _logger?.LogTrace("Write handler 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 write package with reference <{id}>.", id); return(false); } writeResults = await cbh.Event.WaitAsync(_s7Context.Timeout).ConfigureAwait(false); } finally { _writeHandler.TryRemove(id, out _); _logger?.LogTrace("Write handler with id {id} was removed.", id); } } else { _logger?.LogWarning("Could not add write handler with reference <{id}>.", id); } } } catch (ObjectDisposedException) { if (cbh == null) { return(false); } } HandlerErrorResult(id, cbh, writeResults); BildResults(result, normalized, writeResults); } catch (TaskCanceledException) { ThrowHelper.ThrowTimeoutException(); } } } return(true); }