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/09/13 11:35:50 UTC

[incubator-plc4x] branch feature/api-redesign-chris-c updated (f7bd1c4 -> 19716f8)

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

sruehl pushed a change to branch feature/api-redesign-chris-c
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git.


    from f7bd1c4  make ads compile again
     new 26cba52  added support for BigInteger on field handler
     new 19716f8  make ads test run again (still failing though)

The 2 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:
 .../apache/plc4x/edgent/mock/MockFieldHandler.java |    5 +
 .../plc4x/java/api/messages/PlcWriteRequest.java   |    3 +
 .../ads/connection/AdsAbstractPlcConnection.java   |    6 +-
 .../java/ads/connection/AdsTcpPlcConnection.java   |   26 +-
 .../apache/plc4x/java/ads/model/AdsDataType.java   |  543 ++++++++-
 .../org/apache/plc4x/java/ads/model/AdsField.java  |  120 +-
 .../plc4x/java/ads/model/AdsPlcFieldHandler.java   | 1148 +++++++++++++++++++-
 .../model/{AdsField.java => DirectAdsField.java}   |   21 +-
 .../plc4x/java/ads/model/SymbolicAdsField.java     |    5 +-
 .../plc4x/java/ads/protocol/Plc4x2AdsProtocol.java |   42 +-
 .../apache/plc4x/java/ads/ManualPlc4XAdsTest.java  |    2 +-
 .../connection/AdsAbstractPlcConnectionTest.java   |   31 +-
 .../{AdsFieldTest.java => DirectAdsFieldTest.java} |   18 +-
 .../java/ads/protocol/Plc4x2AdsProtocolTest.java   |   48 +-
 .../java/base/connection/PlcFieldHandler.java      |    2 +
 .../java/base/messages/DefaultPlcWriteRequest.java |    7 +
 .../base/protocol/Plc4XSupportedDataTypes.java     |    9 +-
 .../java/s7/netty/util/S7PlcFieldHandler.java      |  108 +-
 .../apache/plc4x/java/test/TestFieldHandler.java   |   34 +-
 19 files changed, 1851 insertions(+), 327 deletions(-)
 copy plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/{AdsField.java => DirectAdsField.java} (85%)
 rename plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/{AdsFieldTest.java => DirectAdsFieldTest.java} (73%)


[incubator-plc4x] 01/02: added support for BigInteger on field handler

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

sruehl pushed a commit to branch feature/api-redesign-chris-c
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 26cba520ee590c64e0d614f27c62d586e961625e
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Sep 13 13:35:07 2018 +0200

    added support for BigInteger on field handler
---
 .../apache/plc4x/edgent/mock/MockFieldHandler.java |   5 +
 .../plc4x/java/api/messages/PlcWriteRequest.java   |   3 +
 .../java/base/connection/PlcFieldHandler.java      |   2 +
 .../java/base/messages/DefaultPlcWriteRequest.java |   7 ++
 .../base/protocol/Plc4XSupportedDataTypes.java     |   9 +-
 .../java/s7/netty/util/S7PlcFieldHandler.java      | 108 +++++++++++----------
 .../apache/plc4x/java/test/TestFieldHandler.java   |  34 ++++---
 7 files changed, 105 insertions(+), 63 deletions(-)

diff --git a/integrations/apache-edgent/src/test/java/org/apache/plc4x/edgent/mock/MockFieldHandler.java b/integrations/apache-edgent/src/test/java/org/apache/plc4x/edgent/mock/MockFieldHandler.java
index f8d2ac8..3d2c1ad 100644
--- a/integrations/apache-edgent/src/test/java/org/apache/plc4x/edgent/mock/MockFieldHandler.java
+++ b/integrations/apache-edgent/src/test/java/org/apache/plc4x/edgent/mock/MockFieldHandler.java
@@ -52,6 +52,11 @@ public class MockFieldHandler implements PlcFieldHandler {
     }
 
     @Override
+    public FieldItem encodeBigInteger(PlcField field, Object[] values) {
+        return new MockFieldItem(values);
+    }
+
+    @Override
     public FieldItem encodeLong(PlcField field, Object[] values) {
         return new MockFieldItem(values);
     }
diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
index c89c003..1dfa4aa 100644
--- a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
+++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcWriteRequest.java
@@ -18,6 +18,7 @@ under the License.
 */
 package org.apache.plc4x.java.api.messages;
 
+import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -36,6 +37,8 @@ public interface PlcWriteRequest extends PlcFieldRequest {
 
         PlcWriteRequest.Builder addItem(String name, String fieldQuery, Integer... values);
 
+        PlcWriteRequest.Builder addItem(String name, String fieldQuery, BigInteger... values);
+
         PlcWriteRequest.Builder addItem(String name, String fieldQuery, Long... values);
 
         PlcWriteRequest.Builder addItem(String name, String fieldQuery, Float... values);
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/connection/PlcFieldHandler.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/connection/PlcFieldHandler.java
index d400b5b..2a86796 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/connection/PlcFieldHandler.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/connection/PlcFieldHandler.java
@@ -34,6 +34,8 @@ public interface PlcFieldHandler {
 
     FieldItem encodeInteger(PlcField field, Object[] values);
 
+    FieldItem encodeBigInteger(PlcField field, Object[] values);
+
     FieldItem encodeLong(PlcField field, Object[] values);
 
     FieldItem encodeFloat(PlcField field, Object[] values);
diff --git a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
index 113bc5b..ec94553 100644
--- a/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/base/messages/DefaultPlcWriteRequest.java
@@ -26,6 +26,7 @@ import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.base.connection.PlcFieldHandler;
 import org.apache.plc4x.java.base.messages.items.FieldItem;
 
+import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -90,6 +91,7 @@ public class DefaultPlcWriteRequest implements InternalPlcWriteRequest {
             handlerMap.put(Byte.class, fieldHandler::encodeByte);
             handlerMap.put(Short.class, fieldHandler::encodeShort);
             handlerMap.put(Integer.class, fieldHandler::encodeInteger);
+            handlerMap.put(BigInteger.class, fieldHandler::encodeBigInteger);
             handlerMap.put(Long.class, fieldHandler::encodeLong);
             handlerMap.put(Float.class, fieldHandler::encodeFloat);
             handlerMap.put(Double.class, fieldHandler::encodeDouble);
@@ -120,6 +122,11 @@ public class DefaultPlcWriteRequest implements InternalPlcWriteRequest {
         }
 
         @Override
+        public PlcWriteRequest.Builder addItem(String name, String fieldQuery, BigInteger... values) {
+            return addItem(name, fieldQuery, values, fieldHandler::encodeBigInteger);
+        }
+
+        @Override
         public Builder addItem(String name, String fieldQuery, Long... values) {
             return addItem(name, fieldQuery, values, fieldHandler::encodeLong);
         }
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 4b1ca7e..dd48376 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
@@ -182,7 +182,7 @@ public class Plc4XSupportedDataTypes {
     public static class DataTypePair<T extends Serializable> {
         private final Pair<T, byte[]> dataTypePair;
 
-        private DataTypePair(Pair<T, byte[]> dataTypePair) {
+        public DataTypePair(Pair<T, byte[]> dataTypePair) {
             this.dataTypePair = dataTypePair;
         }
 
@@ -211,6 +211,13 @@ public class Plc4XSupportedDataTypes {
             return ArrayUtils.clone(dataTypePair.getRight());
         }
 
+        /**
+         * @return the internal pair.
+         */
+        public Pair<T, byte[]> getDataTypePair() {
+            return dataTypePair;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (this == o) {
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7PlcFieldHandler.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7PlcFieldHandler.java
index a34a79a..fd8ad5d 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7PlcFieldHandler.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7PlcFieldHandler.java
@@ -22,7 +22,9 @@ import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.base.connection.PlcFieldHandler;
-import org.apache.plc4x.java.base.messages.items.*;
+import org.apache.plc4x.java.base.messages.items.DefaultIntegerFieldItem;
+import org.apache.plc4x.java.base.messages.items.DefaultTimeFieldItem;
+import org.apache.plc4x.java.base.messages.items.FieldItem;
 import org.apache.plc4x.java.s7.messages.items.*;
 import org.apache.plc4x.java.s7.model.S7Field;
 import org.apache.plc4x.java.s7.types.S7DataType;
@@ -37,7 +39,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
 
     @Override
     public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
-        if(S7Field.matches(fieldQuery)) {
+        if (S7Field.matches(fieldQuery)) {
             return S7Field.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
@@ -47,7 +49,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     public FieldItem encodeBoolean(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
         // All of these types are declared as Bit or Bit-String types.
-        if((s7Field.getDataType() == S7DataType.BOOL) || (s7Field.getDataType() == S7DataType.BYTE) ||
+        if ((s7Field.getDataType() == S7DataType.BOOL) || (s7Field.getDataType() == S7DataType.BYTE) ||
             (s7Field.getDataType() == S7DataType.WORD) || (s7Field.getDataType() == S7DataType.DWORD) ||
             (s7Field.getDataType() == S7DataType.LWORD)) {
             return internalEncodeBoolean(field, values);
@@ -58,7 +60,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeByte(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if((s7Field.getDataType() == S7DataType.BYTE) || (s7Field.getDataType() == S7DataType.SINT) ||
+        if ((s7Field.getDataType() == S7DataType.BYTE) || (s7Field.getDataType() == S7DataType.SINT) ||
             (s7Field.getDataType() == S7DataType.USINT) || (s7Field.getDataType() == S7DataType.CHAR)) {
             return internalEncodeInteger(field, values);
         }
@@ -68,7 +70,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeShort(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if((s7Field.getDataType() == S7DataType.WORD) || (s7Field.getDataType() == S7DataType.INT) ||
+        if ((s7Field.getDataType() == S7DataType.WORD) || (s7Field.getDataType() == S7DataType.INT) ||
             (s7Field.getDataType() == S7DataType.UINT)) {
             return internalEncodeInteger(field, values);
         }
@@ -78,7 +80,17 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeInteger(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if((s7Field.getDataType() == S7DataType.DWORD) || (s7Field.getDataType() == S7DataType.DINT) ||
+        if ((s7Field.getDataType() == S7DataType.DWORD) || (s7Field.getDataType() == S7DataType.DINT) ||
+            (s7Field.getDataType() == S7DataType.UDINT)) {
+            return internalEncodeInteger(field, values);
+        }
+        throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
+    }
+
+    @Override
+    public FieldItem encodeBigInteger(PlcField field, Object[] values) {
+        S7Field s7Field = (S7Field) field;
+        if ((s7Field.getDataType() == S7DataType.DWORD) || (s7Field.getDataType() == S7DataType.DINT) ||
             (s7Field.getDataType() == S7DataType.UDINT)) {
             return internalEncodeInteger(field, values);
         }
@@ -88,7 +100,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeLong(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if((s7Field.getDataType() == S7DataType.LWORD) || (s7Field.getDataType() == S7DataType.LINT) ||
+        if ((s7Field.getDataType() == S7DataType.LWORD) || (s7Field.getDataType() == S7DataType.LINT) ||
             (s7Field.getDataType() == S7DataType.ULINT)) {
             return internalEncodeInteger(field, values);
         }
@@ -98,7 +110,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeFloat(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if(s7Field.getDataType() == S7DataType.REAL) {
+        if (s7Field.getDataType() == S7DataType.REAL) {
             return internalEncodeFloatingPoint(field, values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
@@ -107,7 +119,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDouble(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if(s7Field.getDataType() == S7DataType.LREAL) {
+        if (s7Field.getDataType() == S7DataType.LREAL) {
             return internalEncodeFloatingPoint(field, values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
@@ -116,7 +128,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeString(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if((s7Field.getDataType() == S7DataType.CHAR) || (s7Field.getDataType() == S7DataType.WCHAR) ||
+        if ((s7Field.getDataType() == S7DataType.CHAR) || (s7Field.getDataType() == S7DataType.WCHAR) ||
             (s7Field.getDataType() == S7DataType.STRING) || (s7Field.getDataType() == S7DataType.WSTRING)) {
             return internalEncodeString(field, values);
         }
@@ -126,7 +138,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeTime(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if(s7Field.getDataType() == S7DataType.TIME) {
+        if (s7Field.getDataType() == S7DataType.TIME) {
             return internalEncodeTemporal(field, values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
@@ -135,7 +147,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDate(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if(s7Field.getDataType() == S7DataType.DATE) {
+        if (s7Field.getDataType() == S7DataType.DATE) {
             return internalEncodeTemporal(field, values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
@@ -144,7 +156,7 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDateTime(PlcField field, Object[] values) {
         S7Field s7Field = (S7Field) field;
-        if(s7Field.getDataType() == S7DataType.DATE_AND_TIME) {
+        if (s7Field.getDataType() == S7DataType.DATE_AND_TIME) {
             return internalEncodeTemporal(field, values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + s7Field.getDataType().name());
@@ -165,31 +177,31 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
         }
         List<Boolean> booleanValues = new LinkedList<>();
         for (Object value : values) {
-            if(value instanceof Boolean) {
+            if (value instanceof Boolean) {
                 Boolean booleanValue = (Boolean) value;
                 booleanValues.add(booleanValue);
-            } else if(value instanceof Byte) {
+            } else if (value instanceof Byte) {
                 Byte byteValue = (Byte) value;
                 BitSet bitSet = BitSet.valueOf(new byte[]{byteValue});
-                for(int i = 0; i < 8; i++) {
+                for (int i = 0; i < 8; i++) {
                     booleanValues.add(bitSet.get(i));
                 }
-            } else if(value instanceof Short) {
+            } else if (value instanceof Short) {
                 Short shortValue = (Short) value;
                 BitSet bitSet = BitSet.valueOf(new long[]{shortValue});
-                for(int i = 0; i < 16; i++) {
+                for (int i = 0; i < 16; i++) {
                     booleanValues.add(bitSet.get(i));
                 }
-            } else if(value instanceof Integer) {
+            } else if (value instanceof Integer) {
                 Integer integerValue = (Integer) value;
                 BitSet bitSet = BitSet.valueOf(new long[]{integerValue});
-                for(int i = 0; i < 32; i++) {
+                for (int i = 0; i < 32; i++) {
                     booleanValues.add(bitSet.get(i));
                 }
-            } else if(value instanceof Long) {
+            } else if (value instanceof Long) {
                 long longValue = (Long) value;
                 BitSet bitSet = BitSet.valueOf(new long[]{longValue});
-                for(int i = 0; i < 64; i++) {
+                for (int i = 0; i < 64; i++) {
                     booleanValues.add(bitSet.get(i));
                 }
             } else {
@@ -271,22 +283,22 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
                 throw new IllegalArgumentException(
                     "Cannot assign integer values to " + s7Field.getDataType().name() + " fields.");
         }
-        if(fieldType == DefaultIntegerFieldItem.class) {
+        if (fieldType == DefaultIntegerFieldItem.class) {
             Long[] longValues = new Long[values.length];
             for (int i = 0; i < values.length; i++) {
-                if(!((values[i] instanceof Byte) || (values[i] instanceof Short) ||
-                    (values[i] instanceof Integer) || (values[i] instanceof Long))) {
+                if (!((values[i] instanceof Byte) || (values[i] instanceof Short) ||
+                    (values[i] instanceof Integer) || (values[i] instanceof BigInteger) || (values[i] instanceof Long))) {
                     throw new IllegalArgumentException(
                         "Value of type " + values[i].getClass().getName() +
                             " is not assignable to " + s7Field.getDataType().name() + " fields.");
                 }
                 BigInteger value = BigInteger.valueOf(((Number) values[i]).longValue());
-                if(minValue.compareTo(value) > 0) {
+                if (minValue.compareTo(value) > 0) {
                     throw new IllegalArgumentException(
                         "Value of " + value.toString() + " exceeds allowed minimum for type "
                             + s7Field.getDataType().name() + " (min " + minValue.toString() + ")");
                 }
-                if(maxValue.compareTo(value) < 0) {
+                if (maxValue.compareTo(value) < 0) {
                     throw new IllegalArgumentException(
                         "Value of " + value.toString() + " exceeds allowed maximum for type "
                             + s7Field.getDataType().name() + " (max " + maxValue.toString() + ")");
@@ -298,9 +310,9 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
             BigInteger[] bigIntegerValues = new BigInteger[values.length];
             for (int i = 0; i < values.length; i++) {
                 BigInteger value;
-                if(values[i] instanceof BigInteger) {
+                if (values[i] instanceof BigInteger) {
                     value = (BigInteger) values[i];
-                } else if(((values[i] instanceof Byte) || (values[i] instanceof Short) ||
+                } else if (((values[i] instanceof Byte) || (values[i] instanceof Short) ||
                     (values[i] instanceof Integer) || (values[i] instanceof Long))) {
                     value = BigInteger.valueOf(((Number) values[i]).longValue());
                 } else {
@@ -308,12 +320,12 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
                         "Value of type " + values[i].getClass().getName() +
                             " is not assignable to " + s7Field.getDataType().name() + " fields.");
                 }
-                if(minValue.compareTo(value) > 0) {
+                if (minValue.compareTo(value) > 0) {
                     throw new IllegalArgumentException(
                         "Value of " + value.toString() + " exceeds allowed minimum for type "
                             + s7Field.getDataType().name() + " (min " + minValue.toString() + ")");
                 }
-                if(maxValue.compareTo(value) < 0) {
+                if (maxValue.compareTo(value) < 0) {
                     throw new IllegalArgumentException(
                         "Value of " + value.toString() + " exceeds allowed maximum for type "
                             + s7Field.getDataType().name() + " (max " + maxValue.toString() + ")");
@@ -345,21 +357,21 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
         }
         Double[] floatingPointValues = new Double[values.length];
         for (int i = 0; i < values.length; i++) {
-            if(values[i] instanceof Float) {
+            if (values[i] instanceof Float) {
                 floatingPointValues[i] = ((Float) values[i]).doubleValue();
-            } else if(values[i] instanceof Double) {
+            } else if (values[i] instanceof Double) {
                 floatingPointValues[i] = (Double) values[i];
             } else {
                 throw new IllegalArgumentException(
                     "Value of type " + values[i].getClass().getName() +
                         " is not assignable to " + s7Field.getDataType().name() + " fields.");
             }
-            if(floatingPointValues[i] < minValue) {
+            if (floatingPointValues[i] < minValue) {
                 throw new IllegalArgumentException(
                     "Value of " + floatingPointValues[i] + " exceeds allowed minimum for type "
                         + s7Field.getDataType().name() + " (min " + minValue.toString() + ")");
             }
-            if(floatingPointValues[i] > maxValue) {
+            if (floatingPointValues[i] > maxValue) {
                 throw new IllegalArgumentException(
                     "Value of " + floatingPointValues[i] + " exceeds allowed maximum for type "
                         + s7Field.getDataType().name() + " (max " + maxValue.toString() + ")");
@@ -395,9 +407,9 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
         }
         List<String> stringValues = new LinkedList<>();
         for (Object value : values) {
-            if(value instanceof String) {
+            if (value instanceof String) {
                 String stringValue = (String) value;
-                if(stringValue.length() > maxLength) {
+                if (stringValue.length() > maxLength) {
                     throw new IllegalArgumentException(
                         "String length " + stringValue.length() + " exceeds allowed maximum for type "
                             + s7Field.getDataType().name() + " (max " + maxLength + ")");
@@ -405,40 +417,37 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
                 stringValues.add(stringValue);
             }
             // All other types just translate to max one String character.
-            else if(value instanceof Byte) {
+            else if (value instanceof Byte) {
                 Byte byteValue = (Byte) value;
                 byte[] stringBytes = new byte[]{byteValue};
-                if(encoding16Bit) {
+                if (encoding16Bit) {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
                 } else {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
                 }
-            }
-            else if(value instanceof Short) {
+            } else if (value instanceof Short) {
                 Short shortValue = (Short) value;
                 byte[] stringBytes = new byte[2];
                 stringBytes[0] = (byte) (shortValue >> 8);
                 stringBytes[1] = (byte) (shortValue & 0xFF);
-                if(encoding16Bit) {
+                if (encoding16Bit) {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
                 } else {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
                 }
-            }
-            else if(value instanceof Integer) {
+            } else if (value instanceof Integer) {
                 Integer integerValue = (Integer) value;
                 byte[] stringBytes = new byte[4];
                 stringBytes[0] = (byte) ((integerValue >> 24) & 0xFF);
                 stringBytes[1] = (byte) ((integerValue >> 16) & 0xFF);
                 stringBytes[2] = (byte) ((integerValue >> 8) & 0xFF);
                 stringBytes[3] = (byte) (integerValue & 0xFF);
-                if(encoding16Bit) {
+                if (encoding16Bit) {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
                 } else {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
                 }
-            }
-            else if(value instanceof Long) {
+            } else if (value instanceof Long) {
                 Long longValue = (Long) value;
                 byte[] stringBytes = new byte[8];
                 stringBytes[0] = (byte) ((longValue >> 56) & 0xFF);
@@ -449,13 +458,12 @@ public class S7PlcFieldHandler implements PlcFieldHandler {
                 stringBytes[5] = (byte) ((longValue >> 16) & 0xFF);
                 stringBytes[6] = (byte) ((longValue >> 8) & 0xFF);
                 stringBytes[7] = (byte) (longValue & 0xFF);
-                if(encoding16Bit) {
+                if (encoding16Bit) {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
                 } else {
                     stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
                 }
-            }
-            else {
+            } else {
                 throw new IllegalArgumentException(
                     "Value of type " + value.getClass().getName() +
                         " is not assignable to " + s7Field.getDataType().name() + " fields.");
diff --git a/plc4j/protocols/test/src/main/java/org/apache/plc4x/java/test/TestFieldHandler.java b/plc4j/protocols/test/src/main/java/org/apache/plc4x/java/test/TestFieldHandler.java
index 5953da6..839c89c 100644
--- a/plc4j/protocols/test/src/main/java/org/apache/plc4x/java/test/TestFieldHandler.java
+++ b/plc4j/protocols/test/src/main/java/org/apache/plc4x/java/test/TestFieldHandler.java
@@ -25,6 +25,7 @@ import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.base.connection.PlcFieldHandler;
 import org.apache.plc4x.java.base.messages.items.*;
 
+import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -34,7 +35,7 @@ public class TestFieldHandler implements PlcFieldHandler {
 
     @Override
     public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
-        if(TestField.matches(fieldQuery)) {
+        if (TestField.matches(fieldQuery)) {
             return TestField.of(fieldQuery);
         }
         throw new PlcInvalidFieldException(fieldQuery);
@@ -43,7 +44,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeBoolean(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Boolean.class) {
+        if (testField.getDataType() == Boolean.class) {
             return new DefaultBooleanFieldItem((Boolean[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -52,7 +53,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeByte(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Byte.class) {
+        if (testField.getDataType() == Byte.class) {
             return new DefaultIntegerFieldItem(Arrays.stream(values).map(x -> new Long((Byte) x)).toArray(Long[]::new));
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -61,7 +62,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeShort(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Short.class) {
+        if (testField.getDataType() == Short.class) {
             return new DefaultIntegerFieldItem(Arrays.stream(values).map(x -> new Long((Short) x)).toArray(Long[]::new));
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -70,16 +71,25 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeInteger(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Integer.class) {
+        if (testField.getDataType() == Integer.class) {
             return new DefaultIntegerFieldItem(Arrays.stream(values).map(x -> new Long((Integer) x)).toArray(Long[]::new));
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
     }
 
     @Override
+    public FieldItem encodeBigInteger(PlcField field, Object[] values) {
+        TestField testField = (TestField) field;
+        if (testField.getDataType() == BigInteger.class) {
+            return new DefaultIntegerFieldItem(Arrays.stream(values).map(x -> ((BigInteger) x).longValue()).toArray(Long[]::new));
+        }
+        throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
+    }
+
+    @Override
     public FieldItem encodeLong(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Long.class) {
+        if (testField.getDataType() == Long.class) {
             return new DefaultIntegerFieldItem((Long[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -88,7 +98,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeFloat(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Float.class) {
+        if (testField.getDataType() == Float.class) {
             return new DefaultFloatingPointFieldItem((Double[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -97,7 +107,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDouble(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == Double.class) {
+        if (testField.getDataType() == Double.class) {
             return new DefaultFloatingPointFieldItem((Double[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -106,7 +116,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeString(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == String.class) {
+        if (testField.getDataType() == String.class) {
             return new DefaultStringFieldItem((String[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -115,7 +125,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeTime(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == LocalTime.class) {
+        if (testField.getDataType() == LocalTime.class) {
             return new DefaultTimeFieldItem((LocalDateTime[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -124,7 +134,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDate(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == LocalDate.class) {
+        if (testField.getDataType() == LocalDate.class) {
             return new DefaultTimeFieldItem((LocalDateTime[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());
@@ -133,7 +143,7 @@ public class TestFieldHandler implements PlcFieldHandler {
     @Override
     public FieldItem encodeDateTime(PlcField field, Object[] values) {
         TestField testField = (TestField) field;
-        if(testField.getDataType() == LocalDateTime.class) {
+        if (testField.getDataType() == LocalDateTime.class) {
             return new DefaultTimeFieldItem((LocalDateTime[]) values);
         }
         throw new PlcRuntimeException("Invalid encoder for type " + testField.getDataType().getName());


[incubator-plc4x] 02/02: make ads test run again (still failing though)

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

sruehl pushed a commit to branch feature/api-redesign-chris-c
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 19716f8d5847c3f65ed618023971cab76ded0bf7
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Sep 13 13:35:29 2018 +0200

    make ads test run again (still failing though)
---
 .../ads/connection/AdsAbstractPlcConnection.java   |    6 +-
 .../java/ads/connection/AdsTcpPlcConnection.java   |   26 +-
 .../apache/plc4x/java/ads/model/AdsDataType.java   |  543 ++++++++-
 .../org/apache/plc4x/java/ads/model/AdsField.java  |  120 +-
 .../plc4x/java/ads/model/AdsPlcFieldHandler.java   | 1148 +++++++++++++++++++-
 .../model/{AdsField.java => DirectAdsField.java}   |   21 +-
 .../plc4x/java/ads/model/SymbolicAdsField.java     |    5 +-
 .../plc4x/java/ads/protocol/Plc4x2AdsProtocol.java |   42 +-
 .../apache/plc4x/java/ads/ManualPlc4XAdsTest.java  |    2 +-
 .../connection/AdsAbstractPlcConnectionTest.java   |   31 +-
 .../{AdsFieldTest.java => DirectAdsFieldTest.java} |   18 +-
 .../java/ads/protocol/Plc4x2AdsProtocolTest.java   |   48 +-
 12 files changed, 1746 insertions(+), 264 deletions(-)

diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
index 4664ea0..a80e5e7 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java
@@ -28,8 +28,8 @@ import org.apache.plc4x.java.ads.api.commands.types.*;
 import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
 import org.apache.plc4x.java.ads.api.generic.types.Invoke;
-import org.apache.plc4x.java.ads.model.AdsField;
 import org.apache.plc4x.java.ads.model.AdsPlcFieldHandler;
+import org.apache.plc4x.java.ads.model.DirectAdsField;
 import org.apache.plc4x.java.ads.model.SymbolicAdsField;
 import org.apache.plc4x.java.api.connection.PlcProprietarySender;
 import org.apache.plc4x.java.api.connection.PlcReader;
@@ -60,7 +60,7 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
 
     protected final AmsPort sourceAmsPort;
 
-    protected final ConcurrentMap<SymbolicAdsField, AdsField> fieldMapping;
+    protected final ConcurrentMap<SymbolicAdsField, DirectAdsField> fieldMapping;
 
     protected AdsAbstractPlcConnection(ChannelFactory channelFactory, AmsNetId targetAmsNetId, AmsPort targetAmsPort) {
         this(channelFactory, targetAmsNetId, targetAmsPort, generateAMSNetId(), generateAMSPort());
@@ -178,7 +178,7 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp
             }
 
             IndexOffset symbolHandle = IndexOffset.of(response.getData().getBytes());
-            return AdsField.of(IndexGroup.ReservedGroups.ADSIGRP_SYM_VALBYHND.getAsLong(), symbolHandle.getAsLong(), symbolicAdsFieldInternal.getAdsDataType(), symbolicAdsFieldInternal.getNumberOfElements());
+            return DirectAdsField.of(IndexGroup.ReservedGroups.ADSIGRP_SYM_VALBYHND.getAsLong(), symbolHandle.getAsLong(), symbolicAdsFieldInternal.getAdsDataType(), symbolicAdsFieldInternal.getNumberOfElements());
         });
     }
 
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
index 3d52ccb..d498694 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java
@@ -152,23 +152,23 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
         // TODO: This is blocking, should be changed to be async.
         if (field instanceof SymbolicAdsField) {
             mapFields((SymbolicAdsField) field);
-            AdsField adsField = fieldMapping.get(field);
-            if (adsField == null) {
+            DirectAdsField directAdsField = fieldMapping.get(field);
+            if (directAdsField == null) {
                 throw new PlcRuntimeException("Unresolvable field " + field);
             }
-            indexGroup = IndexGroup.of(adsField.getIndexGroup());
-            indexOffset = IndexOffset.of(adsField.getIndexOffset());
-            adsDataType = adsField.getAdsDataType();
-            numberOfElements = adsField.getNumberOfElements();
+            indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
+            indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
+            adsDataType = directAdsField.getAdsDataType();
+            numberOfElements = directAdsField.getNumberOfElements();
         }
         // If it's no symbolic field, we can continue immediately
         // without having to do any resolving.
-        else if (field instanceof AdsField) {
-            AdsField adsField = (AdsField) field;
-            indexGroup = IndexGroup.of(adsField.getIndexGroup());
-            indexOffset = IndexOffset.of(adsField.getIndexOffset());
-            adsDataType = adsField.getAdsDataType();
-            numberOfElements = adsField.getNumberOfElements();
+        else if (field instanceof DirectAdsField) {
+            DirectAdsField directAdsField = (DirectAdsField) field;
+            indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
+            indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
+            adsDataType = directAdsField.getAdsDataType();
+            numberOfElements = directAdsField.getNumberOfElements();
         } else {
             throw new IllegalArgumentException("Unsupported field type " + field.getClass());
         }
@@ -194,7 +194,7 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc
             Invoke.NONE,
             indexGroup,
             indexOffset,
-            Length.of(adsDataType.getTagetByteSize() * numberOfElements),
+            Length.of(adsDataType.getTargetByteSize() * numberOfElements),
             transmissionMode,
             MaxDelay.of(0),
             CycleTime.of(4000000)
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
index f46c856..7dbc293 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsDataType.java
@@ -18,51 +18,512 @@
  */
 package org.apache.plc4x.java.ads.model;
 
+import java.time.Duration;
+
+/**
+ * Documentation can be found here:
+ *
+ * @link https://infosys.beckhoff.com/english.php?content=../content/1033/tcsystemmanager/basics/TcSysMgr_DatatypeComparison.htm&id=
+ * @link https://infosys.beckhoff.com/english.php?content=../content/1033/tcplccontrol/html/tcplcctrl_plc_data_types_overview.htm&id
+ */
 public enum AdsDataType {
+    // TODO: maybe this are just types for the plc ide and can be removed
     // https://infosys.beckhoff.com/english.php?content=../content/1033/tcsystemmanager/basics/TcSysMgr_DatatypeComparison.htm&id=
-    BIT(1),
-    BIT8(1),
-    BITARR8(1),
-    BITARR16(2),
-    BITARR32(4),
-    INT8(1),
-    INT16(2),
-    INT32(4),
-    INT64(8),
-    UINT8(1),
-    UINT16(2),
-    UINT32(4),
-    UINT64(8),
-    FLOAT(4),
-    DOUBLE(8),
+    BIT(8),
+    BIT8(8),
+    BITARR8(8),
+    BITARR16(16),
+    BITARR32(32),
+    INT8(8),
+    INT16(16),
+    INT32(32),
+    INT64(64),
+    UINT8(8),
+    UINT16(16),
+    UINT32(32),
+    UINT64(64),
+    FLOAT(32),
+    DOUBLE(64),
     // https://infosys.beckhoff.com/english.php?content=../content/1033/tcplccontrol/html/tcplcctrl_plc_data_types_overview.htm&id
-    BOOL(0),
-    BYTE(0),
-    WORD(0),
-    DWORD(0),
-    SINT(0),
-    USINT(0),
-    INT(0),
-    UINT(0),
-    DINT(0),
-    UDINT(0),
-    LINT(0),
-    ULINT(0),
-    REAL(0),
-    LREAL(0),
-    STRING(0),
-    TIME(0),
-    TIME_OF_DAY(0),
-    DATE(0),
-    DATE_AND_TIME(0);
-
-    private final int tagetByteSize;
-
-    AdsDataType(int tagetByteSize) {
-        this.tagetByteSize = tagetByteSize;
+    // Standard Data Types
+    /**
+     * BOOL type variables may be given the values TRUE and FALSE.
+     * <p>
+     * Type	Memory use
+     * BOOL	8 Bit
+     * Note:
+     * <p>
+     * A BOOL type variable is true, if the least significant bit in the memory is set (e.g. 2#00000001 ). If no bit is set in the memory, the variable is FALSE (2#00000000). All other values can´t be interpeted accurately and be displayed (***INVALID: 16#xy *** in the Online View). Such problems may appear, if for example overlapped memory ranges are used in the PLC program.
+     * <p>
+     * Example:
+     * <p>
+     * The boolean variable is in the same memory range as the byte variable.
+     */
+    BOOL(8),
+    /**
+     * BYTE
+     * <p>
+     * Integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * BYTE	0	255	8 Bit
+     */
+    BYTE(0, 255, 8),
+    /**
+     * WORD
+     * Integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * WORD	0	65535	16 Bit
+     */
+    WORD(0, 65535, 16),
+    /**
+     * DWORD
+     * Integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * DWORD	0	4294967295	32 Bit
+     */
+    DWORD(0, 4294967295L, 32),
+    /**
+     * SINT
+     * (Short) signed integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * SINT	-128	127	8 Bit
+     */
+    SINT(-128, 127, 8),
+    /**
+     * USINT
+     * Unsigned (short) integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * USINT	0	255	8 Bit
+     */
+    USINT(0, 255, 8),
+    /**
+     * INT
+     * Signed integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * INT	-32768	32767	16 Bit
+     */
+    INT(-32768, 32767, 16),
+    /**
+     * UINT
+     * Unsigned integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * UINT	0	65535	16 Bit
+     */
+    UINT(0, 65535, 16),
+    /**
+     * DINT
+     * Signed integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * DINT	-2147483648	2147483647	32 Bit
+     */
+    DINT(-2147483648, 2147483647, 32),
+    /**
+     * UDINT
+     * Unsigned integer data type.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * UDINT	0	4294967295	32 Bit
+     */
+    UDINT(0, 4294967295L, 32),
+    /**
+     * LINT  (64 bit integer, currently not supported by TwinCAT)
+     */
+    LINT(64),
+    /**
+     * ULINT (Unsigned 64 bit integer, currently not supported by TwinCAT)
+     */
+    ULINT(64),
+    /**
+     * REAL
+     * 32 Bit floating point data type. It is required to represent rational numbers.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * REAL	~ -3.402823 x 1038	~ 3.402823 x 1038	32 Bit
+     */
+    REAL(Float.MAX_VALUE, Float.MAX_VALUE, 32),
+    /**
+     * LREAL
+     * 64 Bit floating point data type. It is required to represent rational numbers.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * LREAL	~ -1.79769313486231E308	~ 1.79769313486232E308	64 Bit
+     */
+    LREAL(Double.MIN_VALUE, Double.MAX_VALUE, 64),
+    /**
+     * STRING
+     * A STRING type variable can contain any string of characters. The size entry in the declaration determines how much memory space should be reserved for the variable. It refers to the number of characters in the string and can be placed in parentheses or square brackets.
+     * <p>
+     * Example of a string declaration with 35 characters:
+     * <p>
+     * str:STRING(35):='This is a String';
+     * Type	Memory use
+     * STRING
+     * If no size specification is given, the default size of 80 characters will be used: Memory use [Bytes] =  80 + 1 Byte for string terminated Null character;
+     * If string size specification is given: Memory use [Bytes] = String Size + 1 Byte for string terminated Null character);
+     */
+    STRING(81),
+    /**
+     * TIME
+     * Duration time. The most siginificant digit is one millisecond. The data type is handled internally like DWORD.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * TIME	T#0ms	T#71582m47s295ms	32 Bit
+     */
+    TIME(0, Duration.ofMinutes(71582).plusSeconds(47).plusMillis(295).toMillis(), 32),
+    /**
+     * TIME_OF_DAY
+     * TOD
+     * Time of day. The most siginificant digit is one millisecond. The data type is handled internally like DWORD.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * TIME_OF_DAY
+     * TOD
+     * <p>
+     * TOD#00:00	TOD#1193:02:47.295	32 Bit
+     *///TODO: strange maximum
+    TIME_OF_DAY(0, Duration.ofHours(23).plusMinutes(59).plusSeconds(59).plusMillis(999).toMillis(), 32),
+    /**
+     * DATE
+     * Date. The most significant digit is one second. The data type is handled internally like DWORD.
+     * <p>
+     * Type	Lower bound	Upper bound	Memory use
+     * DATE	D#1970-01-01	D#2106-02-06	32 Bit
+     *///TODO: calculate max
+    DATE(0, -1, 32),
+    /**
+     * DATE_AND_TIME
+     * DT
+     * Date and time. The most siginificant digit is one second. The data type is handled internally like DWORD.
+     * <p>
+     * Type	Lower  bound	Upper  bound	Memory use
+     * DATE_AND_TIME
+     * DT
+     * <p>
+     * DT#1970-01-01-00:00	DT#2106-02-06-06:28:15	32 Bit
+     *////TODO: calculate max
+    DATE_AND_TIME(0, -1, 32),
+    //User-defined Data Types
+    /**
+     * Arrays
+     * One-, two-, and three-dimensional fields (arrays) are supported as elementary data types. Arrays can be defined both in the declaration part of a POU and in the global variable lists.
+     * <p>
+     * Syntax:
+     *
+     * <Field_Name>:ARRAY [<LowLim1>..<UpLim1>, <LowLim2>..<UpLim2>] OF <elem. Type>
+     * <p>
+     * LowLim1, LowLim2 identify the lower limit of the field range; UpLim1 and UpLim2 identify the upper limit. The range values must be integers.
+     * <p>
+     * Example:
+     * <p>
+     * Card_game: ARRAY [1..13, 1..4] OF INT;
+     * <p>
+     * <p>
+     * <p>
+     * Initializing of Arrays
+     * You can initialize either all of the elements in an array or none of them.
+     * <p>
+     * Example for initializing arrays:
+     * <p>
+     * arr1 : ARRAY [1..5] OF INT := 1,2,3,4,5;
+     * arr2 : ARRAY [1..2,3..4] OF INT := 1,3(7); (* short for 1,7,7,7 *)
+     * arr3 : ARRAY [1..2,2..3,3..4] OF INT := 2(0),4(4),2,3; (* short for 0,0,4,4,4,4,2,3 *)
+     * <p>
+     * <p>
+     * <p>
+     * Example for the initialization of an array of a structure:
+     * <p>
+     * TYPE STRUCT1
+     * STRUCT
+     * p1:int;
+     * p2:int;
+     * p3:dword;
+     * END_STRUCT
+     * arr1 : ARRAY[1..3] OF STRUCT1:= (p1:=1,p2:=10,p3:=4723), (p1:=2,p2:=0,p3:=299), (p1:=14,p2:=5,p3:=112);
+     * <p>
+     * <p>
+     * Example of the partial initialization of an Array:
+     * <p>
+     * arr1 : ARRAY [1..10] OF INT := 1,2;
+     * Elements to which no value is pre-assigned are initialized with the default initial value of the basic type. In the example above, the elements arr1[3]  to arr1[10] are therefore initialized with 0.
+     * <p>
+     * <p>
+     * <p>
+     * Array components are accessed in a two-dimensional array using the following syntax:
+     *
+     * <Field_Name>[Index1,Index2]
+     * <p>
+     * Example:
+     * <p>
+     * Card_game[9,2]
+     * <p>
+     * <p>
+     * <p>
+     * Note:
+     * <p>
+     * If you define a function in your project with the name CheckBounds, you can automatically check for out-of-range errors in arrays ! The name of the function is fixed and can only have this designation.
+     */
+    ARRAY(-1),//TODO: implement me
+    /**
+     * Pointer
+     * Variable or function block addresses are saved in pointers while a program is running. Pointer declarations have the following syntax:
+     *
+     * <Identifier>: POINTER TO <Datatype/Functionblock>;
+     * A pointer can point to any data type or function block even to user-defined types. The function of the Address Operator ADR is to assign the address of a variable or function block to the pointer.
+     * A pointer can be dereferenced by adding the content operator "^" after the pointer identifier. With the help of the SIZEOF Operator, e.g. a pointer increment can be done.
+     * <p>
+     * <p>
+     * Please note: A pointer is counted up byte-wise ! You can get it counted up like it is usual in the C-Compiler by using the instruction p=p+SIZEOF(p^);.
+     * <p>
+     * <p>
+     * <p>
+     * Attention:
+     * After an Online Change there might be changes concerning the data on certain addresses. Please regard this in case of using pointers on addresses.
+     * <p>
+     * <p>
+     * <p>
+     * Example:
+     * <p>
+     * pt:POINTER TO INT;
+     * var_int1:INT := 5;
+     * var_int2:INT;
+     * <p>
+     * <p>
+     * pt := ADR(var_int1);
+     * var_int2:= pt^; (* var_int2 is now 5 *)
+     * <p>
+     * <p>
+     * Example 2 (Pointer increment):
+     * <p>
+     * ptByCurrDataOffs : POINTER TO BYTE;
+     * udiAddress       : UDINT;
+     * <p>
+     * <p>
+     * <p>
+     * (*--- pointer increment ---*)
+     * udiAddress := ptByCurrDataOffs;
+     * udiAddress := udiAddress + SIZEOF(ptByCurrDataOffs^);
+     * ptByCurrDataOffs := udiAddress;
+     * (* -- end of pointer increment ---*)
+     */
+    POINTER(-1),//TODO: implement me,
+    /**
+     * Enumeration (ENUM)
+     * Enumeration is a user-defined data type that is made up of a number of string constants. These constants are referred to as enumeration values. Enumeration values are recognized in all areas of the project even if they were locally declared within aPOU. It is best to create your enumerations as objects in the Object Organizer under the register card Data types. They begin with the keyword TYPE and end with END_TYPE.
+     * <p>
+     * Syntax:
+     * <p>
+     * TYPE <Identifier>:(<Enum_0> ,<Enum_1>, ...,<Enum_n>);END_TYPE
+     * <p>
+     * The <Identifier> can take on one of the enumeration values and will be initialized with the first one. These values are compatible with whole numbers which means that you can perform operations with them just as you would with INT. You can assign a number x to the <Identifier>. If the enumeration values are not initialized, counting will begin with 0. When initializing, make certain the initial values are increasing. The validity of the number will be reviewed at the time it is run.
+     * <p>
+     * Example:
+     * <p>
+     * TRAFFIC_SIGNAL: (Red, Yellow, Green:=10); (*The initial value for each of the colors is red 0, yellow 1, green 10 *)
+     * TRAFFIC_SIGNAL:=0; (* The value of the traffic signal is red*)
+     * FOR i:= Red TO Green DO
+     * i := i + 1;
+     * END_FOR;
+     * <p>
+     * You may not use the same enumeration value more than once.
+     * <p>
+     * Example:
+     * <p>
+     * TRAFFIC_SIGNAL: (red, yellow, green);
+     * COLOR: (blue, white, red);
+     * <p>
+     * Error: red may not be used for both TRAFFIC_SIGNAL and COLOR.
+     */
+    ENUM(-1),//TODO: implement me,
+    /**
+     * Structures (STRUCT)
+     * Structures are created as objects in the Object Organizer under the register card Data types. They begin with the keyword TYPE and end with END_TYPE.The syntax for structure declarations is as follows:
+     * <p>
+     * TYPE <Structurename>:
+     * STRUCT
+     * <Declaration of Variables 1>
+     * .
+     * .
+     * <Declaration of Variables n>
+     * END_STRUCT
+     * END_TYPE
+     *
+     * <Structurename> is a type that is recognized throughout the project and can be used like a standard data type. Interlocking structures are allowed. The only restriction is that variables may not be placed at addresses (the AT declaration is not allowed!).
+     * <p>
+     * Example for a structure definition named Polygonline:
+     * <p>
+     * TYPE Polygonline:
+     * STRUCT
+     * Start:ARRAY [1..2] OF INT;
+     * Point1:ARRAY [1..2] OF INT;
+     * Point2:ARRAY [1..2] OF INT;
+     * Point3:ARRAY [1..2] OF INT;
+     * Point4:ARRAY [1..2] OF INT;
+     * End:ARRAY [1..2] OF INT;
+     * END_STRUCT
+     * END_TYPE
+     * <p>
+     * You can gain access to structure components using the following syntax:
+     *
+     * <Structure_Name>.<Componentname>
+     * <p>
+     * For example, if you have a structure named "Week" that contains a component named "Monday", you can get to it by doing the following: Week.Monday
+     * <p>
+     * <p>
+     * <p>
+     * Note:
+     * Due to different alignments, structures and arrays may have different configurations and sizes on different hardware platforms (e.g. CX1000 and CX90xx).
+     * <p>
+     * During data exchange the size and structure alignment must be identical!
+     * <p>
+     * <p>
+     * <p>
+     * Example for a structure definition with name ST_ALIGN_SAMPLE:
+     * <p>
+     * TYPE ST_ALIGN_SAMPLE:
+     * STRUCT
+     * _diField1   : DINT;
+     * _byField1   : BYTE;
+     * _iField     : INT;
+     * _byField2   : BYTE;
+     * _diField2   : DINT;
+     * _pField     : POINTER TO BYTE;
+     * END_STRUCT
+     * END_TYPE
+     * <p>
+     * On CX90xx (RISC) platforms the member components of structure ST_ALIGN_SAMPLE have the following sizes and offsets:
+     * <p>
+     * _diField1 (DINT), Offset = 0 (16#0),   Size = 4
+     * _byField1 (BYTE), Offset = 4 (16#4),   Size = 1
+     * _iField (INT), Offset = 6 (16#6),   Size = 2
+     * _byField2 (BYTE), Offset = 8 (16#8),   Size = 1
+     * _diField2 (DINT), Offset = 12 (16#C),  Size = 4
+     * _pField (POINTER TO BYTE), Offset = 16 (16#10), Size = 4
+     * <p>
+     * Overall size through natural alignment with Pack(4) and so-called padding bytes: 20
+     * <p>
+     * <p>
+     * <p>
+     * On CX10xx platforms the member components of structure ST_ALIGN_SAMPLE have the following sizes and offsets:
+     * <p>
+     * _diField1 (DINT), Offset = 0 (16#0),   Size = 4
+     * _byField1 (BYTE), Offset = 4 (16#4),   Size = 1
+     * _iField (INT), Offset = 5 (16#5),   Size = 2
+     * _byField2 (BYTE), Offset = 7 (16#7),   Size = 1
+     * _diField2 (DINT), Offset = 8 (16#8),  Size = 4
+     * _pField (POINTER TO BYTE), Offset = 12 (16#C), Size = 4
+     * <p>
+     * Overall size: 16
+     * <p>
+     * <p>
+     * <p>
+     * Display of structure ST_ALIGN_SAMPLE for CX90xx platforms (RISC) with representation of the padding bytes:
+     * <p>
+     * TYPE ST_ALIGN_SAMPLE:
+     * STRUCT
+     * _diField1    : DINT;
+     * _byField1    : BYTE;
+     * _byPadding   : BYTE;
+     * _iField      : INT;
+     * _byField2    : BYTE;
+     * _a_byPadding : ARRAY[0..2] OF BYTE;
+     * _diField2    : DINT;
+     * _pField      : POINTER TO BYTE;
+     * END_STRUCT
+     * END_TYPE
+     */
+    STRUCT(-1),//TODO: implement me,
+    /**
+     * References (Alias types)
+     * You can use the user-defined derived data type to create an alternative name for a variable, constant or function block. Create your references as objects in the Object Organizer under the register card Data types. They begin with the keyword TYPE and end with END_TYPE.
+     * <p>
+     * Syntax:
+     * <p>
+     * TYPE <Identifier>: <Assignment term>;
+     * END_TYPE
+     * <p>
+     * Example:
+     * <p>
+     * TYPE message:STRING[50];
+     * END_TYPE;
+     */
+    ALIAS(-1),//TODO: implement me,
+    /**
+     * Subrange types
+     * A sub-range data type is a type whose range of values is only a subset of that of the basic type. The declaration can be carried out in the data types register, but a variable can also be directly declared with a subrange type:
+     * Syntax for the declaration in the 'Data types' register:
+     * <p>
+     * TYPE <Name> : <Inttype> (<ug>..<og>) END_TYPE;
+     * Type	Description
+     * <Name>	must be a valid IEC identifier
+     * <Inttype>	is one of the data types SINT, USINT, INT, UINT, DINT, UDINT, BYTE, WORD, DWORD (LINT, ULINT, LWORD).
+     * <ug>	Is a constant which must be compatible with the basic type and which sets the lower boundary of the range types. The lower boundary itself is included in this range.
+     * <og>	Is a constant that must be compatible with the basic type, and sets the upper boundary of the range types. The upper boundary itself is included in this basic type.
+     * Example:
+     * <p>
+     * TYPE
+     * SubInt : INT (-4095..4095);
+     * END_TYPE
+     * Direct declaration of a variable with a subrange type:
+     * <p>
+     * VAR
+     * i1 : INT (-4095..4095);
+     * i2: INT (5...10):=5;
+     * ui : UINT (0..10000);
+     * END_VAR
+     * If a constant is assigned to a subrange type (in the declaration or in the implementation) that does not apply to this range (e.g. 1:=5000), an error message is issued.
+     * In order to check for observance of range boundaries at runtime, the functions CheckRangeSigned or CheckRangeUnsigned must be introduced.
+     */
+    SUB_RANGE_DATA_TYPE(-1),//TODO: implement me,
+
+    UNKNOWN(-1);
+
+    private final String typeName;
+
+    private final double lowerBound;
+
+    private final double upperBound;
+
+    private final int memoryUse;
+
+    private final int targetByteSize;
+
+    AdsDataType(int memoryUse) {
+        this(-1, -1, memoryUse);
+    }
+
+    AdsDataType(double lowerBound, double upperBound, int memoryUse) {
+        this.lowerBound = lowerBound;
+        this.upperBound = upperBound;
+        this.typeName = name();
+        this.memoryUse = memoryUse;
+        this.targetByteSize = this.memoryUse * 8;
+    }
+
+    public String getTypeName() {
+        return typeName;
+    }
+
+    public double getLowerBound() {
+        return lowerBound;
+    }
+
+    public double getUpperBound() {
+        return upperBound;
+    }
+
+    public int getMemoryUse() {
+        return memoryUse;
     }
 
-    public int getTagetByteSize() {
-        return tagetByteSize;
+    public int getTargetByteSize() {
+        return targetByteSize;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
index e5a1822..cab080b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
@@ -18,124 +18,8 @@
  */
 package org.apache.plc4x.java.ads.model;
 
-import org.apache.plc4x.java.ads.api.util.ByteValue;
-import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
 import org.apache.plc4x.java.api.model.PlcField;
 
-import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * ADS address witch is defined by {@code indexGroup/indexOffset}. These values can be either supplied as int or hex
- * representation.
- */
-public class AdsField implements PlcField {
-
-    private static final Pattern RESOURCE_ADDRESS_PATTERN = Pattern.compile("^((0[xX](?<indexGroupHex>[0-9a-fA-F]+))|(?<indexGroup>\\d+))/((0[xX](?<indexOffsetHex>[0-9a-fA-F]+))|(?<indexOffset>\\d+)):(?<adsDataType>.+)(\\[(?<numberOfElements>\\d)])?");
-
-    private final long indexGroup;
-
-    private final long indexOffset;
-
-    private final AdsDataType adsDataType;
-
-    private final int numberOfElements;
-
-    private AdsField(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
-        ByteValue.checkUnsignedBounds(indexGroup, 4);
-        this.indexGroup = indexGroup;
-        ByteValue.checkUnsignedBounds(indexOffset, 4);
-        this.indexOffset = indexOffset;
-        this.adsDataType = Objects.requireNonNull(adsDataType);
-        this.numberOfElements = numberOfElements != null ? numberOfElements : 1;
-        if (this.numberOfElements <= 0) {
-            throw new IllegalArgumentException("numberOfElements must be greater then zero. Was " + this.numberOfElements);
-        }
-    }
-
-    public static AdsField of(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
-        return new AdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
-    }
-
-    public static AdsField of(String address) throws PlcInvalidFieldException {
-        Matcher matcher = RESOURCE_ADDRESS_PATTERN.matcher(address);
-        if (!matcher.matches()) {
-            throw new PlcInvalidFieldException(address, RESOURCE_ADDRESS_PATTERN, "{indexGroup}/{indexOffset}:{adsDataType}([numberOfElements])?");
-        }
-
-        String indexGroupStringHex = matcher.group("indexGroupHex");
-        String indexGroupString = matcher.group("indexGroup");
-
-        String indexOffsetStringHex = matcher.group("indexOffsetHex");
-        String indexOffsetString = matcher.group("indexOffset");
-
-        long indexGroup;
-        if (indexGroupStringHex != null) {
-            indexGroup = Long.parseLong(indexGroupStringHex, 16);
-        } else {
-            indexGroup = Long.parseLong(indexGroupString);
-        }
-
-        long indexOffset;
-        if (indexOffsetStringHex != null) {
-            indexOffset = Long.parseLong(indexOffsetStringHex, 16);
-        } else {
-            indexOffset = Long.parseLong(indexOffsetString);
-        }
-
-        String adsDataTypeString = matcher.group("adsDataType");
-        AdsDataType adsDataType = AdsDataType.valueOf(adsDataTypeString);
-
-        String numberOfElementsString = matcher.group("numberOfElements");
-        Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null;
-
-        return new AdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
-    }
-
-    public static boolean matches(String address) {
-        return RESOURCE_ADDRESS_PATTERN.matcher(address).matches();
-    }
-
-    public long getIndexGroup() {
-        return indexGroup;
-    }
-
-    public long getIndexOffset() {
-        return indexOffset;
-    }
-
-    public AdsDataType getAdsDataType() {
-        return adsDataType;
-    }
-
-    public int getNumberOfElements() {
-        return numberOfElements;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof AdsField)) {
-            return false;
-        }
-        AdsField that = (AdsField) o;
-        return indexGroup == that.indexGroup &&
-            indexOffset == that.indexOffset;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(indexGroup, indexOffset);
-    }
-
-    @Override
-    public String toString() {
-        return "AdsField{" +
-            "indexGroup=" + indexGroup +
-            ", indexOffset=" + indexOffset +
-            '}';
-    }
+public interface AdsField extends PlcField {
+    AdsDataType getAdsDataType();
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsPlcFieldHandler.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsPlcFieldHandler.java
index 0029fa7..bb6e70c 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsPlcFieldHandler.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsPlcFieldHandler.java
@@ -18,18 +18,27 @@
  */
 package org.apache.plc4x.java.ads.model;
 
-import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.base.connection.PlcFieldHandler;
-import org.apache.plc4x.java.base.messages.items.FieldItem;
+import org.apache.plc4x.java.base.messages.items.*;
 
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.util.BitSet;
+import java.util.LinkedList;
+import java.util.List;
+
+// TODO: implement me acording to ads. currently copy pasta from S7
+// Use endian decoders.
+// TODO: replace all ifs with switches
 public class AdsPlcFieldHandler implements PlcFieldHandler {
 
     @Override
     public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
-        if (AdsField.matches(fieldQuery)) {
-            return AdsField.of(fieldQuery);
+        if (DirectAdsField.matches(fieldQuery)) {
+            return DirectAdsField.of(fieldQuery);
         } else if (SymbolicAdsField.matches(fieldQuery)) {
             return SymbolicAdsField.of(fieldQuery);
         }
@@ -38,67 +47,1154 @@ public class AdsPlcFieldHandler implements PlcFieldHandler {
 
     @Override
     public FieldItem encodeBoolean(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        // All of these types are declared as Bit or Bit-String types.
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeBoolean(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeByte(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeInteger(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeShort(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeInteger(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeInteger(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeInteger(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+    }
+
+    @Override
+    public FieldItem encodeBigInteger(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeInteger(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeLong(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeInteger(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeFloat(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeFloatingPoint(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeDouble(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeFloatingPoint(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeString(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeString(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeTime(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeTemporal(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeDate(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeTemporal(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
     }
 
     @Override
     public FieldItem encodeDateTime(PlcField field, Object[] values) {
-        // TODO: implement me
-        throw new NotImplementedException("not yet implemented");
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+                return internalEncodeTemporal(field, values);
+            case UNKNOWN:
+            default:
+                throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+    }
+
+    private FieldItem internalEncodeBoolean(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+            case UNKNOWN:
+            default:
+                //throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+        switch (adsField.getAdsDataType()) {
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+                break;
+            default:
+                throw new IllegalArgumentException(
+                    "Cannot assign boolean values to " + adsField.getAdsDataType().name() + " fields.");
+        }
+        List<Boolean> booleanValues = new LinkedList<>();
+        for (Object value : values) {
+            if (value instanceof Boolean) {
+                Boolean booleanValue = (Boolean) value;
+                booleanValues.add(booleanValue);
+            } else if (value instanceof Byte) {
+                Byte byteValue = (Byte) value;
+                BitSet bitSet = BitSet.valueOf(new byte[]{byteValue});
+                for (int i = 0; i < 8; i++) {
+                    booleanValues.add(bitSet.get(i));
+                }
+            } else if (value instanceof Short) {
+                Short shortValue = (Short) value;
+                BitSet bitSet = BitSet.valueOf(new long[]{shortValue});
+                for (int i = 0; i < 16; i++) {
+                    booleanValues.add(bitSet.get(i));
+                }
+            } else if (value instanceof Integer) {
+                Integer integerValue = (Integer) value;
+                BitSet bitSet = BitSet.valueOf(new long[]{integerValue});
+                for (int i = 0; i < 32; i++) {
+                    booleanValues.add(bitSet.get(i));
+                }
+            } else if (value instanceof Long) {
+                long longValue = (Long) value;
+                BitSet bitSet = BitSet.valueOf(new long[]{longValue});
+                for (int i = 0; i < 64; i++) {
+                    booleanValues.add(bitSet.get(i));
+                }
+            } else {
+                throw new IllegalArgumentException(
+                    "Value of type " + value.getClass().getName() +
+                        " is not assignable to " + adsField.getAdsDataType().name() + " fields.");
+            }
+        }
+        return new DefaultBooleanFieldItem(booleanValues.toArray(new Boolean[0]));
+    }
+
+    private FieldItem internalEncodeInteger(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+            case UNKNOWN:
+            default:
+                //throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+        BigInteger minValue;
+        BigInteger maxValue;
+        Class<? extends FieldItem> fieldType;
+        switch (adsField.getAdsDataType()) {
+            case BYTE:
+                minValue = BigInteger.valueOf((long) Byte.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Byte.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case WORD:
+                minValue = BigInteger.valueOf((long) Short.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Short.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case DWORD:
+                minValue = BigInteger.valueOf((long) Integer.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Integer.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case SINT:
+                minValue = BigInteger.valueOf((long) Byte.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Byte.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case USINT:
+                minValue = BigInteger.valueOf((long) 0);
+                maxValue = BigInteger.valueOf((long) Byte.MAX_VALUE * 2);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case INT:
+                minValue = BigInteger.valueOf((long) Short.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Short.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case UINT:
+                minValue = BigInteger.valueOf((long) 0);
+                maxValue = BigInteger.valueOf(((long) Short.MAX_VALUE) * 2);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case DINT:
+                minValue = BigInteger.valueOf((long) Integer.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Integer.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case UDINT:
+                minValue = BigInteger.valueOf((long) 0);
+                maxValue = BigInteger.valueOf(((long) Integer.MAX_VALUE) * 2);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case LINT:
+                minValue = BigInteger.valueOf(Long.MIN_VALUE);
+                maxValue = BigInteger.valueOf(Long.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case ULINT:
+                minValue = BigInteger.valueOf((long) 0);
+                maxValue = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf((long) 2));
+                fieldType = DefaultBigIntegerFieldItem.class;
+                break;
+            case INT32:
+                minValue = BigInteger.valueOf((long) Integer.MIN_VALUE);
+                maxValue = BigInteger.valueOf((long) Integer.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            case INT64:
+                minValue = BigInteger.valueOf(Long.MIN_VALUE);
+                maxValue = BigInteger.valueOf(Long.MAX_VALUE);
+                fieldType = DefaultIntegerFieldItem.class;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                    "Cannot assign integer values to " + adsField.getAdsDataType().name() + " fields.");
+        }
+        if (fieldType == DefaultIntegerFieldItem.class) {
+            Long[] longValues = new Long[values.length];
+            for (int i = 0; i < values.length; i++) {
+                if (!((values[i] instanceof Byte) || (values[i] instanceof Short) ||
+                    (values[i] instanceof Integer) || (values[i] instanceof BigInteger) || (values[i] instanceof Long))) {
+                    throw new IllegalArgumentException(
+                        "Value of type " + values[i].getClass().getName() +
+                            " is not assignable to " + adsField.getAdsDataType().name() + " fields.");
+                }
+                BigInteger value = BigInteger.valueOf(((Number) values[i]).longValue());
+                if (minValue.compareTo(value) > 0) {
+                    throw new IllegalArgumentException(
+                        "Value of " + value.toString() + " exceeds allowed minimum for type "
+                            + adsField.getAdsDataType().name() + " (min " + minValue.toString() + ")");
+                }
+                if (maxValue.compareTo(value) < 0) {
+                    throw new IllegalArgumentException(
+                        "Value of " + value.toString() + " exceeds allowed maximum for type "
+                            + adsField.getAdsDataType().name() + " (max " + maxValue.toString() + ")");
+                }
+                longValues[i] = value.longValue();
+            }
+            return new DefaultIntegerFieldItem(longValues);
+        } else {
+            BigInteger[] bigIntegerValues = new BigInteger[values.length];
+            for (int i = 0; i < values.length; i++) {
+                BigInteger value;
+                if (values[i] instanceof BigInteger) {
+                    value = (BigInteger) values[i];
+                } else if (((values[i] instanceof Byte) || (values[i] instanceof Short) ||
+                    (values[i] instanceof Integer) || (values[i] instanceof Long))) {
+                    value = BigInteger.valueOf(((Number) values[i]).longValue());
+                } else {
+                    throw new IllegalArgumentException(
+                        "Value of type " + values[i].getClass().getName() +
+                            " is not assignable to " + adsField.getAdsDataType().name() + " fields.");
+                }
+                if (minValue.compareTo(value) > 0) {
+                    throw new IllegalArgumentException(
+                        "Value of " + value.toString() + " exceeds allowed minimum for type "
+                            + adsField.getAdsDataType().name() + " (min " + minValue.toString() + ")");
+                }
+                if (maxValue.compareTo(value) < 0) {
+                    throw new IllegalArgumentException(
+                        "Value of " + value.toString() + " exceeds allowed maximum for type "
+                            + adsField.getAdsDataType().name() + " (max " + maxValue.toString() + ")");
+                }
+                bigIntegerValues[i] = value;
+            }
+            return new DefaultBigIntegerFieldItem(bigIntegerValues);
+        }
+    }
+
+    private FieldItem internalEncodeFloatingPoint(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+            case UNKNOWN:
+            default:
+                //throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+        Double minValue;
+        Double maxValue;
+        switch (adsField.getAdsDataType()) {
+            case REAL:
+                // Yes this is actually correct, if I set min to Float.MIN_VALUE (0.0 < Float.MIN_VALUE = true)
+                minValue = (double) -Float.MAX_VALUE;
+                maxValue = (double) Float.MAX_VALUE;
+                break;
+            case LREAL:
+                // Yes this is actually correct, if I set min to Double.MIN_VALUE (0.0 < Double.MIN_VALUE = true)
+                minValue = -Double.MAX_VALUE;
+                maxValue = Double.MAX_VALUE;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                    "Cannot assign floating point values to " + adsField.getAdsDataType().name() + " fields.");
+        }
+        Double[] floatingPointValues = new Double[values.length];
+        for (int i = 0; i < values.length; i++) {
+            if (values[i] instanceof Float) {
+                floatingPointValues[i] = ((Float) values[i]).doubleValue();
+            } else if (values[i] instanceof Double) {
+                floatingPointValues[i] = (Double) values[i];
+            } else {
+                throw new IllegalArgumentException(
+                    "Value of type " + values[i].getClass().getName() +
+                        " is not assignable to " + adsField.getAdsDataType().name() + " fields.");
+            }
+            if (floatingPointValues[i] < minValue) {
+                throw new IllegalArgumentException(
+                    "Value of " + floatingPointValues[i] + " exceeds allowed minimum for type "
+                        + adsField.getAdsDataType().name() + " (min " + minValue.toString() + ")");
+            }
+            if (floatingPointValues[i] > maxValue) {
+                throw new IllegalArgumentException(
+                    "Value of " + floatingPointValues[i] + " exceeds allowed maximum for type "
+                        + adsField.getAdsDataType().name() + " (max " + maxValue.toString() + ")");
+            }
+        }
+        return new DefaultFloatingPointFieldItem(floatingPointValues);
+    }
+
+    private FieldItem internalEncodeString(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+            case UNKNOWN:
+            default:
+                //throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+        int maxLength;
+        boolean encoding16Bit;
+        switch (adsField.getAdsDataType()) {
+            case STRING:
+                maxLength = 254;
+                encoding16Bit = false;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                    "Cannot assign string values to " + adsField.getAdsDataType().name() + " fields.");
+        }
+        List<String> stringValues = new LinkedList<>();
+        for (Object value : values) {
+            if (value instanceof String) {
+                String stringValue = (String) value;
+                if (stringValue.length() > maxLength) {
+                    throw new IllegalArgumentException(
+                        "String length " + stringValue.length() + " exceeds allowed maximum for type "
+                            + adsField.getAdsDataType().name() + " (max " + maxLength + ")");
+                }
+                stringValues.add(stringValue);
+            }
+            // All other types just translate to max one String character.
+            else if (value instanceof Byte) {
+                Byte byteValue = (Byte) value;
+                byte[] stringBytes = new byte[]{byteValue};
+                if (encoding16Bit) {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
+                } else {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
+                }
+            } else if (value instanceof Short) {
+                Short shortValue = (Short) value;
+                byte[] stringBytes = new byte[2];
+                stringBytes[0] = (byte) (shortValue >> 8);
+                stringBytes[1] = (byte) (shortValue & 0xFF);
+                if (encoding16Bit) {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
+                } else {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
+                }
+            } else if (value instanceof Integer) {
+                Integer integerValue = (Integer) value;
+                byte[] stringBytes = new byte[4];
+                stringBytes[0] = (byte) ((integerValue >> 24) & 0xFF);
+                stringBytes[1] = (byte) ((integerValue >> 16) & 0xFF);
+                stringBytes[2] = (byte) ((integerValue >> 8) & 0xFF);
+                stringBytes[3] = (byte) (integerValue & 0xFF);
+                if (encoding16Bit) {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
+                } else {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
+                }
+            } else if (value instanceof Long) {
+                Long longValue = (Long) value;
+                byte[] stringBytes = new byte[8];
+                stringBytes[0] = (byte) ((longValue >> 56) & 0xFF);
+                stringBytes[1] = (byte) ((longValue >> 48) & 0xFF);
+                stringBytes[2] = (byte) ((longValue >> 40) & 0xFF);
+                stringBytes[3] = (byte) ((longValue >> 32) & 0xFF);
+                stringBytes[4] = (byte) ((longValue >> 24) & 0xFF);
+                stringBytes[5] = (byte) ((longValue >> 16) & 0xFF);
+                stringBytes[6] = (byte) ((longValue >> 8) & 0xFF);
+                stringBytes[7] = (byte) (longValue & 0xFF);
+                if (encoding16Bit) {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-16")));
+                } else {
+                    stringValues.add(new String(stringBytes, Charset.forName("UTF-8")));
+                }
+            } else {
+                throw new IllegalArgumentException(
+                    "Value of type " + value.getClass().getName() +
+                        " is not assignable to " + adsField.getAdsDataType().name() + " fields.");
+            }
+        }
+        return new DefaultStringFieldItem(stringValues.toArray(new String[0]));
+    }
+
+    private FieldItem internalEncodeTemporal(PlcField field, Object[] values) {
+        AdsField adsField = (AdsField) field;
+        switch (adsField.getAdsDataType()) {
+            case BIT:
+            case BIT8:
+            case BITARR8:
+            case BITARR16:
+            case BITARR32:
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case UINT8:
+            case UINT16:
+            case UINT32:
+            case UINT64:
+            case FLOAT:
+            case DOUBLE:
+            case BOOL:
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case SINT:
+            case USINT:
+            case INT:
+            case UINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+            case STRING:
+            case TIME:
+            case TIME_OF_DAY:
+            case DATE:
+            case DATE_AND_TIME:
+            case ARRAY:
+            case POINTER:
+            case ENUM:
+            case STRUCT:
+            case ALIAS:
+            case SUB_RANGE_DATA_TYPE:
+            case UNKNOWN:
+            default:
+                //throw new PlcRuntimeException("Invalid encoder for type " + adsField.getAdsDataType().name());
+        }
+        switch (adsField.getAdsDataType()) {
+            case TIME:
+            case DATE:
+            case DATE_AND_TIME:
+                return new DefaultTimeFieldItem();
+            default:
+                throw new IllegalArgumentException(
+                    "Cannot assign temporal values to " + adsField.getAdsDataType().name() + " fields.");
+        }
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/DirectAdsField.java
similarity index 85%
copy from plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
copy to plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/DirectAdsField.java
index e5a1822..70211de 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/AdsField.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/DirectAdsField.java
@@ -20,7 +20,6 @@ package org.apache.plc4x.java.ads.model;
 
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
-import org.apache.plc4x.java.api.model.PlcField;
 
 import java.util.Objects;
 import java.util.regex.Matcher;
@@ -30,9 +29,9 @@ import java.util.regex.Pattern;
  * ADS address witch is defined by {@code indexGroup/indexOffset}. These values can be either supplied as int or hex
  * representation.
  */
-public class AdsField implements PlcField {
+public class DirectAdsField implements AdsField {
 
-    private static final Pattern RESOURCE_ADDRESS_PATTERN = Pattern.compile("^((0[xX](?<indexGroupHex>[0-9a-fA-F]+))|(?<indexGroup>\\d+))/((0[xX](?<indexOffsetHex>[0-9a-fA-F]+))|(?<indexOffset>\\d+)):(?<adsDataType>.+)(\\[(?<numberOfElements>\\d)])?");
+    private static final Pattern RESOURCE_ADDRESS_PATTERN = Pattern.compile("^((0[xX](?<indexGroupHex>[0-9a-fA-F]+))|(?<indexGroup>\\d+))/((0[xX](?<indexOffsetHex>[0-9a-fA-F]+))|(?<indexOffset>\\d+)):(?<adsDataType>\\w+)(\\[(?<numberOfElements>\\d)])?");
 
     private final long indexGroup;
 
@@ -42,7 +41,7 @@ public class AdsField implements PlcField {
 
     private final int numberOfElements;
 
-    private AdsField(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
+    private DirectAdsField(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
         ByteValue.checkUnsignedBounds(indexGroup, 4);
         this.indexGroup = indexGroup;
         ByteValue.checkUnsignedBounds(indexOffset, 4);
@@ -54,11 +53,11 @@ public class AdsField implements PlcField {
         }
     }
 
-    public static AdsField of(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
-        return new AdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
+    public static DirectAdsField of(long indexGroup, long indexOffset, AdsDataType adsDataType, Integer numberOfElements) {
+        return new DirectAdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
     }
 
-    public static AdsField of(String address) throws PlcInvalidFieldException {
+    public static DirectAdsField of(String address) throws PlcInvalidFieldException {
         Matcher matcher = RESOURCE_ADDRESS_PATTERN.matcher(address);
         if (!matcher.matches()) {
             throw new PlcInvalidFieldException(address, RESOURCE_ADDRESS_PATTERN, "{indexGroup}/{indexOffset}:{adsDataType}([numberOfElements])?");
@@ -90,7 +89,7 @@ public class AdsField implements PlcField {
         String numberOfElementsString = matcher.group("numberOfElements");
         Integer numberOfElements = numberOfElementsString != null ? Integer.valueOf(numberOfElementsString) : null;
 
-        return new AdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
+        return new DirectAdsField(indexGroup, indexOffset, adsDataType, numberOfElements);
     }
 
     public static boolean matches(String address) {
@@ -118,10 +117,10 @@ public class AdsField implements PlcField {
         if (this == o) {
             return true;
         }
-        if (!(o instanceof AdsField)) {
+        if (!(o instanceof DirectAdsField)) {
             return false;
         }
-        AdsField that = (AdsField) o;
+        DirectAdsField that = (DirectAdsField) o;
         return indexGroup == that.indexGroup &&
             indexOffset == that.indexOffset;
     }
@@ -133,7 +132,7 @@ public class AdsField implements PlcField {
 
     @Override
     public String toString() {
-        return "AdsField{" +
+        return "DirectAdsField{" +
             "indexGroup=" + indexGroup +
             ", indexOffset=" + indexOffset +
             '}';
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
index b8fc06e..bd94d7b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/model/SymbolicAdsField.java
@@ -19,7 +19,6 @@
 package org.apache.plc4x.java.ads.model;
 
 import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
-import org.apache.plc4x.java.api.model.PlcField;
 
 import java.util.Objects;
 import java.util.regex.Matcher;
@@ -28,9 +27,9 @@ import java.util.regex.Pattern;
 /**
  * ADS address witch is defined by symbolic name (e.g. {@code Main.items[0]}).
  */
-public class SymbolicAdsField implements PlcField {
+public class SymbolicAdsField implements AdsField {
 
-    private static final Pattern SYMBOLIC_ADDRESS_PATTERN = Pattern.compile("^(?<symbolicAddress>.+):(?<adsDataType>.+)(\\[(?<numberOfElements>\\d)])?");
+    private static final Pattern SYMBOLIC_ADDRESS_PATTERN = Pattern.compile("^(?<symbolicAddress>.+):(?<adsDataType>\\w+)(\\[(?<numberOfElements>\\d)])?");
 
     private final String symbolicAddress;
 
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
index 5a85640..2366493 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java
@@ -28,7 +28,7 @@ import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
 import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 import org.apache.plc4x.java.ads.model.AdsDataType;
-import org.apache.plc4x.java.ads.model.AdsField;
+import org.apache.plc4x.java.ads.model.DirectAdsField;
 import org.apache.plc4x.java.ads.model.SymbolicAdsField;
 import org.apache.plc4x.java.ads.protocol.exception.AdsException;
 import org.apache.plc4x.java.api.exceptions.PlcException;
@@ -66,7 +66,7 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
 
     private final ConcurrentMap<Long, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse>> requests;
 
-    private final ConcurrentMap<SymbolicAdsField, AdsField> fieldMapping;
+    private final ConcurrentMap<SymbolicAdsField, DirectAdsField> fieldMapping;
 
     private List<Consumer<AdsDeviceNotificationRequest>> deviceNotificationListeners;
 
@@ -75,7 +75,7 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
     private final AmsNetId sourceAmsNetId;
     private final AmsPort sourceAmsPort;
 
-    public Plc4x2AdsProtocol(AmsNetId targetAmsNetId, AmsPort targetAmsPort, AmsNetId sourceAmsNetId, AmsPort sourceAmsPort, ConcurrentMap<SymbolicAdsField, AdsField> fieldMapping) {
+    public Plc4x2AdsProtocol(AmsNetId targetAmsNetId, AmsPort targetAmsPort, AmsNetId sourceAmsNetId, AmsPort sourceAmsPort, ConcurrentMap<SymbolicAdsField, DirectAdsField> fieldMapping) {
         this.targetAmsNetId = targetAmsNetId;
         this.targetAmsPort = targetAmsPort;
         this.sourceAmsNetId = sourceAmsNetId;
@@ -139,22 +139,22 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
         }
         PlcField field = writeRequest.getFields().get(0);
         if (field instanceof SymbolicAdsField) {
-            AdsField mappedField = fieldMapping.get(field);
+            DirectAdsField mappedField = fieldMapping.get(field);
             LOGGER.debug("Replacing {} with {}", field, mappedField);
             field = mappedField;
         }
-        if (!(field instanceof AdsField)) {
-            throw new PlcProtocolException("PlcField not of type AdsField: " + field.getClass());
+        if (!(field instanceof DirectAdsField)) {
+            throw new PlcProtocolException("PlcField not of type DirectAdsField: " + field.getClass());
         }
-        AdsField adsField = (AdsField) field;
+        DirectAdsField directAdsField = (DirectAdsField) field;
         Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
-        IndexGroup indexGroup = IndexGroup.of(adsField.getIndexGroup());
-        IndexOffset indexOffset = IndexOffset.of(adsField.getIndexOffset());
+        IndexGroup indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
+        IndexOffset indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
 
         FieldItem fieldItem = writeRequest.getFieldItems().get(0);
         Object[] values = fieldItem.getValues();
 
-        byte[] bytes = encodeData(adsField.getAdsDataType(), values);
+        byte[] bytes = encodeData(directAdsField.getAdsDataType(), values);
         Data data = Data.of(bytes);
         AmsPacket amsPacket = AdsWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
         LOGGER.debug("encoded write request {}", amsPacket);
@@ -170,23 +170,23 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
         }
         PlcField field = readRequest.getFields().get(0);
         if (field instanceof SymbolicAdsField) {
-            AdsField mappedField = fieldMapping.get(field);
+            DirectAdsField mappedField = fieldMapping.get(field);
             if (mappedField == null) {
                 throw new PlcProtocolException("No field mapping for " + field);
             }
             LOGGER.debug("Replacing {} with {}", field, mappedField);
             field = mappedField;
         }
-        if (!(field instanceof AdsField)) {
-            throw new PlcProtocolException("PlcField not of type AdsField: " + field.getClass());
+        if (!(field instanceof DirectAdsField)) {
+            throw new PlcProtocolException("PlcField not of type DirectAdsField: " + field.getClass());
         }
-        AdsField adsField = (AdsField) field;
+        DirectAdsField directAdsField = (DirectAdsField) field;
         Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
-        IndexGroup indexGroup = IndexGroup.of(adsField.getIndexGroup());
-        IndexOffset indexOffset = IndexOffset.of(adsField.getIndexOffset());
-        AdsDataType adsDataType = adsField.getAdsDataType();
-        int numberOfElements = adsField.getNumberOfElements();
-        int readLength = adsDataType.getTagetByteSize() * numberOfElements;
+        IndexGroup indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
+        IndexOffset indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
+        AdsDataType adsDataType = directAdsField.getAdsDataType();
+        int numberOfElements = directAdsField.getNumberOfElements();
+        int readLength = adsDataType.getTargetByteSize() * numberOfElements;
         Length length = Length.of(readLength);
         AmsPacket amsPacket = AdsReadRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length);
         LOGGER.debug("encoded read request {}", amsPacket);
@@ -282,11 +282,11 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
     }
 
     @SuppressWarnings("unchecked")
-    private InternalPlcResponse decodeReadResponse(AdsReadResponse responseMessage, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> requestContainer) throws PlcProtocolException {
+    private InternalPlcResponse decodeReadResponse(AdsReadResponse responseMessage, PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> requestContainer) {
         InternalPlcReadRequest plcReadRequest = (InternalPlcReadRequest) requestContainer.getRequest();
 
         // TODO: only single requests supported for now
-        AdsField field = (AdsField) plcReadRequest.getFields().get(0);
+        DirectAdsField field = (DirectAdsField) plcReadRequest.getFields().get(0);
 
 
         PlcResponseCode responseCode = decodeResponseCode(responseMessage.getResult());
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ManualPlc4XAdsTest.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ManualPlc4XAdsTest.java
index 286c78f..b4da510 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ManualPlc4XAdsTest.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ManualPlc4XAdsTest.java
@@ -58,7 +58,7 @@ public class ManualPlc4XAdsTest {
             CompletableFuture<PlcSubscriptionResponse> subscribeResponse = plcSubscriber.subscribe(builder -> builder.addChangeOfStateField("stationChange", "Allgemein_S2.Station:BYTE"));
             PlcSubscriptionResponse plcSubscriptionResponse = subscribeResponse.get();
 
-            PlcConsumerRegistration plcConsumerRegistration = plcSubscriber.register(plcSubscriptionEvent -> System.out.println(plcSubscriptionEvent), plcSubscriptionResponse.getSubscriptionHandles());
+            PlcConsumerRegistration plcConsumerRegistration = plcSubscriber.register(System.out::println, plcSubscriptionResponse.getSubscriptionHandles());
 
             TimeUnit.SECONDS.sleep(5);
 
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnectionTest.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnectionTest.java
index da02be6..bf61a59 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnectionTest.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnectionTest.java
@@ -29,12 +29,15 @@ import org.apache.plc4x.java.ads.api.commands.types.Data;
 import org.apache.plc4x.java.ads.api.commands.types.Result;
 import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
-import org.apache.plc4x.java.ads.model.AdsField;
+import org.apache.plc4x.java.ads.model.DirectAdsField;
 import org.apache.plc4x.java.ads.model.SymbolicAdsField;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.messages.PlcFieldRequest;
+import org.apache.plc4x.java.api.messages.PlcProprietaryResponse;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.base.connection.ChannelFactory;
-import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.base.messages.*;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -119,26 +122,26 @@ public class AdsAbstractPlcConnectionTest {
 
     @Test
     public void read() {
-        CompletableFuture<PlcReadResponse<?>> read = SUT.read(mock(PlcReadRequest.class));
+        CompletableFuture<PlcReadResponse<?>> read = SUT.read(mock(InternalPlcReadRequest.class));
         assertNotNull(read);
 
-        simulatePipelineError(() -> SUT.read(mock(PlcReadRequest.class)));
+        simulatePipelineError(() -> SUT.read(mock(InternalPlcReadRequest.class)));
     }
 
     @Test
     public void write() {
-        CompletableFuture<PlcWriteResponse<?>> write = SUT.write(mock(PlcWriteRequest.class));
+        CompletableFuture<PlcWriteResponse<?>> write = SUT.write(mock(InternalPlcWriteRequest.class));
         assertNotNull(write);
 
-        simulatePipelineError(() -> SUT.write(mock(PlcWriteRequest.class)));
+        simulatePipelineError(() -> SUT.write(mock(InternalPlcWriteRequest.class)));
     }
 
     @Test
     public void send() {
-        CompletableFuture send = SUT.send(mock(PlcProprietaryRequest.class));
+        CompletableFuture send = SUT.send(mock(InternalPlcProprietaryRequest.class));
         assertNotNull(send);
 
-        simulatePipelineError(() -> SUT.send(mock(PlcProprietaryRequest.class)));
+        simulatePipelineError(() -> SUT.send(mock(InternalPlcProprietaryRequest.class)));
     }
 
     public void simulatePipelineError(FutureProducingTestRunnable futureProducingTestRunnable) {
@@ -178,7 +181,7 @@ public class AdsAbstractPlcConnectionTest {
         {
             when(channel.writeAndFlush(any(PlcRequestContainer.class))).then(invocation -> {
                 PlcRequestContainer plcRequestContainer = invocation.getArgument(0);
-                PlcProprietaryResponse plcProprietaryResponse = mock(PlcProprietaryResponse.class, RETURNS_DEEP_STUBS);
+                PlcProprietaryResponse plcProprietaryResponse = mock(InternalPlcProprietaryResponse.class, RETURNS_DEEP_STUBS);
                 AdsReadWriteResponse adsReadWriteResponse = mock(AdsReadWriteResponse.class, RETURNS_DEEP_STUBS);
                 when(adsReadWriteResponse.getResult()).thenReturn(Result.of(0));
                 when(adsReadWriteResponse.getData()).thenReturn(Data.of(new byte[]{1, 2, 3, 4}));
@@ -187,8 +190,8 @@ public class AdsAbstractPlcConnectionTest {
                 return mock(ChannelFuture.class);
             });
 
-            SUT.mapFields(SymbolicAdsField.of("Main.byByte[0]"));
-            SUT.mapFields(SymbolicAdsField.of("Main.byByte[0]"));
+            SUT.mapFields(SymbolicAdsField.of("Main.byByte[0]:BYTE"));
+            SUT.mapFields(SymbolicAdsField.of("Main.byByte[0]:BYTE"));
             verify(channel, times(1)).writeAndFlush(any(PlcRequestContainer.class));
             SUT.clearMapping();
             reset(channel);
@@ -197,7 +200,7 @@ public class AdsAbstractPlcConnectionTest {
         {
             when(channel.writeAndFlush(any(PlcRequestContainer.class))).then(invocation -> {
                 PlcRequestContainer plcRequestContainer = invocation.getArgument(0);
-                PlcProprietaryResponse plcProprietaryResponse = mock(PlcProprietaryResponse.class, RETURNS_DEEP_STUBS);
+                PlcProprietaryResponse plcProprietaryResponse = mock(InternalPlcProprietaryResponse.class, RETURNS_DEEP_STUBS);
                 AdsReadWriteResponse adsReadWriteResponse = mock(AdsReadWriteResponse.class, RETURNS_DEEP_STUBS);
                 when(adsReadWriteResponse.getResult()).thenReturn(Result.of(1));
                 when(plcProprietaryResponse.getResponse()).thenReturn(adsReadWriteResponse);
@@ -227,7 +230,7 @@ public class AdsAbstractPlcConnectionTest {
     @Test
     public void close() throws Exception {
         Map fieldMapping = (Map) FieldUtils.getDeclaredField(AdsAbstractPlcConnection.class, "fieldMapping", true).get(SUT);
-        fieldMapping.put(mock(SymbolicAdsField.class), mock(AdsField.class));
+        fieldMapping.put(mock(SymbolicAdsField.class), mock(DirectAdsField.class));
         SUT.close();
     }
 
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/AdsFieldTest.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/DirectAdsFieldTest.java
similarity index 73%
rename from plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/AdsFieldTest.java
rename to plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/DirectAdsFieldTest.java
index 542efa8..dc781d4 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/AdsFieldTest.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/model/DirectAdsFieldTest.java
@@ -24,40 +24,44 @@ import org.junit.Test;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
-public class AdsFieldTest {
+public class DirectAdsFieldTest {
 
     @Test
     public void of() {
-        AdsField field = AdsField.of("1/10");
+        DirectAdsField field = DirectAdsField.of("1/10:BYTE[2]");
         assertThat(field.getIndexGroup(), is(1L));
         assertThat(field.getIndexOffset(), is(10L));
+        assertThat(field.getAdsDataType(), is(AdsDataType.BYTE));
+        assertThat(field.getNumberOfElements(), is(2));
     }
 
     @Test
     public void ofHex() {
-        AdsField field = AdsField.of("0x1/0xff");
+        DirectAdsField field = DirectAdsField.of("0x1/0xff:BYTE[2]");
         assertThat(field.getIndexGroup(), is(1L));
         assertThat(field.getIndexOffset(), is(255L));
+        assertThat(field.getAdsDataType(), is(AdsDataType.BYTE));
+        assertThat(field.getNumberOfElements(), is(2));
     }
 
     @Test(expected = PlcInvalidFieldException.class)
     public void stringInField() {
-        AdsField field = AdsField.of("group/offset");
+        DirectAdsField field = DirectAdsField.of("group/offset");
     }
 
     @Test(expected = PlcInvalidFieldException.class)
     public void singleNumberField() {
-        AdsField field = AdsField.of("10");
+        DirectAdsField field = DirectAdsField.of("10");
     }
 
     @Test(expected = PlcInvalidFieldException.class)
     public void wrongSeperator() {
-        AdsField field = AdsField.of("1:10");
+        DirectAdsField field = DirectAdsField.of("1:10");
     }
 
     @Test
     public void getGroupAndOffset() {
-        AdsField field = AdsField.of(2L, 20L, AdsDataType.BYTE, 1);
+        DirectAdsField field = DirectAdsField.of(2L, 20L, AdsDataType.BYTE, 1);
         assertThat(field.getIndexGroup(), is(2L));
         assertThat(field.getIndexOffset(), is(20L));
         assertThat(field.getAdsDataType(), is(AdsDataType.BYTE));
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocolTest.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocolTest.java
index d5b6b5a..a97be10 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocolTest.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocolTest.java
@@ -31,8 +31,10 @@ import org.apache.plc4x.java.ads.api.generic.AmsPacket;
 import org.apache.plc4x.java.ads.api.generic.types.AmsNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AmsPort;
 import org.apache.plc4x.java.ads.api.generic.types.Invoke;
+import org.apache.plc4x.java.ads.model.AdsDataType;
 import org.apache.plc4x.java.ads.model.AdsPlcFieldHandler;
 import org.apache.plc4x.java.base.messages.*;
+import org.apache.plc4x.java.base.protocol.Plc4XSupportedDataTypes;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -44,10 +46,8 @@ import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.GregorianCalendar;
-import java.util.List;
+import java.math.BigInteger;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
@@ -98,18 +98,23 @@ public class Plc4x2AdsProtocolTest {
         AmsPort sourceAmsPort = AmsPort.of(14);
         Invoke invokeId = Invoke.of(2);
         return streamOfLittleEndianDataTypePairs()
+            // TODO: calender doesnt work anymore so we might need to adjust the generator above.
+            .filter(o -> o.getDataTypeClass() != GregorianCalendar.class)
+            .filter(o -> o.getDataTypeClass() != Byte[].class)
+            .filter(o -> o.getDataTypeClass() != byte[].class)
+            .map(Plc4x2AdsProtocolTest::mapToAdsDataType)
             .map(pair -> Stream.of(
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
                         (InternalPlcRequest) new DefaultPlcWriteRequest.Builder(new AdsPlcFieldHandler())
-                            .addItem(RandomStringUtils.randomAscii(10), "1/1:BYTE:1", pair.getValue())
+                            .addItem(RandomStringUtils.randomAscii(10), "1/1:" + pair.adsDataType, pair.getValue())
                             .build(), new CompletableFuture<>()),
                     AdsWriteResponse.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, Result.of(0))
                 ),
                 ImmutablePair.of(
                     new PlcRequestContainer<>(
                         (InternalPlcRequest) new DefaultPlcReadRequest.Builder(new AdsPlcFieldHandler())
-                            .addItem(RandomStringUtils.randomAscii(10), "1/1:BYTE:1")
+                            .addItem(RandomStringUtils.randomAscii(10), "1/1:" + pair.adsDataType)
                             .build(), new CompletableFuture<>()),
                     AdsReadResponse.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, Result.of(0), Data.of(pair.getByteRepresentation()))
                 )
@@ -119,6 +124,37 @@ public class Plc4x2AdsProtocolTest {
             .map(pair -> new Object[]{Object.class.getSimpleName(), pair.left, pair.left.getResponseFuture(), pair.left.getRequest().getClass().getSimpleName(), pair.right, pair.right.getClass().getSimpleName()}).collect(Collectors.toList());
     }
 
+    private static AdsDataTypePair mapToAdsDataType(Plc4XSupportedDataTypes.DataTypePair dataTypePair) {
+        // TODO: check usefull type mapping
+        Map<Class<?>, AdsDataType> dataTypeMap = new HashMap<>();
+        dataTypeMap.put(Boolean.class, AdsDataType.BOOL);
+        dataTypeMap.put(Byte.class, AdsDataType.BYTE);
+        dataTypeMap.put(Short.class, AdsDataType.INT);
+        dataTypeMap.put(Float.class, AdsDataType.REAL);
+        dataTypeMap.put(Integer.class, AdsDataType.INT32);
+        dataTypeMap.put(Double.class, AdsDataType.LREAL);
+        dataTypeMap.put(BigInteger.class, AdsDataType.INT64);
+        dataTypeMap.put(Calendar.class, AdsDataType.DATE_AND_TIME);
+        dataTypeMap.put(String.class, AdsDataType.STRING);
+        dataTypeMap.put(byte[].class, AdsDataType.BYTE);
+        dataTypeMap.put(Byte[].class, AdsDataType.BYTE);
+        return new AdsDataTypePair(dataTypePair, dataTypeMap.getOrDefault(dataTypePair.getDataTypeClass(), AdsDataType.BYTE));
+    }
+
+    private static class AdsDataTypePair extends Plc4XSupportedDataTypes.DataTypePair {
+
+        private final AdsDataType adsDataType;
+
+        private AdsDataTypePair(Plc4XSupportedDataTypes.DataTypePair dataTypePair, AdsDataType adsDataType) {
+            super(dataTypePair.getDataTypePair());
+            this.adsDataType = adsDataType;
+        }
+
+        private AdsDataType getAdsDataType() {
+            return adsDataType;
+        }
+    }
+
     @Before
     public void setUp() {
         AmsNetId targetAmsNetId = AmsNetId.of("1.2.3.4.5.6");