You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2018/07/26 11:38:58 UTC

[incubator-plc4x] branch master updated (6adebdf -> 9e05e64)

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git.


    from 6adebdf  fixed calender tests and simplified assertions while at it
     new 5f3d7ab  removed unsused method (cleanup for 6adebdf)
     new 14d5585  added BigInteger support on modbus and ads
     new 9efd47c  fixed documentation of test class javadoc
     new 18bb3f3  modbus: fixed coil parsing
     new 9e05e64  modbus protocol test: increased readability by extracting duplicate code

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../ads/protocol/util/LittleEndianDecoder.java     |  12 ++
 .../ads/protocol/util/LittleEndianEncoder.java     |  18 +++
 .../base/protocol/Plc4XSupportedDataTypes.java     |  20 ++-
 .../java/modbus/netty/Plc4XModbusProtocol.java     |  55 ++++++-
 .../plc4x/java/modbus/ManualPlc4XModbusTest.java   |  44 ++++--
 .../java/modbus/netty/Plc4XModbusProtocolTest.java | 173 +++++++++------------
 6 files changed, 200 insertions(+), 122 deletions(-)


[incubator-plc4x] 04/05: modbus: fixed coil parsing

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 18bb3f3a561e1d8d4a71712b7b3df0dfd6d50391
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 26 12:54:47 2018 +0200

    modbus: fixed coil parsing
---
 .../java/modbus/netty/Plc4XModbusProtocol.java     |  7 ++--
 .../plc4x/java/modbus/ManualPlc4XModbusTest.java   | 44 +++++++++++++++-----
 .../java/modbus/netty/Plc4XModbusProtocolTest.java | 47 +++++++++++-----------
 3 files changed, 63 insertions(+), 35 deletions(-)

diff --git a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
index b4914a8..769d17d 100644
--- a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
+++ b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
@@ -401,12 +401,13 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
         }
         byteBuf.readBytes(bytes);
         List<T> data = new LinkedList<>();
-        for (int i = 0, j = 0; i < readRequestItem.getSize(); i++) {
-            if (i != 0 && i % 8 == 0) {
+        for (int i = 0, j = 0; data.size() < readRequestItem.getSize(); i++) {
+            if (i > 7) {
                 // Every 8 Coils we need to increase the access
                 j++;
+                i = 0;
             }
-            boolean coilSet = (1 << i & bytes[j]) == 1;
+            boolean coilSet = (bytes[j] & (1L << i)) != 0;
             byte coilFlag = coilSet ? (byte) 1 : (byte) 0;
             if (dataType == Boolean.class) {
                 @SuppressWarnings("unchecked")
diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
index 36c5ff8..a37a702 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/ManualPlc4XModbusTest.java
@@ -21,9 +21,12 @@ package org.apache.plc4x.java.modbus;
 import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.connection.PlcConnection;
 import org.apache.plc4x.java.api.connection.PlcReader;
+import org.apache.plc4x.java.api.connection.PlcWriter;
 import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
 import org.apache.plc4x.java.api.messages.specific.TypeSafePlcReadRequest;
 import org.apache.plc4x.java.api.messages.specific.TypeSafePlcReadResponse;
+import org.apache.plc4x.java.api.messages.specific.TypeSafePlcWriteRequest;
+import org.apache.plc4x.java.api.messages.specific.TypeSafePlcWriteResponse;
 import org.apache.plc4x.java.api.model.Address;
 
 import java.util.concurrent.CompletableFuture;
@@ -42,16 +45,39 @@ public class ManualPlc4XModbusTest {
         try (PlcConnection plcConnection = new PlcDriverManager().getConnection(connectionUrl)) {
             System.out.println("PlcConnection " + plcConnection);
 
-            PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
+            {
+                PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
 
-            Address address = plcConnection.parseAddress("register:7");
-            CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
-                .read(new TypeSafePlcReadRequest<>(Integer.class, address));
-            TypeSafePlcReadResponse<Integer> readResponse = response.get();
-            System.out.println("Response " + readResponse);
-            ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
-            System.out.println("ResponseItem " + responseItem);
-            responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+                Address address = plcConnection.parseAddress("register:7");
+                CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
+                    .read(new TypeSafePlcReadRequest<>(Integer.class, address));
+                TypeSafePlcReadResponse<Integer> readResponse = response.get();
+                System.out.println("Response " + readResponse);
+                ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
+                System.out.println("ResponseItem " + responseItem);
+                responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+            }
+
+            {
+                PlcReader reader = plcConnection.getReader().orElseThrow(() -> new RuntimeException("No Reader found"));
+
+                Address address = plcConnection.parseAddress("coil:1");
+                CompletableFuture<TypeSafePlcReadResponse<Integer>> response = reader
+                    .read(new TypeSafePlcReadRequest<>(Integer.class, address));
+                TypeSafePlcReadResponse<Integer> readResponse = response.get();
+                System.out.println("Response " + readResponse);
+                ReadResponseItem<Integer> responseItem = readResponse.getResponseItem().orElseThrow(() -> new RuntimeException("No Item found"));
+                System.out.println("ResponseItem " + responseItem);
+                responseItem.getValues().stream().map(integer -> "Value: " + integer).forEach(System.out::println);
+            }
+
+            {
+                PlcWriter writer = plcConnection.getWriter().orElseThrow(() -> new RuntimeException("No Writer found"));
+                Address address = plcConnection.parseAddress("coil:1");
+                CompletableFuture<TypeSafePlcWriteResponse<Integer>> write = writer.write(new TypeSafePlcWriteRequest<>(Integer.class, address, 1));
+                TypeSafePlcWriteResponse<Integer> writeResponse = write.get();
+                System.out.println("Response " + writeResponse);
+            }
         } catch (Exception e) {
             e.printStackTrace();
             System.exit(1);
diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
index f28cb69..01b8d75 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
@@ -24,7 +24,6 @@ import com.digitalpetri.modbus.requests.*;
 import com.digitalpetri.modbus.responses.*;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
-import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
@@ -51,7 +50,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.defaultAssert;
-import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.streamOfLittleEndianDataTypePairs;
+import static org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes.streamOfBigEndianDataTypePairs;
 import static org.apache.plc4x.java.base.util.Assert.assertByteEquals;
 import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.assertEquals;
@@ -95,7 +94,7 @@ public class Plc4XModbusProtocolTest {
 
     @Parameterized.Parameters(name = "{index} Type:{0} {3} {5}")
     public static Collection<Object[]> data() {
-        return streamOfLittleEndianDataTypePairs()
+        return streamOfBigEndianDataTypePairs()
             .map(pair -> Stream.of(
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -103,7 +102,9 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(pair.getLeft().getClass(), CoilModbusAddress.of("coil:1"))
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadCoilsResponse(Unpooled.wrappedBuffer(pair.getRight())))
+                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+                    // all positive so we return one byte with the first bit set
+                    new ModbusTcpPayload((short) 0, (short) 0, new ReadCoilsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x1})))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -111,7 +112,9 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(CoilModbusAddress.of("coil:1"), pair.getLeft())
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, pair.getRight()[0]))
+                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+                    // all positive so we return one byte with the first bit set
+                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, 1))
                 ),
                 /* Read request no supported on maskwrite so how to handle?
                 ImmutablePair.of(
@@ -136,7 +139,9 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(pair.getLeft().getClass(), ReadDiscreteInputsModbusAddress.of("readdiscreteinputs:1"))
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(pair.getRight())))
+                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
+                    // all positive so we return one byte with the first bit set
+                    new ModbusTcpPayload((short) 0, (short) 0, new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x01})))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -144,7 +149,7 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(pair.getLeft().getClass(), ReadHoldingRegistersModbusAddress.of("readholdingregisters:1"))
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(evenUp(pair.getRight()))))
+                    new ModbusTcpPayload((short) 0, (short) 0, new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -152,7 +157,7 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(pair.getLeft().getClass(), ReadInputRegistersModbusAddress.of("readinputregisters:1"))
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadInputRegistersResponse(Unpooled.wrappedBuffer(evenUp(pair.getRight()))))
+                    new ModbusTcpPayload((short) 0, (short) 0, new ReadInputRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -176,19 +181,15 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(RegisterModbusAddress.of("register:1"), pair.getLeft())
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, pair.getRight()[0]))
+                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, cutRegister(pair.getRight())[0]))
                 )
             ))
             .flatMap(stream -> stream)
             .map(pair -> new Object[]{pair.left.getRequest().getRequestItem().orElseThrow(IllegalStateException::new).getDatatype().getSimpleName(), pair.left, pair.left.getResponseFuture(), pair.left.getRequest().getClass().getSimpleName(), pair.right, pair.right.getModbusPdu().getClass().getSimpleName()}).collect(Collectors.toList());
     }
 
-    private static byte[] evenUp(byte[] bytes) {
-        if (bytes.length % 2 == 0) {
-            return bytes;
-        } else {
-            return ArrayUtils.insert(0, bytes, (byte) 0x0);
-        }
+    private static byte[] cutRegister(byte[] right) {
+        return new byte[]{right.length > 1 ? right[right.length - 2] : 0x0, right[right.length - 1]};
     }
 
     @Before
@@ -371,35 +372,35 @@ public class Plc4XModbusProtocolTest {
         ResponseItem responseItem = (ResponseItem) plcResponse.getResponseItem().get();
         LOGGER.info("ResponseItem {}", responseItem);
         ModbusPdu modbusPdu = modbusTcpPayload.getModbusPdu();
-        if (modbusPdu instanceof MaskWriteRegisterRequest) {
+        if (modbusPdu instanceof MaskWriteRegisterResponse) {
             WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
             assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
-        } else if (modbusPdu instanceof ReadCoilsRequest) {
+        } else if (modbusPdu instanceof ReadCoilsResponse) {
             ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
             Object value = readResponseItem.getValues().get(0);
             defaultAssert(value);
-        } else if (modbusPdu instanceof ReadDiscreteInputsRequest) {
+        } else if (modbusPdu instanceof ReadDiscreteInputsResponse) {
             ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
             Object value = readResponseItem.getValues().get(0);
             defaultAssert(value);
-        } else if (modbusPdu instanceof ReadHoldingRegistersRequest) {
+        } else if (modbusPdu instanceof ReadHoldingRegistersResponse) {
             ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
             Object value = readResponseItem.getValues().get(0);
             defaultAssert(value);
-        } else if (modbusPdu instanceof ReadInputRegistersRequest) {
+        } else if (modbusPdu instanceof ReadInputRegistersResponse) {
             ReadResponseItem readResponseItem = (ReadResponseItem) responseItem;
             Object value = readResponseItem.getValues().get(0);
             defaultAssert(value);
-        } else if (modbusPdu instanceof WriteMultipleCoilsRequest) {
+        } else if (modbusPdu instanceof WriteMultipleCoilsResponse) {
             WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
             assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
-        } else if (modbusPdu instanceof WriteMultipleRegistersRequest) {
+        } else if (modbusPdu instanceof WriteMultipleRegistersResponse) {
             WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
             assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
         } else if (modbusPdu instanceof WriteSingleCoilResponse) {
             WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
             assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
-        } else if (modbusPdu instanceof WriteSingleRegisterRequest) {
+        } else if (modbusPdu instanceof WriteSingleRegisterResponse) {
             WriteResponseItem writeResponseItem = (WriteResponseItem) responseItem;
             assertEquals(ResponseCode.OK, writeResponseItem.getResponseCode());
         }


[incubator-plc4x] 03/05: fixed documentation of test class javadoc

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 9efd47c32a6d5d8125636b020dadd80f3097f982
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 26 11:38:22 2018 +0200

    fixed documentation of test class javadoc
---
 .../apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java    | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java b/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
index f84e532..3585d94 100644
--- a/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
+++ b/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
@@ -80,7 +80,7 @@ public class Plc4XSupportedDataTypes {
     }
 
     /**
-     * A {@link Stream} of instances of {@link Class}es plc4x can currently support with their according byte representation.
+     * A {@link Stream} of instances of {@link Class}es plc4x can currently support with their according little endian byte representation.
      *
      * @return a stream of {@link org.apache.commons.lang3.tuple.Pair}s of instances and their byte values.
      * @see #streamOfPlc4XSupportedDataTypes
@@ -90,7 +90,7 @@ public class Plc4XSupportedDataTypes {
     }
 
     /**
-     * A {@link Stream} of instances of {@link Class}es which are defined by {@code inputStream} can currently support with their according byte representation.
+     * A {@link Stream} of instances of {@link Class}es which are defined by {@code inputStream} can currently support with their according little endian byte representation.
      *
      * @param inputStream a stream of {@link org.apache.commons.lang3.tuple.Pair}s of instances and their byte values.
      * @see #streamOfPlc4XSupportedDataTypes
@@ -102,7 +102,7 @@ public class Plc4XSupportedDataTypes {
     }
 
     /**
-     * A {@link Stream} of instances of {@link Class}es plc4x can currently support with their according little endian byte representation.
+     * A {@link Stream} of instances of {@link Class}es plc4x can currently support with their according big endian byte representation.
      *
      * @return a stream of {@link org.apache.commons.lang3.tuple.Pair}s of instances and their byte values.
      * @see #streamOfPlc4XSupportedDataTypes


[incubator-plc4x] 01/05: removed unsused method (cleanup for 6adebdf)

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 5f3d7ab9371959b75fbab2768cc8deb4dc046cd8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 19 16:15:58 2018 +0200

    removed unsused method (cleanup for 6adebdf)
---
 .../apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java    | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
index d7dd942..42b882e 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
@@ -393,13 +393,6 @@ public class Plc4XModbusProtocolTest {
         }
     }
 
-    private <T> void assertPayloadDependentEquals(Class<T> expectedType, Object actual, T expected) {
-        if (!payloadClazzName.equalsIgnoreCase(expectedType.getSimpleName())) {
-            return;
-        }
-        assertThat(actual, equalTo(expected));
-    }
-
     private void syncInvoiceId() throws Exception {
         Field transactionId = SUT.getClass().getDeclaredField("transactionId");
         transactionId.setAccessible(true);


[incubator-plc4x] 02/05: added BigInteger support on modbus and ads

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 14d558505a519cadfa7045a6b0b9e6b097362530
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 26 11:13:58 2018 +0200

    added BigInteger support on modbus and ads
---
 .../ads/protocol/util/LittleEndianDecoder.java     | 12 ++++++
 .../ads/protocol/util/LittleEndianEncoder.java     | 18 ++++++++
 .../base/protocol/Plc4XSupportedDataTypes.java     | 14 ++++---
 .../java/modbus/netty/Plc4XModbusProtocol.java     | 48 ++++++++++++++++++++++
 .../java/modbus/netty/Plc4XModbusProtocolTest.java | 16 +++++++-
 5 files changed, 101 insertions(+), 7 deletions(-)

diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
index 3539be0..dcea26f 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
@@ -18,6 +18,7 @@
  */
 package org.apache.plc4x.java.ads.protocol.util;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.plc4x.java.ads.api.commands.types.Length;
 import org.apache.plc4x.java.ads.api.commands.types.TimeStamp;
 import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
@@ -97,6 +98,10 @@ public class LittleEndianDecoder {
             } else if (datatype == Integer.class) {
                 decodeInteger(safeLengthAdsData, i, result);
                 i += 4;
+            } else if (datatype == BigInteger.class) {
+                decodeBigInteger(safeLengthAdsData, result);
+                // A big integer can consume the whole stream
+                i = length;
             } else if (datatype == Float.class) {
                 decodeFloat(safeLengthAdsData, i, result);
                 i += 4;
@@ -143,6 +148,13 @@ public class LittleEndianDecoder {
         result.add((byteOne & 0xff) | ((byteTwo & 0xff) << 8) | ((byteThree & 0xff) << 16) | (byteFour & 0xff) << 24);
     }
 
+    private static void decodeBigInteger(byte[] adsData, List<Object> result) {
+        byte[] clone = ArrayUtils.clone(adsData);
+        ArrayUtils.reverse(clone);
+        byte[] bigIntegerByteArray = ArrayUtils.insert(0, clone, (byte) 0x0);
+        result.add(new BigInteger(bigIntegerByteArray));
+    }
+
     private static void decodeFloat(byte[] adsData, int i, List<Object> result) {
         byte byteOne = adsData[i];
         byte byteTwo = adsData[i + 1];
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
index 5c75a61..6b147c5 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
@@ -39,6 +39,7 @@ public class LittleEndianEncoder {
         // Utility class
     }
 
+    // TODO: add bound checking
     public static byte[] encodeData(Class<?> valueType, Object... values) throws PlcProtocolException {
         if (values.length == 0) {
             return new byte[]{};
@@ -52,6 +53,8 @@ public class LittleEndianEncoder {
             result = encodeShort(Arrays.stream(values).map(Short.class::cast));
         } else if (valueType == Integer.class) {
             result = encodeInteger(Arrays.stream(values).map(Integer.class::cast));
+        } else if (valueType == BigInteger.class) {
+            result = encodeBigInteger(Arrays.stream(values).map(BigInteger.class::cast));
         } else if (valueType == Calendar.class || Calendar.class.isAssignableFrom(valueType)) {
             result = encodeCalendar(Arrays.stream(values).map(Calendar.class::cast));
         } else if (valueType == Float.class) {
@@ -128,6 +131,21 @@ public class LittleEndianEncoder {
             });
     }
 
+    private static Stream<byte[]> encodeBigInteger(Stream<BigInteger> bigIntegerStream) {
+        return bigIntegerStream
+            .map(bigIntValue -> {
+                byte[] bytes = bigIntValue.toByteArray();
+                if (bytes[0] == 0x0) {
+                    byte[] subArray = ArrayUtils.subarray(bytes, 1, bytes.length);
+                    ArrayUtils.reverse(subArray);
+                    return subArray;
+                } else {
+                    ArrayUtils.reverse(bytes);
+                    return bytes;
+                }
+            });
+    }
+
     private static Stream<byte[]> encodeCalendar(Stream<Calendar> calendarStream) {
         return calendarStream
             .map(Calendar.class::cast)
diff --git a/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java b/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
index a8dc32c..f84e532 100644
--- a/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
+++ b/plc4j/protocols/driver-bases/test/src/main/java/org/apache/plc4x/java/base/protocol/Plc4XSupportedDataTypes.java
@@ -23,6 +23,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 
 import java.io.Serializable;
+import java.math.BigInteger;
 import java.util.*;
 import java.util.stream.Stream;
 
@@ -41,11 +42,12 @@ public class Plc4XSupportedDataTypes {
         littleEndianMap.put(Boolean.class, ImmutablePair.of(Boolean.TRUE, new byte[]{0x01}));
         littleEndianMap.put(Byte.class, ImmutablePair.of(Byte.valueOf("1"), new byte[]{0x1}));
         littleEndianMap.put(Short.class, ImmutablePair.of(Short.valueOf("1"), new byte[]{0x1, 0x0}));
-        littleEndianMap.put(Calendar.class, ImmutablePair.of(calenderInstance, new byte[]{0x0, (byte) 0x80, 0x3E, 0x15, (byte) 0xAB, 0x47, (byte) 0xFC, 0x28}));
-        littleEndianMap.put(GregorianCalendar.class, littleEndianMap.get(Calendar.class));
         littleEndianMap.put(Float.class, ImmutablePair.of(Float.valueOf("1"), new byte[]{0x0, 0x0, (byte) 0x80, 0x3F}));
-        littleEndianMap.put(Double.class, ImmutablePair.of(Double.valueOf("1"), new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, (byte) 0xF0, 0x3F}));
         littleEndianMap.put(Integer.class, ImmutablePair.of(Integer.valueOf("1"), new byte[]{0x1, 0x0, 0x0, 0x0}));
+        littleEndianMap.put(Double.class, ImmutablePair.of(Double.valueOf("1"), new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, (byte) 0xF0, 0x3F}));
+        littleEndianMap.put(BigInteger.class, ImmutablePair.of(BigInteger.valueOf(1), new byte[]{0x1, 0x0, 0x0, 0x0}));
+        littleEndianMap.put(Calendar.class, ImmutablePair.of(calenderInstance, new byte[]{0x0, (byte) 0x80, 0x3E, 0x15, (byte) 0xAB, 0x47, (byte) 0xFC, 0x28}));
+        littleEndianMap.put(GregorianCalendar.class, littleEndianMap.get(Calendar.class));
         littleEndianMap.put(String.class, ImmutablePair.of(String.valueOf("Hello World!"), new byte[]{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00}));
         bigEndianMap = new HashMap<>();
         littleEndianMap.forEach((clazz, pair) -> {
@@ -66,11 +68,13 @@ public class Plc4XSupportedDataTypes {
         return Stream.of(
             Boolean.class,
             Byte.class,
+            // TODO: add byte[]
             Short.class,
-            Calendar.class,
             Float.class,
-            Double.class,
             Integer.class,
+            Double.class,
+            BigInteger.class,
+            Calendar.class,
             String.class
         );
     }
diff --git a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
index 9a050f4..b4914a8 100644
--- a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
+++ b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java
@@ -37,6 +37,7 @@ import org.apache.plc4x.java.modbus.model.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.math.BigInteger;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -260,6 +261,7 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
                     && !(value instanceof byte[])
                     && !(value instanceof Short)
                     && !(value instanceof Integer)
+                    && !(value instanceof BigInteger)
                 ) {
                 throw new PlcRuntimeException("Unsupported datatype detected " + value.getClass());
             }
@@ -311,6 +313,8 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
                     throw new PlcProtocolException("Value to high to fit into Byte: " + value);
                 }
                 coilSet = (int) value == 1;
+            } else if (value.getClass() == BigInteger.class) {
+                coilSet = value.equals(BigInteger.ONE);
             }
             byte coilToSet = (coilSet ? (byte) 1 : (byte) 0);
             actualCoil = (byte) (actualCoil | coilToSet << i);
@@ -344,12 +348,41 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
                 }
                 buffer.writeBytes(bytes);
             } else if (value.getClass() == Short.class) {
+                if ((short) value < 0) {
+                    throw new PlcProtocolException("Only positive values are supported for Short: " + value);
+                }
                 buffer.writeShort((short) value);
             } else if (value.getClass() == Integer.class) {
                 if ((int) value > Integer.MAX_VALUE) {
                     throw new PlcProtocolException("Value to high to fit into register: " + value);
                 }
+                if ((int) value < 0) {
+                    throw new PlcProtocolException("Only positive values are supported for Integer: " + value);
+                }
                 buffer.writeShort((int) value);
+            } else if (value.getClass() == BigInteger.class) {
+                if (((BigInteger) value).compareTo(BigInteger.ZERO) < 0) {
+                    throw new PlcProtocolException("Only positive values are supported for BigInteger: " + value);
+                }
+                if (((BigInteger) value).compareTo(BigInteger.valueOf(0XFFFF_FFFFL)) > 0) {
+                    throw new PlcProtocolException("Value to high to fit into register: " + value);
+                }
+                // TODO: for now we can't support big values as we only write one register at once
+                if (((BigInteger) value).compareTo(BigInteger.valueOf(0XFFFFL)) > 0) {
+                    throw new PlcProtocolException("Value to high to fit into register: " + value);
+                }
+                // TODO: Register has 2 bytes so we trim to 2 instead of 4 like the second if above
+                int maxBytes = 2;
+                byte[] bigIntegerBytes = ((BigInteger) value).toByteArray();
+                byte[] bytes = new byte[maxBytes];
+                int lengthToCopy = Math.min(bigIntegerBytes.length, maxBytes);
+                int srcPosition = Math.max(bigIntegerBytes.length - maxBytes, 0);
+                int destPosition = maxBytes - lengthToCopy;
+                System.arraycopy(bigIntegerBytes, srcPosition, bytes, destPosition, lengthToCopy);
+
+                // TODO: check if this is a good representation.
+                // TODO: can a big integer span multiple registers?
+                buffer.writeBytes(bytes);
             }
         }
         byte[] result = new byte[buffer.writerIndex()];
@@ -393,6 +426,10 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
                 @SuppressWarnings("unchecked")
                 T itemToBeAdded = (T) Integer.valueOf(coilFlag);
                 data.add(itemToBeAdded);
+            } else if (dataType == BigInteger.class) {
+                @SuppressWarnings("unchecked")
+                T itemToBeAdded = (T) BigInteger.valueOf(coilFlag);
+                data.add(itemToBeAdded);
             }
         }
         return data;
@@ -431,9 +468,20 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload,
                 T itemToBeAdded = (T) Short.valueOf((short) intValue);
                 data.add(itemToBeAdded);
             } else if (dataType == Integer.class) {
+                if (intValue < 0) {
+                    throw new PlcProtocolException("Integer underflow: " + intValue);
+                }
                 @SuppressWarnings("unchecked")
                 T itemToBeAdded = (T) Integer.valueOf(intValue);
                 data.add(itemToBeAdded);
+            } else if (dataType == BigInteger.class) {
+                if (intValue < 0) {
+                    throw new PlcProtocolException("BigInteger underflow: " + intValue);
+                }
+                // TODO: can a big integer span multiple registers?
+                @SuppressWarnings("unchecked")
+                T itemToBeAdded = (T) new BigInteger(register);
+                data.add(itemToBeAdded);
             }
         }
         return data;
diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
index 42b882e..f28cb69 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
@@ -43,6 +43,7 @@ import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.math.BigInteger;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -167,7 +168,7 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem((Class) pair.getLeft().getClass(), RegisterModbusAddress.of("register:1"), pair.getLeft(), pair.getLeft(), pair.getLeft())
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteMultipleCoilsResponse(1, 3))
+                    new ModbusTcpPayload((short) 0, (short) 0, new WriteMultipleRegistersResponse(1, 3))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
@@ -175,7 +176,7 @@ public class Plc4XModbusProtocolTest {
                             .builder()
                             .addItem(RegisterModbusAddress.of("register:1"), pair.getLeft())
                             .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, pair.getRight()[0]))
+                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, pair.getRight()[0]))
                 )
             ))
             .flatMap(stream -> stream)
@@ -228,6 +229,9 @@ public class Plc4XModbusProtocolTest {
             } else if (payloadClazzName.equals(Integer.class.getSimpleName())) {
                 assertThat(andMask, equalTo(1));
                 assertThat(orMask, equalTo(2));
+            } else if (payloadClazzName.equals(BigInteger.class.getSimpleName())) {
+                assertThat(andMask, equalTo(1));
+                assertThat(orMask, equalTo(2));
             } else if (payloadClazzName.equals(String.class.getSimpleName())) {
                 assertThat(andMask, equalTo(1));
                 assertThat(orMask, equalTo(2));
@@ -275,6 +279,8 @@ public class Plc4XModbusProtocolTest {
                 assertByteEquals(new byte[]{0x0}, bytes);
             } else if (payloadClazzName.equals(Integer.class.getSimpleName())) {
                 assertByteEquals(new byte[]{0x0}, bytes);
+            } else if (payloadClazzName.equals(BigInteger.class.getSimpleName())) {
+                assertByteEquals(new byte[]{0x0}, bytes);
             } else if (payloadClazzName.equals(String.class.getSimpleName())) {
                 assertByteEquals(new byte[]{0x0}, bytes);
             }
@@ -297,6 +303,8 @@ public class Plc4XModbusProtocolTest {
                 assertByteEquals(new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, bytes);
             } else if (payloadClazzName.equals(Integer.class.getSimpleName())) {
                 assertByteEquals(new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, bytes);
+            } else if (payloadClazzName.equals(BigInteger.class.getSimpleName())) {
+                assertByteEquals(new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, bytes);
             } else if (payloadClazzName.equals(String.class.getSimpleName())) {
                 assertByteEquals(new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, bytes);
             }
@@ -318,6 +326,8 @@ public class Plc4XModbusProtocolTest {
                 assertThat(coilValue, equalTo(true));
             } else if (payloadClazzName.equals(Integer.class.getSimpleName())) {
                 assertThat(coilValue, equalTo(true));
+            } else if (payloadClazzName.equals(BigInteger.class.getSimpleName())) {
+                assertThat(coilValue, equalTo(true));
             } else if (payloadClazzName.equals(String.class.getSimpleName())) {
                 assertThat(coilValue, equalTo(true));
             }
@@ -338,6 +348,8 @@ public class Plc4XModbusProtocolTest {
                 assertThat(value, equalTo(1));
             } else if (payloadClazzName.equals(Integer.class.getSimpleName())) {
                 assertThat(value, equalTo(1));
+            } else if (payloadClazzName.equals(BigInteger.class.getSimpleName())) {
+                assertThat(value, equalTo(1));
             } else if (payloadClazzName.equals(String.class.getSimpleName())) {
                 assertThat(value, equalTo(1));
             }


[incubator-plc4x] 05/05: modbus protocol test: increased readability by extracting duplicate code

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 9e05e644adfc88d22e13ba04374229e94e9cff3e
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Jul 26 13:37:59 2018 +0200

    modbus protocol test: increased readability by extracting duplicate code
---
 .../java/modbus/netty/Plc4XModbusProtocolTest.java | 135 ++++++++-------------
 1 file changed, 49 insertions(+), 86 deletions(-)

diff --git a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
index 01b8d75..0a40696 100644
--- a/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
+++ b/plc4j/protocols/modbus/src/test/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocolTest.java
@@ -29,6 +29,7 @@ import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.messages.items.ReadResponseItem;
 import org.apache.plc4x.java.api.messages.items.ResponseItem;
 import org.apache.plc4x.java.api.messages.items.WriteResponseItem;
+import org.apache.plc4x.java.api.model.Address;
 import org.apache.plc4x.java.api.types.ResponseCode;
 import org.apache.plc4x.java.modbus.model.*;
 import org.junit.Before;
@@ -96,98 +97,60 @@ public class Plc4XModbusProtocolTest {
     public static Collection<Object[]> data() {
         return streamOfBigEndianDataTypePairs()
             .map(pair -> Stream.of(
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcReadRequest
-                            .builder()
-                            .addItem(pair.getLeft().getClass(), CoilModbusAddress.of("coil:1"))
-                            .build(), new CompletableFuture<>()),
-                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
-                    // all positive so we return one byte with the first bit set
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadCoilsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x1})))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcWriteRequest
-                            .builder()
-                            .addItem(CoilModbusAddress.of("coil:1"), pair.getLeft())
-                            .build(), new CompletableFuture<>()),
-                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
-                    // all positive so we return one byte with the first bit set
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleCoilResponse(1, 1))
-                ),
+                producePair(pair.getLeft().getClass(), CoilModbusAddress.of("coil:1"), new ReadCoilsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x1}))),
+                producePair(CoilModbusAddress.of("coil:1"), new WriteSingleCoilResponse(1, 1), pair.getLeft()),
                 /* Read request no supported on maskwrite so how to handle?
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcReadRequest
-                            .builder()
-                            .addItem(pair.left.getClass(), MaskWriteRegisterModbusAddress.of("maskwrite:1/1/2"))
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new MaskWriteRegisterResponse(1, 1, 2))
-                ), */
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcWriteRequest
-                            .builder()
-                            .addItem(MaskWriteRegisterModbusAddress.of("maskwrite:1/1/2"), pair.getLeft())
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new MaskWriteRegisterResponse(1, 1, 2))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcReadRequest
-                            .builder()
-                            .addItem(pair.getLeft().getClass(), ReadDiscreteInputsModbusAddress.of("readdiscreteinputs:1"))
-                            .build(), new CompletableFuture<>()),
-                    // Coils are a bit different so the only know 1 or 0. So we know streamOfBigEndianDataTypePairs are
-                    // all positive so we return one byte with the first bit set
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x01})))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcReadRequest
-                            .builder()
-                            .addItem(pair.getLeft().getClass(), ReadHoldingRegistersModbusAddress.of("readholdingregisters:1"))
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcReadRequest
-                            .builder()
-                            .addItem(pair.getLeft().getClass(), ReadInputRegistersModbusAddress.of("readinputregisters:1"))
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new ReadInputRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight()))))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcWriteRequest
-                            .builder()
-                            .addItem((Class) pair.getLeft().getClass(), CoilModbusAddress.of("coil:1"), pair.getLeft(), pair.getLeft(), pair.getLeft())
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteMultipleCoilsResponse(1, 3))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcWriteRequest
-                            .builder()
-                            .addItem((Class) pair.getLeft().getClass(), RegisterModbusAddress.of("register:1"), pair.getLeft(), pair.getLeft(), pair.getLeft())
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteMultipleRegistersResponse(1, 3))
-                ),
-                ImmutablePair.of(
-                    new PlcRequestContainer<>(
-                        PlcWriteRequest
-                            .builder()
-                            .addItem(RegisterModbusAddress.of("register:1"), pair.getLeft())
-                            .build(), new CompletableFuture<>()),
-                    new ModbusTcpPayload((short) 0, (short) 0, new WriteSingleRegisterResponse(1, cutRegister(pair.getRight())[0]))
-                )
+                producePair(pair.getLeft().getClass(), MaskWriteRegisterModbusAddress.of("maskwrite:1/1/2"), new MaskWriteRegisterResponse(1, 1, 2)),
+                */
+                producePair(MaskWriteRegisterModbusAddress.of("maskwrite:1/1/2"), new MaskWriteRegisterResponse(1, 1, 2), pair.getLeft()),
+                producePair(pair.getLeft().getClass(), ReadDiscreteInputsModbusAddress.of("readdiscreteinputs:1"), new ReadDiscreteInputsResponse(Unpooled.wrappedBuffer(new byte[]{(byte) 0x01}))),
+                producePair(pair.getLeft().getClass(), ReadHoldingRegistersModbusAddress.of("readholdingregisters:1"), new ReadHoldingRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight())))),
+                producePair(pair.getLeft().getClass(), ReadInputRegistersModbusAddress.of("readinputregisters:1"), new ReadInputRegistersResponse(Unpooled.wrappedBuffer(cutRegister(pair.getRight())))),
+                producePair(CoilModbusAddress.of("coil:1"), new WriteMultipleCoilsResponse(1, 3), pair.getLeft(), pair.getLeft(), pair.getLeft()),
+                producePair(RegisterModbusAddress.of("register:1"), new WriteMultipleRegistersResponse(1, 3), pair.getLeft(), pair.getLeft(), pair.getLeft()),
+                producePair(RegisterModbusAddress.of("register:1"), new WriteSingleRegisterResponse(1, cutRegister(pair.getRight())[0]), pair.getLeft())
             ))
             .flatMap(stream -> stream)
             .map(pair -> new Object[]{pair.left.getRequest().getRequestItem().orElseThrow(IllegalStateException::new).getDatatype().getSimpleName(), pair.left, pair.left.getResponseFuture(), pair.left.getRequest().getClass().getSimpleName(), pair.right, pair.right.getModbusPdu().getClass().getSimpleName()}).collect(Collectors.toList());
     }
 
+    private static ImmutablePair<PlcRequestContainer<PlcReadRequest, PlcResponse>, ModbusTcpPayload> producePair(Class type, Address address, ModbusPdu modbusPdu) {
+        return ImmutablePair.of(
+            new PlcRequestContainer<>(
+                PlcReadRequest
+                    .builder()
+                    .addItem(type, address)
+                    .build(), new CompletableFuture<>()),
+            new ModbusTcpPayload((short) 0, (short) 0, modbusPdu)
+        );
+    }
+
+    @SuppressWarnings("unchecked")
+    private static ImmutablePair<PlcRequestContainer<PlcWriteRequest, PlcResponse>, ModbusTcpPayload> producePair(Address address, ModbusPdu modbusPdu, Object... values) {
+        if (values.length == 0) {
+            throw new IllegalArgumentException("At least one value ist required");
+        }
+        if (values.length == 1) {
+            return ImmutablePair.of(
+                new PlcRequestContainer<>(
+                    PlcWriteRequest
+                        .builder()
+                        .addItem(address, values[0])
+                        .build(), new CompletableFuture<>()),
+                new ModbusTcpPayload((short) 0, (short) 0, modbusPdu)
+            );
+        } else {
+            return ImmutablePair.of(
+                new PlcRequestContainer<>(
+                    PlcWriteRequest
+                        .builder()
+                        .addItem((Class<Object>) values[0].getClass(), address, values)
+                        .build(), new CompletableFuture<>()),
+                new ModbusTcpPayload((short) 0, (short) 0, modbusPdu)
+            );
+        }
+    }
+
     private static byte[] cutRegister(byte[] right) {
         return new byte[]{right.length > 1 ? right[right.length - 2] : 0x0, right[right.length - 1]};
     }