public async Task RetriesOnOldTransactionUsingRetryCount() { // Arrange var request = new ReadHoldingRegistersRequest(1, 1, 1); var oldResponse = new ReadOnlySequence <byte>(new byte[] { 0, 1, 0, 0, 0, 5, 1, 3, 2, 0, 0 }.AsMemory()); var newResponse = new ReadOnlySequence <byte>(new byte[] { 0, 2, 0, 0, 0, 5, 1, 3, 2, 0, 0 }.AsMemory()); var pipeAdapterMock = new Mock <IPipeResource>(); pipeAdapterMock.Setup(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); pipeAdapterMock.SetupSequence(x => x.ReadAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())) .ReturnsAsync(oldResponse) .ReturnsAsync(oldResponse) .ReturnsAsync(newResponse); var transactionIdProviderMock = new Mock <ITransactionIdProvider>(); transactionIdProviderMock.Setup(x => x.NewId()).Returns(2); var target = new ModbusTcpTransport(pipeAdapterMock.Object, transactionIdProviderMock.Object, Mock.Of <ILogger <IModbusMaster> >()) { Retries = 2 }; // Act var actual = await target.SendAsync <ReadHoldingRegistersResponse>(request); // Assert pipeAdapterMock.Verify(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>()), Times.Exactly(3)); pipeAdapterMock.Verify(x => x.ReadAsync(It.IsAny <int>(), It.IsAny <CancellationToken>()), Times.Exactly(3)); }
public async Task ReadsPipeAgainIfNotEnoughtData() { // Arrange var request = new ReadHoldingRegistersRequest(1, 1, 1); var response = new byte[] { 0, 1, 0, 0, 0, 5, 1, 3, 2, 0, 0 }; var responseSequence = new ReadOnlySequence <byte>(response.AsMemory()); var pipeAdapterMock = new Mock <IPipeResource>(); pipeAdapterMock.Setup(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); pipeAdapterMock.Setup(x => x.ReadAsync(6, It.IsAny <CancellationToken>())).ReturnsAsync(responseSequence.Slice(0, 6)); pipeAdapterMock.Setup(x => x.ReadAsync(11, It.IsAny <CancellationToken>())).ReturnsAsync(responseSequence); var transactionIdProviderMock = new Mock <ITransactionIdProvider>(); transactionIdProviderMock.Setup(x => x.NewId()).Returns(1); var target = new ModbusTcpTransport(pipeAdapterMock.Object, transactionIdProviderMock.Object, Mock.Of <ILogger <IModbusMaster> >()); // Act var actual = await target.SendAsync <ReadHoldingRegistersResponse>(request, It.IsAny <CancellationToken>()); // Assert pipeAdapterMock.Verify(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>()), Times.Once()); pipeAdapterMock.Verify(x => x.ReadAsync(6, It.IsAny <CancellationToken>()), Times.Once()); pipeAdapterMock.Verify(x => x.ReadAsync(6, It.IsAny <CancellationToken>()), Times.Once()); pipeAdapterMock.Verify(x => x.MarkExamined(responseSequence.Slice(0, 6)), Times.Once()); pipeAdapterMock.Verify(x => x.MarkConsumed(responseSequence), Times.Once()); }
public async Task ThrowsOnOldTransactionIfDifferenceIsEqualToThreshold() { // Arrange var request = new ReadHoldingRegistersRequest(1, 1, 1); var oldResponse = new ReadOnlySequence <byte>(new byte[] { 0, 3, 0, 0, 0, 5, 1, 3, 2, 0, 0 }.AsMemory()); var newResponse = new ReadOnlySequence <byte>(new byte[] { 0, 5, 0, 0, 0, 5, 1, 3, 2, 0, 0 }.AsMemory()); var pipeAdapterMock = new Mock <IPipeResource>(); pipeAdapterMock.Setup(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); pipeAdapterMock.SetupSequence(x => x.ReadAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())) .ReturnsAsync(oldResponse) .ReturnsAsync(newResponse); var transactionIdProviderMock = new Mock <ITransactionIdProvider>(); transactionIdProviderMock.Setup(x => x.NewId()).Returns(2); var target = new ModbusTcpTransport(pipeAdapterMock.Object, transactionIdProviderMock.Object, Mock.Of <ILogger <IModbusMaster> >()) { Retries = 0, RetryOnOldResponseThreshold = 2 }; // Act await Assert.ThrowsAsync <IOException>(() => target.SendAsync <ReadHoldingRegistersResponse>(request)); // Assert pipeAdapterMock.Verify(x => x.WriteAsync(It.IsAny <ReadOnlyMemory <byte> >(), It.IsAny <CancellationToken>()), Times.Once()); pipeAdapterMock.Verify(x => x.ReadAsync(It.IsAny <int>(), It.IsAny <CancellationToken>()), Times.Once()); }
public void ModbusTransportThrowsOnInvalidWaitToRetryMilliseconds(int milliseconds) { // Arrange var transport = new ModbusTcpTransport(new Mock <IPipeResource>().Object, new Mock <ITransactionIdProvider>().Object, Mock.Of <ILogger <IModbusMaster> >()); // Act/Assert Assert.Throws <ArgumentOutOfRangeException>(() => transport.WaitToRetryMilliseconds = milliseconds); }
internal void ReadFrameCompleted(IAsyncResult ar) { _log.DebugFormat("Read Frame completed {0} bytes", _stream.EndRead(ar)); byte[] frame = CollectionUtility.Concat(_mbapHeader, _messageFrame); _log.InfoFormat("RX: {0}", StringUtility.Join(", ", frame)); IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(CollectionUtility.Slice(frame, 6, frame.Length - 6)); request.TransactionID = (ushort)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); // TODO refactor ModbusTcpTransport transport = new ModbusTcpTransport(); // perform action and build response IModbusMessage response = _slave.ApplyRequest(request); response.TransactionID = request.TransactionID; // write response byte[] responseFrame = transport.BuildMessageFrame(response); _log.InfoFormat("TX: {0}", StringUtility.Join(", ", responseFrame)); _stream.BeginWrite(responseFrame, 0, responseFrame.Length, WriteCompleted, null); }
internal void ReadFrameCompleted(IAsyncResult ar) { _log.DebugFormat("Read Frame completed {0} bytes", _stream.EndRead(ar)); byte[] frame = CollectionUtility.Concat(_mbapHeader, _messageFrame); _log.InfoFormat("RX: {0}", StringUtility.Join(", ", frame)); IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(CollectionUtility.Slice(frame, 6, frame.Length - 6)); request.TransactionID = (ushort) IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frame, 0)); // TODO refactor ModbusTcpTransport transport = new ModbusTcpTransport(); // perform action and build response IModbusMessage response = _slave.ApplyRequest(request); response.TransactionID = request.TransactionID; // write response byte[] responseFrame = transport.BuildMessageFrame(response); _log.InfoFormat("TX: {0}", StringUtility.Join(", ", responseFrame)); _stream.BeginWrite(responseFrame, 0, responseFrame.Length, WriteCompleted, null); }