예제 #1
0
        public void FC023Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            lock (server.Lock)
            {
                var buffer = server.GetHoldingRegisterBuffer <float>();

                buffer[6] = 65.455F;
                buffer[7] = 24;
                buffer[8] = 25;
            }

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual1 = client.ReadWriteMultipleRegisters <float, float>(0, 2, 10, 12, new float[] { 1.211F });

            // Assert
            var expected = new float[] { 0, 0, 0, 0, 0, 1.211F, 24, 25, 0, 0 };

            Assert.True(expected.SequenceEqual(actual1.ToArray()));

            lock (server.Lock)
            {
                var actual2 = server.GetHoldingRegisterBuffer <float>().Slice(1, 10);
                Assert.True(expected.SequenceEqual(actual2.ToArray()));
            }
        }
예제 #2
0
        public async Task FC04Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            void AsyncWorkaround()
            {
                var buffer = server.GetInputRegisterBuffer <float>();

                buffer[6] = 65.455F;
                buffer[7] = 24;
                buffer[8] = 25;
            }

            lock (server.Lock)
            {
                AsyncWorkaround();
            }

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual = await client.ReadInputRegistersAsync <float>(0, 2, 10);

            // Assert
            var expected = _array;

            Assert.True(expected.SequenceEqual(actual.ToArray()));
        }
예제 #3
0
        public void HandlesBigEndian()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint, ModbusEndianness.BigEndian);

            // Act
            client.WriteMultipleRegisters(0, 0, new int[] { 0x20302020, 0x40101010, 0x11220000 });

            // Assert
            var expected = new int[] { 0x20203020, 0x10101040, 0x00002211 };

            lock (server.Lock)
            {
                var actual = server.GetHoldingRegisterBuffer <int>().Slice(0, 3);
                Assert.True(expected.SequenceEqual(actual.ToArray()));
            }
        }
예제 #4
0
        public void ClientRespectsConnectTimeout()
        {
            // Arrange
            var endpoint       = EndpointSource.GetNext();
            var connectTimeout = 500;

            var client = new ModbusTcpClient()
            {
                ConnectTimeout = connectTimeout
            };

            // Act
            var sw = Stopwatch.StartNew();

            try
            {
                client.Connect(endpoint);
            }
            catch (Exception)
            {
                // Assert
                var elapsed = sw.ElapsedMilliseconds;

                Assert.True(elapsed < connectTimeout * 2, "The connect timeout is not respected.");
            }
        }
예제 #5
0
        public async void ServerHandlesRequestFire()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            // Act
            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            await Task.Run(() =>
            {
                var data       = Enumerable.Range(0, 20).Select(i => (float)i).ToArray();
                var sw         = Stopwatch.StartNew();
                var iterations = 10000;

                for (int i = 0; i < iterations; i++)
                {
                    client.WriteMultipleRegisters(0, 0, data);
                }

                var timePerRequest = sw.Elapsed.TotalMilliseconds / iterations;
                _logger.WriteLine($"Time per request: {timePerRequest * 1000:F0} us. Frequency: {1/timePerRequest * 1000:F0} requests per second.");

                client.Disconnect();
            });

            // Assert
        }
예제 #6
0
        public void BigEndianWritePerformanceTest()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var buffer = server.GetHoldingRegisters();

            // Act
            var sw = Stopwatch.StartNew();

            for (int i = 0; i < 1_000_000; i++)
            {
                buffer.SetBigEndian(address: 1, 12334234.0);
            }

            // Assert
            var elapsed = sw.Elapsed;

            server.Stop();

            _logger.WriteLine($"Time per 1000 write operations: {elapsed.TotalMilliseconds / 1000} ms");
        }
예제 #7
0
        public void FC05Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            client.WriteSingleCoil(0, 2, true);
            client.WriteSingleCoil(0, 7, true);
            client.WriteSingleCoil(0, 9, true);
            client.WriteSingleCoil(0, 26, true);

            // Assert
            var expected = new byte[] { 132, 2, 0, 4 };

            lock (server.Lock)
            {
                var actual = server.GetCoilBuffer <byte>().Slice(0, 4);
                Assert.True(expected.SequenceEqual(actual.ToArray()));
            }
        }
예제 #8
0
        public void FC16Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            client.WriteMultipleRegisters(0, 2, _array);

            // Assert
            var expected = _array;

            lock (server.Lock)
            {
                var actual = server.GetHoldingRegisterBuffer <float>().Slice(1, 10);
                Assert.True(expected.SequenceEqual(actual.ToArray()));
            }
        }
예제 #9
0
        public async Task FC02Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            void AsyncWorkaround()
            {
                var buffer = server.GetDiscreteInputBuffer <byte>();

                buffer[1] = 9;
                buffer[2] = 0;
                buffer[3] = 24;
            }

            lock (server.Lock)
            {
                AsyncWorkaround();
            }

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual = await client.ReadDiscreteInputsAsync(0, 8, 25);

            // Assert
            var expected = new byte[] { 9, 0, 24, 0 };

            Assert.True(expected.SequenceEqual(actual.ToArray()));
        }
예제 #10
0
        public void FC06Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            client.WriteSingleRegister(0, 02, 259);
            client.WriteSingleRegister(0, 10, 125);
            client.WriteSingleRegister(0, 11, 16544);
            client.WriteSingleRegister(0, 12, 4848);

            // Assert
            var expected = new short[] { 0, 0, 259, 0, 0, 0, 0, 0, 0, 0, 125, 16544, 4848 };

            lock (server.Lock)
            {
                var actual = server.GetHoldingRegisterBuffer <short>().Slice(0, 13);
                Assert.True(expected.SequenceEqual(actual.ToArray()));
            }
        }
예제 #11
0
        public void FC01Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            lock (server.Lock)
            {
                var buffer = server.GetCoilBuffer <byte>();

                buffer[1] = 9;
                buffer[2] = 0;
                buffer[3] = 24;
            }

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual = client.ReadCoils(0, 8, 25);

            // Assert
            var expected = new byte[] { 9, 0, 24, 0 };

            Assert.True(expected.SequenceEqual(actual.ToArray()));
        }
예제 #12
0
        public async void TimeoutIsResetAfterRequest()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            var delay = TimeSpan.FromSeconds(1);

            await Task.Run(async() =>
            {
                var data = Enumerable.Range(0, 20).Select(i => (float)i).ToArray();

                // Act
                await Task.Delay(delay);
                var lastRequest1 = server.RequestHandlerSet.First().LastRequest.Elapsed;
                client.WriteMultipleRegisters(0, 0, data);
                var lastRequest2 = server.RequestHandlerSet.First().LastRequest.Elapsed;

                client.Disconnect();

                // Assert
                Assert.True(lastRequest1 >= delay);
                Assert.True(lastRequest2 < delay);
            });

            server.Stop();
        }
예제 #13
0
        public void FC03Test()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            lock (server.Lock)
            {
                var buffer = server.GetHoldingRegisterBuffer <float>();

                buffer[6] = 65.455F;
                buffer[7] = 24;
                buffer[8] = 25;
            }

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual = client.ReadHoldingRegisters <float>(0, 2, 10);

            // Assert
            var expected = _array;

            Assert.True(expected.SequenceEqual(actual.ToArray()));
        }
예제 #14
0
        public async Task BitOperationsTest()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            var expectedArray = new byte[] { 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03 };

            await Task.Run(() =>
            {
                var buffer = server.GetCoils();

                // Act + Assert
                buffer.Set(8554, true);
                buffer.Set(8556, true);
                buffer.Set(8557, true);

                var actual1 = buffer.Get(8554);
                var actual2 = buffer.Get(8555);
                var actual3 = buffer.Get(8556);
                var actual4 = buffer.Get(8557);

                Assert.True(actual1);
                Assert.False(actual2);
                Assert.True(actual3);
                Assert.True(actual4);

                buffer.Set(8557, false);
                var actual5 = buffer.Get(8557);
                Assert.False(actual5);

                buffer.Toggle(8557);
                var actual6 = buffer.Get(8557);
                Assert.True(actual6);

                buffer.Set(8607, true);
                buffer.Set(8608, true);
                var actual7 = buffer.Get(8607);
                var actual8 = buffer.Get(8608);

                Assert.True(actual7);
                Assert.True(actual8);

                buffer.Toggle(8609);
                var actual9 = buffer.Get(8609);

                Assert.True(actual9);

                var actualArray = buffer[1069..1077];
                Assert.True(actualArray.SequenceEqual(expectedArray));
            });
예제 #15
0
        public async void ServerHandlesMultipleClients()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer();

            server.Start(endpoint);

            // Act
            var clients = Enumerable.Range(0, 20).Select(index => new ModbusTcpClient()).ToList();

            var tasks = clients.Select((client, index) =>
            {
                var data = Enumerable.Range(0, 20).Select(i => (float)i).ToArray();

                client.Connect(endpoint);
                _logger.WriteLine($"Client {index}: Connected.");

                return(Task.Run(async() =>
                {
                    _logger.WriteLine($"Client {index}: Task started.");

                    for (int i = 0; i < 10; i++)
                    {
                        client.ReadHoldingRegisters <short>(0, 0, 100);
                        _logger.WriteLine($"Client {index}: ReadHoldingRegisters({i})");
                        await Task.Delay(50);
                        client.WriteMultipleRegisters(0, 0, data);
                        _logger.WriteLine($"Client {index}: WriteMultipleRegisters({i})");
                        await Task.Delay(50);
                        client.ReadCoils(0, 0, 25);
                        _logger.WriteLine($"Client {index}: ReadCoils({i})");
                        await Task.Delay(50);
                        client.ReadInputRegisters <float>(0, 0, 20);
                        _logger.WriteLine($"Client {index}: ReadInputRegisters({i})");
                        await Task.Delay(50);
                    }

                    client.Disconnect();
                }));
            }).ToList();

            await Task.WhenAll(tasks);

            server.Stop();

            // Assert
        }
예제 #16
0
        public void CanWriteMaximumNumberOfRegisters()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            client.WriteMultipleRegisters <ushort>(0, 0, new ushort[123]);
        }
예제 #17
0
        public async void ServerRespectsMaxClientConnectionLimit()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            var server = new ModbusTcpServer()
            {
                MaxConnections = 2
            };

            server.Start(endpoint);

            // Act
            var client1 = new ModbusTcpClient();
            var client2 = new ModbusTcpClient();
            var client3 = new ModbusTcpClient();

            await Task.Run(() =>
            {
                client1.Connect(endpoint);
                client1.WriteSingleRegister(1, 2, 3);

                client2.Connect(endpoint);
                client2.WriteSingleRegister(1, 2, 3);

                client3.Connect(endpoint);

                try
                {
                    client3.WriteSingleRegister(1, 2, 3);
                }

                // Windows
                catch (IOException) { }

                // Linux
                catch (InvalidOperationException) { }

                server.MaxConnections = 3;

                client3.Connect(endpoint);
                client3.WriteSingleRegister(1, 2, 3);
            });

            server.Stop();

            // Assert
        }
예제 #18
0
        public void CanReadMaximumNumberOfRegisters()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            client.ReadHoldingRegisters <ushort>(0, 0, 125);
            client.ReadInputRegisters <ushort>(0, 0, 125);
        }
예제 #19
0
        public void ThrowsWhenWritingTooManyRegisters()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            Action action = () => client.WriteMultipleRegisters <ushort>(0, 0, new ushort[124]);

            // Assert
            Assert.Throws <ModbusException>(action);
        }
예제 #20
0
        public void ThrowsIfZeroBytesAreRequested()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            Action action = () => client.ReadHoldingRegisters <byte>(0, 0, 0);

            // Assert
            Assert.Throws <ModbusException>(action);
        }
예제 #21
0
        public void ThrowsIfOddNumberOfBytesIsRequested()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            Action action = () => client.ReadHoldingRegisters <byte>(0, 0, 3);

            // Assert

            Assert.Throws <ArgumentOutOfRangeException>(action);
        }
예제 #22
0
        public void ArraySizeIsCorrectForBooleanInput()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            var actual = client.ReadHoldingRegisters <bool>(0, 0, 10).ToArray().Count();

            // Assert
            var expected = 10;

            Assert.True(actual == expected);
        }
예제 #23
0
        public void ThrowsWhenReadingTooManyRegisters()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();

            using var server = new ModbusTcpServer();
            server.Start(endpoint);

            var client = new ModbusTcpClient();

            client.Connect(endpoint);

            // Act
            Action action1 = () => client.ReadHoldingRegisters <ushort>(0, 0, 126);
            Action action2 = () => client.ReadInputRegisters <ushort>(0, 0, 126);

            // Assert
            Assert.Throws <ModbusException>(action1);
            Assert.Throws <ModbusException>(action2);
        }
예제 #24
0
        public async void ServerWorksWithExternalTcpClient()
        {
            // Arrange
            var endpoint = EndpointSource.GetNext();
            var listener = new TcpListener(endpoint);

            using var server = new ModbusTcpServer();
            var client = new ModbusTcpClient();

            var expected = new double[] { 0.1, 0.2, 0.3, 0.4, 0.5 };

            double[] actual = null;

            // Act
            listener.Start();

            var clientTask = Task.Run(() =>
            {
                client.Connect(endpoint);

                actual = client
                         .ReadWriteMultipleRegisters <double, double>(0, 0, 5, 0, expected)
                         .ToArray();

                client.Disconnect();
            });

            var serverTask = Task.Run(() =>
            {
                var tcpClient = listener.AcceptTcpClient();
                server.Start(tcpClient);
            });

            await clientTask;

            // Assert
            Assert.True(actual.SequenceEqual(expected));
        }