private async Task <SendMessageResult> sendMessageAsync(byte unitId, ReadOnlyMemory <byte> message, int timeout, CancellationToken cancellationToken) { SendMessageResult result = new SendMessageResult { Bytes = 0, Packets = 0, }; ReadOnlyMemory <byte> modbusMessage = buildSerialMessage(unitId, message); try { result.Bytes += await _client.SendAsync(modbusMessage, timeout, cancellationToken); result.Packets += 1; } catch (ObjectDisposedException) { throw new ModbusException("Failed to Send RTU Message to Modbus Device ID '" + unitId + "' on '" + RemoteHost + ":" + Port + "' - The underlying Socket Connection has been Closed"); } catch (TimeoutException) { throw new ModbusException("Failed to Send RTU Message within the Timeout Period to Modbus Device ID '" + unitId + "' on '" + RemoteHost + ":" + Port + "'"); } catch (System.Net.Sockets.SocketException e) { throw new ModbusException("Failed to Send RTU Message to Modbus Device ID '" + unitId + "' on '" + RemoteHost + ":" + Port + "'", e); } return(result); }
public async Task <ProcessRequestResult> ProcessRequestAsync(RTURequest request, int timeout, int retries, int?delayBetweenMessages, CancellationToken cancellationToken) { int attempts = 0; Memory <byte> responseMessage = new Memory <byte>(); int bytesSent = 0; int packetsSent = 0; int bytesReceived = 0; int packetsReceived = 0; DateTime startTimestamp = DateTime.UtcNow; while (attempts <= retries) { try { await _requestSemaphore.WaitAsync(cancellationToken); if (attempts > 0) { await destroyAndInitializeClient(request.UnitID, timeout, cancellationToken); } // Build the Request into a Message we can Send ReadOnlyMemory <byte> requestMessage = request.BuildMessage(); TimeSpan timeSinceLastMessage = DateTime.UtcNow.Subtract(_lastMessageTimestamp); if (delayBetweenMessages.HasValue && delayBetweenMessages.Value > 0 && timeSinceLastMessage.TotalMilliseconds < delayBetweenMessages.Value) { await Task.Delay(TimeSpan.FromMilliseconds(delayBetweenMessages.Value - timeSinceLastMessage.TotalMilliseconds), cancellationToken); } // Send the Message SendMessageResult sendResult = await sendMessageAsync(request.UnitID, requestMessage, timeout, cancellationToken); bytesSent += sendResult.Bytes; packetsSent += sendResult.Packets; // Receive a Response ReceiveMessageResult receiveResult = await receiveMessageAsync(request, request.UnitID, timeout, cancellationToken); bytesReceived += receiveResult.Bytes; packetsReceived += receiveResult.Packets; responseMessage = receiveResult.Message; break; } catch (Exception) { if (attempts >= retries) { throw; } } finally { _requestSemaphore.Release(); } // Increment the Attempts attempts++; } try { return(new ProcessRequestResult { BytesSent = bytesSent, PacketsSent = packetsSent, BytesReceived = bytesReceived, PacketsReceived = packetsReceived, Duration = DateTime.UtcNow.Subtract(startTimestamp).TotalMilliseconds, Response = RTUResponse.CreateNew(responseMessage, request), }); } catch (RTUException e) { throw new ModbusException("Received an RTU Error Response from Modbus Device ID '" + request.UnitID + "' on '" + _remoteHost + ":" + _port + "'", e); } }