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

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

commit 19716f8d5847c3f65ed618023971cab76ded0bf7
Author: Sebastian Rühl <sru...@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");

Reply via email to