You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/08/01 16:00:33 UTC

[plc4x] 03/03: - Continued working on the AMS/ADS Driver - Added test-cases for the different types of requests - Started implementing the read-logic for single and multiple reads

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

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

commit a7b7b8455d1ce07fdf04f8fbc049232f5694d5c0
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Aug 1 18:00:13 2020 +0200

    - Continued working on the AMS/ADS Driver
    - Added test-cases for the different types of requests
    - Started implementing the read-logic for single and multiple reads
---
 .../apache/plc4x/java/amsads/AMSADSPlcDriver.java  |  17 -
 .../connection/AdsAbstractPlcConnection.java       |   6 +-
 .../connection/AdsConnectionFactory.java           |   2 +-
 .../connection/AdsSerialPlcConnection.java         |   2 +-
 .../connection/AdsTcpPlcConnection.java            |   4 +-
 .../{ => attic}/protocol/Ads2PayloadProtocol.java  |   4 +-
 .../protocol/Payload2SerialProtocol.java           |   6 +-
 .../{ => attic}/protocol/Payload2TcpProtocol.java  |   9 +-
 .../{ => attic}/protocol/Plc4x2AdsProtocol.java    |  17 +-
 .../amsads/configuration/AdsConfiguration.java     |  44 ++-
 .../java/amsads/protocol/AdsProtocolLogic.java     | 214 ++++++++++-
 .../plc4x/java/amsads/AMSADSPlcDriverTest.java     |  42 ---
 .../amsads/AmsAdsSerializerParserTest.java         |   6 +-
 .../protocol/amsads/BenchmarkGeneratedDf1.java     |  76 ----
 .../plc4x/protocol/amsads/BenchmarkManualDf1.java  | 239 ------------
 .../apache/plc4x/protocol/amsads/EndToEndTest.java |  57 ---
 .../org/apache/plc4x/protocol/amsads/IOTest.java   |  91 -----
 .../testsuite/AdsParserSerializerTest.xml          | 414 +++++++++++++++++++++
 .../src/test/resources/testsuite/Df1Testsuite.xml  | 101 -----
 19 files changed, 698 insertions(+), 653 deletions(-)

diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java
index 4cb876c..4961373 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/AMSADSPlcDriver.java
@@ -18,11 +18,9 @@
  */
 package org.apache.plc4x.java.amsads;
 
-import org.apache.commons.lang3.ArrayUtils;
 import org.apache.plc4x.java.amsads.configuration.AdsConfiguration;
 import org.apache.plc4x.java.amsads.field.AdsFieldHandler;
 import org.apache.plc4x.java.amsads.protocol.AdsProtocolLogic;
-import org.apache.plc4x.java.amsads.readwrite.AmsNetId;
 import org.apache.plc4x.java.amsads.readwrite.AmsPacket;
 import org.apache.plc4x.java.amsads.readwrite.io.AmsPacketIO;
 import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -30,9 +28,6 @@ import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
 /**
  * Implementation of the ADS protocol, based on:
  * - ADS Protocol
@@ -43,9 +38,6 @@ public class AMSADSPlcDriver extends GeneratedDriverBase<AmsPacket> {
 
     public static final int TCP_PORT = 48898;
 
-    public static final Pattern AMS_NET_ID_PATTERN =
-        Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
-
     @Override
     public String getProtocolCode() {
         return "ads";
@@ -78,13 +70,4 @@ public class AMSADSPlcDriver extends GeneratedDriverBase<AmsPacket> {
             .build();
     }
 
-    public static AmsNetId AmsNetIdOf(String address) {
-        if (!AMS_NET_ID_PATTERN.matcher(address).matches()) {
-            throw new IllegalArgumentException(address + " must match " + AMS_NET_ID_PATTERN);
-        }
-        String[] split = address.split("\\.");
-        short[] shorts = ArrayUtils.toPrimitive(Stream.of(split).map(Integer::parseInt).map(Integer::shortValue).toArray(Short[]::new));
-        return new AmsNetId(shorts[5], shorts[4], shorts[3], shorts[2], shorts[1], shorts[0]);
-    }
-
 }
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsAbstractPlcConnection.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsAbstractPlcConnection.java
similarity index 98%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsAbstractPlcConnection.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsAbstractPlcConnection.java
index 95e9294..38ff2c6 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsAbstractPlcConnection.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsAbstractPlcConnection.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.connection;
+package org.apache.plc4x.java.amsads.attic.connection;
 
 import io.netty.channel.ChannelFuture;
 import org.apache.commons.configuration2.Configuration;
@@ -147,7 +147,8 @@ public abstract class AdsAbstractPlcConnection extends DefaultNettyPlcConnection
                 0xF003L,
                 0L,
                 4L,
-                symbolicAdsFieldInternal.getSymbolicField().getBytes().length,
+                // TODO: Implement the items ...
+                null,
                 symbolicAdsFieldInternal.getSymbolicField().getBytes()
             );
 
@@ -189,7 +190,6 @@ public abstract class AdsAbstractPlcConnection extends DefaultNettyPlcConnection
                 return new AdsWriteRequest(
                     0xF006L,
                     0L,
-                    bytes.length,
                     bytes
                 );
             })
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsConnectionFactory.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsConnectionFactory.java
similarity index 97%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsConnectionFactory.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsConnectionFactory.java
index aa44d35..36754c8 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsConnectionFactory.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsConnectionFactory.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.connection;
+package org.apache.plc4x.java.amsads.attic.connection;
 
 import org.apache.plc4x.java.amsads.readwrite.AmsNetId;
 
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsSerialPlcConnection.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsSerialPlcConnection.java
similarity index 98%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsSerialPlcConnection.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsSerialPlcConnection.java
index 72816b0..b29df2a 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsSerialPlcConnection.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsSerialPlcConnection.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.connection;
+package org.apache.plc4x.java.amsads.attic.connection;
 
 import org.apache.plc4x.java.amsads.readwrite.AmsNetId;
 import org.apache.plc4x.java.transport.serial.SerialChannelFactory;
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsTcpPlcConnection.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsTcpPlcConnection.java
similarity index 99%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsTcpPlcConnection.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsTcpPlcConnection.java
index a148e2e..b69eb94 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/connection/AdsTcpPlcConnection.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/connection/AdsTcpPlcConnection.java
@@ -16,14 +16,14 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.connection;
+package org.apache.plc4x.java.amsads.attic.connection;
 
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.plc4x.java.amsads.field.AdsFieldHandler;
 import org.apache.plc4x.java.amsads.field.DirectAdsField;
 import org.apache.plc4x.java.amsads.field.SymbolicAdsField;
 import org.apache.plc4x.java.amsads.model.*;
-import org.apache.plc4x.java.amsads.protocol.Plc4x2AdsProtocol;
+import org.apache.plc4x.java.amsads.attic.protocol.Plc4x2AdsProtocol;
 import org.apache.plc4x.java.amsads.protocol.util.LittleEndianDecoder;
 import org.apache.plc4x.java.amsads.readwrite.*;
 import org.apache.plc4x.java.amsads.types.AdsDataType;
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Ads2PayloadProtocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Ads2PayloadProtocol.java
similarity index 96%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Ads2PayloadProtocol.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Ads2PayloadProtocol.java
index 535e308..a20ff7c 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Ads2PayloadProtocol.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Ads2PayloadProtocol.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.protocol;
+package org.apache.plc4x.java.amsads.attic.protocol;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -56,7 +56,7 @@ public class Ads2PayloadProtocol extends MessageToMessageCodec<ByteBuf, AmsPacke
     @Override
     protected void encode(ChannelHandlerContext channelHandlerContext, AmsPacket amsPacket, List<Object> out) throws AdsException {
         LOGGER.trace("(<--OUT): {}, {}, {}", channelHandlerContext, amsPacket, out);
-        Long invokeId = amsPacket.getAmsHeader().getInvokeId();
+        Long invokeId = amsPacket.getInvokeId();
         if (invokeId != 0L) {
             requests.put(invokeId, amsPacket);
         }
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2SerialProtocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2SerialProtocol.java
similarity index 95%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2SerialProtocol.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2SerialProtocol.java
index 11a355b..4092bbf 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2SerialProtocol.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2SerialProtocol.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.protocol;
+package org.apache.plc4x.java.amsads.attic.protocol;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -78,7 +78,7 @@ public class Payload2SerialProtocol extends MessageToMessageCodec<ByteBuf, ByteB
         try {
             AmsSerialFrameIO.staticSerialize(writeBuffer, amsSerialFrame);
         } catch (ParseException e) {
-            throw new AdsException(amsPacketSer.getAmsHeader().getInvokeId(), e);
+            throw new AdsException(amsPacketSer.getInvokeId(), e);
         }
         out.add(writeBuffer.getData());
     }
@@ -103,7 +103,7 @@ public class Payload2SerialProtocol extends MessageToMessageCodec<ByteBuf, ByteB
                 try {
                     AmsPacketIO.staticSerialize(writeBuffer, amsPacket);
                 } catch (ParseException e) {
-                    throw new AdsException(amsPacket.getAmsHeader().getInvokeId(), e);
+                    throw new AdsException(amsPacket.getInvokeId(), e);
                 }
                 out.add(writeBuffer.getData());
             } catch (Exception e) {
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2TcpProtocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2TcpProtocol.java
similarity index 91%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2TcpProtocol.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2TcpProtocol.java
index 775c506..e719bf0 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Payload2TcpProtocol.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Payload2TcpProtocol.java
@@ -16,7 +16,7 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.protocol;
+package org.apache.plc4x.java.amsads.attic.protocol;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
@@ -25,7 +25,6 @@ import io.netty.handler.codec.MessageToMessageCodec;
 import org.apache.plc4x.java.amsads.protocol.exception.AdsException;
 import org.apache.plc4x.java.amsads.readwrite.AmsPacket;
 import org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket;
-import org.apache.plc4x.java.amsads.readwrite.AmsTcpHeader;
 import org.apache.plc4x.java.amsads.readwrite.io.AmsPacketIO;
 import org.apache.plc4x.java.amsads.readwrite.io.AmsTCPPacketIO;
 import org.apache.plc4x.java.spi.generation.ParseException;
@@ -55,9 +54,9 @@ public class Payload2TcpProtocol extends MessageToMessageCodec<ByteBuf, ByteBuf>
 
         WriteBuffer writeBuffer = new WriteBuffer(amsPacketSer.getLengthInBytes(), true);
         try {
-            AmsTCPPacketIO.staticSerialize(writeBuffer, new AmsTCPPacket(new AmsTcpHeader(amsPacketSer.getLengthInBytes()), amsPacketSer));
+            AmsTCPPacketIO.staticSerialize(writeBuffer, new AmsTCPPacket(amsPacketSer));
         } catch (ParseException e) {
-            throw new AdsException(amsPacketSer.getAmsHeader().getInvokeId(), e);
+            throw new AdsException(amsPacketSer.getInvokeId(), e);
         }
         out.add(writeBuffer.getData());
     }
@@ -82,7 +81,7 @@ public class Payload2TcpProtocol extends MessageToMessageCodec<ByteBuf, ByteBuf>
                 try {
                     AmsPacketIO.staticSerialize(writeBuffer, amsPacket);
                 } catch (ParseException e) {
-                    throw new AdsException(amsPacket.getAmsHeader().getInvokeId(), e);
+                    throw new AdsException(amsPacket.getInvokeId(), e);
                 }
                 out.add(writeBuffer.getData());
             } catch (Exception e) {
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4x2AdsProtocol.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Plc4x2AdsProtocol.java
similarity index 94%
rename from sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4x2AdsProtocol.java
rename to sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Plc4x2AdsProtocol.java
index 2919524..3d12b7a 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/Plc4x2AdsProtocol.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/attic/protocol/Plc4x2AdsProtocol.java
@@ -16,11 +16,10 @@
  specific language governing permissions and limitations
  under the License.
  */
-package org.apache.plc4x.java.amsads.protocol;
+package org.apache.plc4x.java.amsads.attic.protocol;
 
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageCodec;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.plc4x.java.amsads.types.AdsDataType;
 import org.apache.plc4x.java.amsads.field.AdsField;
 import org.apache.plc4x.java.amsads.field.DirectAdsField;
@@ -168,8 +167,8 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
             LOGGER.debug("Requested AdsDatatype {} is exceeded by number of bytes {}. Limit {}.", directAdsField.getAdsDataType(), bytesToBeWritten, maxTheoreticalSize);
             throw new PlcProtocolPayloadTooBigException("ADS", maxTheoreticalSize, bytesToBeWritten, plcValues);
         }
-        AdsWriteRequest data = new AdsWriteRequest(indexGroup, indexOffset, bytes.length, bytes);
-        AmsPacket amsPacket = new AmsPacket(new AmsHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, CommandId.ADS_WRITE, new State(false, false, false, false, false, false, true, false, false), data.getLength(), 0, invokeId), data);
+        AdsWriteRequest data = new AdsWriteRequest(indexGroup, indexOffset, bytes);
+        AmsPacket amsPacket = new AmsPacket(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, CommandId.ADS_WRITE, new State(false, false, false, false, false, false, true, false, false), 0, invokeId, data);
         LOGGER.debug("encoded write request {}", amsPacket);
         out.add(amsPacket);
         requests.put(invokeId, msg);
@@ -200,8 +199,8 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
         AdsDataType adsDataType = directAdsField.getAdsDataType();
         int numberOfElements = directAdsField.getNumberOfElements();
         int readLength = adsDataType.getTargetByteSize() * numberOfElements;
-        AdsReadRequest data = new AdsReadRequest(indexGroup, indexOffset, readLength);
-        AmsPacket amsPacket = new AmsPacket(new AmsHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, CommandId.ADS_READ, new State(false, false, false, false, false, false, true, false, false), data.getLength(), 0, invokeId), data);
+        AdsReadWriteRequest data = new AdsReadWriteRequest(indexGroup, indexOffset, readLength, new AdsReadRequest[0], new byte[0]);
+        AmsPacket amsPacket = new AmsPacket(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, CommandId.ADS_READ, new State(false, false, false, false, false, false, true, false, false), 0, invokeId, data);
         LOGGER.debug("encoded read request {}", amsPacket);
         out.add(amsPacket);
         requests.put(invokeId, msg);
@@ -215,19 +214,19 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque
         AmsPacket amsPacket = (AmsPacket) plcProprietaryRequest.getProprietaryRequest();
         LOGGER.debug("encoded proprietary request {}", amsPacket);
         out.add(amsPacket);
-        requests.put(amsPacket.getAmsHeader().getInvokeId(), msg);
+        requests.put(amsPacket.getInvokeId(), msg);
     }
 
     @Override
     protected void decode(ChannelHandlerContext channelHandlerContext, AmsPacket amsPacket, List<Object> out) throws Exception {
         LOGGER.trace("(-->IN): {}, {}, {}", channelHandlerContext, amsPacket, out);
-        ADSData data = amsPacket.getData();
+        AdsData data = amsPacket.getData();
         if (data instanceof AdsDeviceNotificationRequest) {
             LOGGER.debug("Received notification {}", amsPacket);
             handleAdsDeviceNotificationRequest((AdsDeviceNotificationRequest) data);
             return;
         }
-        PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> plcRequestContainer = requests.remove(amsPacket.getAmsHeader().getInvokeId());
+        PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> plcRequestContainer = requests.remove(amsPacket.getInvokeId());
         if (plcRequestContainer == null) {
             LOGGER.info("Unmapped packet received {}", amsPacket);
             return;
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/configuration/AdsConfiguration.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/configuration/AdsConfiguration.java
index 2f21d3e..8919d38 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/configuration/AdsConfiguration.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/configuration/AdsConfiguration.java
@@ -18,6 +18,7 @@ under the License.
 */
 package org.apache.plc4x.java.amsads.configuration;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.plc4x.java.amsads.AMSADSPlcDriver;
 import org.apache.plc4x.java.amsads.readwrite.AmsNetId;
 import org.apache.plc4x.java.spi.configuration.Configuration;
@@ -25,11 +26,18 @@ import org.apache.plc4x.java.spi.configuration.ConfigurationParameterConverter;
 import org.apache.plc4x.java.spi.configuration.annotations.ConfigurationParameter;
 import org.apache.plc4x.java.spi.configuration.annotations.ParameterConverter;
 import org.apache.plc4x.java.spi.configuration.annotations.Required;
+import org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultValue;
 import org.apache.plc4x.java.transport.serial.SerialTransportConfiguration;
 import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
 
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
 public class AdsConfiguration implements Configuration, TcpTransportConfiguration, SerialTransportConfiguration {
 
+    public static final Pattern AMS_NET_ID_PATTERN =
+        Pattern.compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
+
     @Required
     @ConfigurationParameter
     @ParameterConverter(AmsNetIdConverter.class)
@@ -48,6 +56,14 @@ public class AdsConfiguration implements Configuration, TcpTransportConfiguratio
     @ConfigurationParameter
     protected int sourceAmsPort;
 
+    @ConfigurationParameter("timeout-symbolic-address-resolution")
+    @IntDefaultValue(1000)
+    protected int timeoutSymbolicAddressResolution;
+
+    @ConfigurationParameter("timeout-request")
+    @IntDefaultValue(2000)
+    protected int timeoutRequest;
+
     public AmsNetId getTargetAmsNetId() {
         return targetAmsNetId;
     }
@@ -80,6 +96,22 @@ public class AdsConfiguration implements Configuration, TcpTransportConfiguratio
         this.sourceAmsPort = sourceAmsPort;
     }
 
+    public int getTimeoutSymbolicAddressResolution() {
+        return timeoutSymbolicAddressResolution;
+    }
+
+    public void setTimeoutSymbolicAddressResolution(int timeoutSymbolicAddressResolution) {
+        this.timeoutSymbolicAddressResolution = timeoutSymbolicAddressResolution;
+    }
+
+    public int getTimeoutRequest() {
+        return timeoutRequest;
+    }
+
+    public void setTimeoutRequest(int timeoutRequest) {
+        this.timeoutRequest = timeoutRequest;
+    }
+
     @Override
     public int getDefaultPort() {
         return AMSADSPlcDriver.TCP_PORT;
@@ -99,7 +131,17 @@ public class AdsConfiguration implements Configuration, TcpTransportConfiguratio
 
         @Override
         public AmsNetId convert(String value) {
-            return AMSADSPlcDriver.AmsNetIdOf(value);
+            return amsNetIdOf(value);
         }
     }
+
+    public static AmsNetId amsNetIdOf(String address) {
+        if (!AMS_NET_ID_PATTERN.matcher(address).matches()) {
+            throw new IllegalArgumentException(address + " must match " + AMS_NET_ID_PATTERN);
+        }
+        String[] split = address.split("\\.");
+        short[] shorts = ArrayUtils.toPrimitive(Stream.of(split).map(Integer::parseInt).map(Integer::shortValue).toArray(Short[]::new));
+        return new AmsNetId(shorts[5], shorts[4], shorts[3], shorts[2], shorts[1], shorts[0]);
+    }
+
 }
diff --git a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AdsProtocolLogic.java b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AdsProtocolLogic.java
index be5dc78..8ecba8f 100644
--- a/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AdsProtocolLogic.java
+++ b/sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/protocol/AdsProtocolLogic.java
@@ -19,14 +19,54 @@ under the License.
 package org.apache.plc4x.java.amsads.protocol;
 
 import org.apache.plc4x.java.amsads.configuration.AdsConfiguration;
-import org.apache.plc4x.java.amsads.readwrite.AmsPacket;
+import org.apache.plc4x.java.amsads.field.DirectAdsField;
+import org.apache.plc4x.java.amsads.field.SymbolicAdsField;
+import org.apache.plc4x.java.amsads.readwrite.*;
+import org.apache.plc4x.java.amsads.readwrite.types.CommandId;
+import org.apache.plc4x.java.amsads.readwrite.types.ReservedIndexGroups;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.spi.ConversationContext;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.transaction.RequestTransactionManager;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
 
 public class AdsProtocolLogic extends Plc4xProtocolBase<AmsPacket> implements HasConfiguration<AdsConfiguration> {
 
     private AdsConfiguration configuration;
+    public static final State DEFAULT_COMMAND_STATE = new State(
+        false, false, false, false, false, false, true, false, false);
+
+    private ConversationContext<AmsPacket> adsDriverContext;
+    private static final AtomicLong invokeIdGenerator = new AtomicLong(0);
+    private RequestTransactionManager tm;
+
+    private ConcurrentHashMap<SymbolicAdsField, DirectAdsField> symbolicFieldMapping;
+    private ConcurrentHashMap<SymbolicAdsField, CompletableFuture<DirectAdsField>> pendingResolutionRequests;
+
+    public AdsProtocolLogic() {
+        symbolicFieldMapping = new ConcurrentHashMap<>();
+        pendingResolutionRequests = new ConcurrentHashMap<>();
+
+        // Initialize Transaction Manager.
+        // Until the number of concurrent requests is successfully negotiated we set it to a
+        // maximum of only one request being able to be sent at a time. During the login process
+        // No concurrent requests can be sent anyway. It will be updated when receiving the
+        // S7ParameterSetupCommunication response.
+        this.tm = new RequestTransactionManager(1);
+    }
 
     @Override
     public void setConfiguration(AdsConfiguration configuration) {
@@ -34,8 +74,180 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsPacket> implements Ha
     }
 
     @Override
+    public void setContext(ConversationContext<AmsPacket> context) {
+        super.setContext(context);
+        adsDriverContext = context;
+    }
+
+    @Override
     public void close(ConversationContext<AmsPacket> context) {
 
     }
 
+    @Override
+    public void onConnect(ConversationContext<AmsPacket> context) {
+        // AMS/ADS doesn't know a concept of a connect.
+        context.fireConnected();
+    }
+
+    @Override
+    public void onDisconnect(ConversationContext<AmsPacket> context) {
+        super.onDisconnect(context);
+        // TODO: Here we have to clean up all of the handles this connection acquired.
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
+
+        // Get all ADS addresses in their resolved state.
+        final List<DirectAdsField> directAdsFields = getDirectAddresses(readRequest.getFields());
+
+        // Depending on the number of fields, use a single item request or a sum-request
+        if(directAdsFields.size() == 1) {
+            // Do a normal (single item) ADS Read Request
+            return singleRead(readRequest, directAdsFields.get(0));
+        } else {
+            // Do a ADS-Sum Read Request.
+            return multiRead(readRequest, directAdsFields);
+        }
+    }
+
+    protected CompletableFuture<PlcReadResponse> singleRead(PlcReadRequest readRequest, DirectAdsField directAdsField) {
+        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+
+        int size = directAdsField.getAdsDataType().getTargetByteSize() * directAdsField.getNumberOfElements();
+        AdsData adsData = new AdsReadRequest(directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), size);
+        AmsPacket amsPacket = new AmsPacket(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
+            configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
+            CommandId.ADS_READ, DEFAULT_COMMAND_STATE, 0, invokeIdGenerator.getAndIncrement(), adsData);
+
+        // Start a new request-transaction (Is ended in the response-handler)
+        RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+        transaction.submit(() -> context.sendRequest(amsPacket)
+            .expectResponse(AmsPacket.class, Duration.ofMillis(configuration.getTimeoutRequest()))
+            .onTimeout(future::completeExceptionally)
+            .onError((p, e) -> future.completeExceptionally(e))
+            .check(responseAmsPacket -> responseAmsPacket.getInvokeId() == amsPacket.getInvokeId())
+            .unwrap(AmsPacket::getData)
+            .handle(responseAdsData -> {
+                final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, responseAdsData);
+                // Convert the response from the PLC into a PLC4X Response ...
+                future.complete(plcReadResponse);
+                // Finish the request-transaction.
+                transaction.endRequest();
+            }));
+        return future;
+    }
+
+    protected CompletableFuture<PlcReadResponse> multiRead(PlcReadRequest readRequest, List<DirectAdsField> directAdsFields) {
+        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
+
+        // Calculate the size of all fields together.
+        int size = 0;
+
+        // TODO: Add the items ...
+        List<AdsReadRequest> items = new ArrayList<>(directAdsFields.size());
+
+        // With multi-requests, the index-group is fixed and the index offset indicates the number of elements.
+        AdsData adsData = new AdsReadWriteRequest(
+            ReservedIndexGroups.ADSIGRP_MULTIPLE_READ.getValue(), directAdsFields.size(), size,
+            items.toArray(new AdsReadRequest[0]), new byte[0]);
+
+        AmsPacket amsPacket = new AmsPacket(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(),
+            configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(),
+            CommandId.ADS_READ, DEFAULT_COMMAND_STATE, 0, invokeIdGenerator.getAndIncrement(), adsData);
+
+        // Start a new request-transaction (Is ended in the response-handler)
+        RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+        transaction.submit(() -> context.sendRequest(amsPacket)
+            .expectResponse(AmsPacket.class, Duration.ofMillis(configuration.getTimeoutRequest()))
+            .onTimeout(future::completeExceptionally)
+            .onError((p, e) -> future.completeExceptionally(e))
+            .check(responseAmsPacket -> responseAmsPacket.getInvokeId() == amsPacket.getInvokeId())
+            .unwrap(AmsPacket::getData)
+            .handle(responseAdsData -> {
+                final PlcReadResponse plcReadResponse = convertToPlc4xReadResponse(readRequest, responseAdsData);
+                // Convert the response from the PLC into a PLC4X Response ...
+                future.complete(plcReadResponse);
+                // Finish the request-transaction.
+                transaction.endRequest();
+            }));
+        return future;
+    }
+
+    protected PlcReadResponse convertToPlc4xReadResponse(PlcReadRequest readRequest, AdsData adsData) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
+        return super.write(writeRequest);
+    }
+
+    @Override
+    protected void decode(ConversationContext<AmsPacket> context, AmsPacket msg) throws Exception {
+        super.decode(context, msg);
+    }
+
+    protected List<DirectAdsField> getDirectAddresses(List<PlcField> fields) {
+        // Get all symbolic fields from the current request.
+        // These potentially need to be resolved to direct addresses, if this has not been done before.
+        final List<SymbolicAdsField> referencedSymbolicFields = fields.stream()
+            .filter(plcField -> plcField instanceof SymbolicAdsField)
+            .map(plcField -> (SymbolicAdsField) plcField).collect(Collectors.toList());
+
+        // Find out for which of these symbolic addresses no resolution has been initiated.
+        final List<SymbolicAdsField> symbolicFieldsNeedingResolution = referencedSymbolicFields.stream()
+            .filter(symbolicAdsField -> symbolicFieldMapping.containsKey(symbolicAdsField))
+            .collect(Collectors.toList());
+
+        // If there are unresolved symbolic addresses, initiate the resolution
+        if(!symbolicFieldsNeedingResolution.isEmpty()) {
+            // If a previous request initiated a resolution request, join that resolutions future instead.
+            // If not, initiate a new resolution request.
+            final CompletableFuture<Void> resolutionComplete =
+                CompletableFuture.allOf(symbolicFieldsNeedingResolution.stream().map(symbolicAdsField -> {
+                    if (pendingResolutionRequests.containsKey(symbolicAdsField)) {
+                        return pendingResolutionRequests.get(symbolicAdsField);
+                    } else {
+                        // Initiate a new resolution-request and add that to the pending resolution requests.
+                        CompletableFuture<DirectAdsField> internalResolutionFuture =
+                            resolveSymbolicAddress(symbolicAdsField);
+                        // Create a second future which will be completed as soon as the resolution result has
+                        // been added to the map.
+                        CompletableFuture<DirectAdsField> resolutionFuture = new CompletableFuture<>();
+                        // Make sure the resolved address is added to the mapping.
+                        internalResolutionFuture.thenAccept(directAdsField -> {
+                            symbolicFieldMapping.put(symbolicAdsField, directAdsField);
+                            // Now we can tell the other waiting processes about the result.
+                            resolutionFuture.complete(directAdsField);
+                        });
+                        return resolutionFuture;
+                    }
+                }).toArray(CompletableFuture[]::new));
+            // Wait for the resolution to finish.
+            try {
+                resolutionComplete.get(configuration.getTimeoutSymbolicAddressResolution(), TimeUnit.MILLISECONDS);
+            } catch (TimeoutException e) {
+                // TODO: Return an error indicating a timeout during resolution.
+            } catch (InterruptedException | ExecutionException e) {
+                // TODO: Return an error indicating a timeout an internal server error.
+            }
+        }
+
+        // So here all fields should be resolved so we can continue normally.
+        return fields.stream().map(plcField -> {
+            if(plcField instanceof SymbolicAdsField) {
+                return symbolicFieldMapping.get(plcField);
+            } else {
+                return (DirectAdsField) plcField;
+            }
+        }).collect(Collectors.toList());
+    }
+
+    protected CompletableFuture<DirectAdsField> resolveSymbolicAddress(SymbolicAdsField symbolicAdsField) {
+        return null;
+    }
+
 }
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java
deleted file mode 100644
index ce56c37..0000000
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.plc4x.java.amsads;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import java.util.regex.Matcher;
-
-
-public class AMSADSPlcDriverTest {
-
-/*    @Test
-    public void matchExpression() {
-        Matcher matcher = SERIAL_PATTERN.matcher("serial:///COM4");
-
-        Assertions.assertTrue(matcher.matches());
-    }
-
-    @Test
-    public void matchExpression2() {
-        Matcher matcher = DF1_URI_PATTERN.matcher("df1:serial:///COM4");
-
-        Assertions.assertTrue(matcher.matches());
-    }*/
-}
\ No newline at end of file
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/AmsAdsSerializerParserTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/AmsAdsSerializerParserTest.java
index cf76143..360d92f 100644
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/AmsAdsSerializerParserTest.java
+++ b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/AmsAdsSerializerParserTest.java
@@ -20,10 +20,12 @@
 package org.apache.plc4x.protocol.amsads;
 
 
-public class AmsAdsSerializerParserTest /*extends ProtocolTestsuiteRunner*/ {
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class AmsAdsSerializerParserTest extends ParserSerializerTestsuiteRunner {
 
     public AmsAdsSerializerParserTest() {
-        //super("/testsuite/Df1Testsuite.xml");
+        super("/testsuite/AdsParserSerializerTest.xml");
     }
 
 }
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java
deleted file mode 100644
index 696c9f8..0000000
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.plc4x.protocol.amsads;
-
-public class BenchmarkGeneratedDf1 {
-
-    public static void main(String[] args) throws Exception {
-        /*// Manually build a message
-        ReadRequest readRequest = new ReadRequest(new DF1SymbolMessageFrameStart((short) 0x09, (short) 0x00, new DF1ReadRequest((short) 0x00, 0x01, 0x0B, (short) 0x02)), new DF1SymbolMessageFrameEnd());
-
-        // Serialize the message
-        WriteBuffer writeBuffer = new WriteBuffer(100, false);
-        new ReadRequestIO().serialize(writeBuffer, readRequest);
-        byte[] data = writeBuffer.getData();
-
-        // Send the serialized message to the PLC via COM port
-        SerialPort comPort = SerialPort.getCommPort("/dev/cu.usbserial-AL065SUZ");
-        comPort.openPort();
-        comPort.setComPortParameters(19200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
-        comPort.writeBytes(data, 20);
-
-        // Give the PLC some time to respond.
-        while (comPort.bytesAvailable() == 0) {
-            Thread.sleep(22);
-        }
-
-        // Read the response
-        byte[] readBytes = new byte[comPort.bytesAvailable()];
-        comPort.readBytes(readBytes, readBytes.length);
-
-        // Parse the ACK/NACK response
-        ReadBuffer readBuffer = new ReadBuffer(readBytes);
-        Result result = new ResultIO().parse(readBuffer);
-
-        // Check if the response was an ACK
-        if(result.getResult() instanceof DF1SymbolMessageFrameACK) {
-            // The actual result is sent with a little delay.
-            while (comPort.bytesAvailable() == 0) {
-                Thread.sleep(22);
-            }
-
-            // Read the actual response data
-            readBytes = new byte[comPort.bytesAvailable()];
-            comPort.readBytes(readBytes, readBytes.length);
-
-            // Parse the response
-            readBuffer = new ReadBuffer(readBytes);
-            ReadResponse readResponse = new ReadResponseIO().parse(readBuffer, (short) 0x02);
-
-            // So something senseless ;-)
-            System.out.println(readResponse);
-        } else {
-            System.out.println("Didn't get an ACK");
-        }
-
-        comPort.closePort();*/
-    }
-
-}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java
deleted file mode 100644
index 7e4141b..0000000
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.plc4x.protocol.df1;
-
-import com.fazecast.jSerialComm.SerialPort;
-
-public class BenchmarkManualDf1 {
-
-    public static void main(String[] args) throws Exception {
-//        byte[] rData = Hex.decodeHex("0300006702f080320100000001005600000407120a10060001032b84000160120a10020001032b840001a0120a10010001032b840001a9120a10050001032b84000150120a10020001032b84000198120a10040001032b84000140120a10020001032b84000190");
-//        long start = System.currentTimeMillis();
-//        int numRunsParse = 2000000;
-//        TPKTPacketIO tpktPacketIO = new TPKTPacketIO();
-//
-//
-//        CommPortIdentifier id = CommPortIdentifier.getPortIdentifier("");
-//
-//
-//        // Benchmark the parsing code
-//        TPKTPacket packet = null;
-//        for(int i = 0; i < numRunsParse; i++) {
-//            ReadBuffer rBuf = new ReadBuffer(rData);
-//            packet = tpktPacketIO.parse(rBuf);
-//        }
-//        long endParsing = System.currentTimeMillis();
-//
-//        System.out.println("Parsed " + numRunsParse + " packets in " + (endParsing - start) + "ms");
-//        System.out.println("That's " + ((float) (endParsing - start) / numRunsParse) + "ms per packet");
-//
-//        // Benchmark the serializing code
-//        int numRunsSerialize = 2000000;
-//        byte[] oData = null;
-//        for(int i = 0; i < numRunsSerialize; i++) {
-//            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
-//            tpktPacketIO.serialize(wBuf, packet);
-//            oData = wBuf.getData();
-//        }
-//        long endSerializing = System.currentTimeMillis();
-//
-//        System.out.println("Serialized " + numRunsSerialize + " packets in " + (endSerializing - endParsing) + "ms");
-//        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRunsSerialize) + "ms per packet");
-//        if(!Arrays.equals(rData, oData)) {
-//            for(int i = 0; i < rData.length; i++) {
-//                if(rData[i] != oData[i]) {
-//                    System.out.println("Difference in byte " + i);
-//                }
-//            }
-//            System.out.println("Not equals");
-//        } else {
-//            System.out.println("Bytes equal");
-//        }
-
-
-//        byte[] rData = {0x10, 0x02, 0x00, 0x09, 0x41, 0x00, 0x01, 0x00, 0x1F, 0x1F, 0x10, 0x03, 0x1A, 0x2B};
-//
-//        DF1SymbolIO df1SymbolIO = new DF1SymbolIO();
-//        DF1Symbol packet;
-//        ReadBuffer rBuf = new ReadBuffer(rData);
-//        int statusWord = (rData[7]<<8) + rData[6];
-//        DF1Command messageCommand = new DF1Command((short)rData[5]); //,(short)statusWord);
-//        DF1SymbolMessageFrameStart messageStart = new DF1SymbolMessageFrameStart((short)rData[3],(short)rData[2], messageCommand);
-//        packet = df1SymbolIO.parse(rBuf, (short) (rData.length-12), messageStart);
-//
-//        System.out.println("x: " + packet);
-//        System.exit(0);
-
-
-
-        SerialPort comPort = SerialPort.getCommPorts()[0];
-        comPort.openPort();
-
-        comPort.setComPortParameters(19200, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY);
-//        comPort.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
-
-        System.out.print(comPort.getSystemPortName() + " | ");
-        //System.out.print(comPort.getPortDescription() + " | ");
-        System.out.print(comPort.getDescriptivePortName() + " | Baud rate: ");
-        System.out.println(comPort.getBaudRate());
-//        System.out.println(comPort.getReadTimeout());
-//        System.out.println(comPort.getWriteTimeout());
-
-
-
-//        DF1SymbolIO df1message = new DF1SymbolIO();
-
-
-        byte[] c_STX = {0x02};
-        byte[] c_SOH = {0x01};
-        byte[] c_ETX = {0x03};
-        byte[] c_EOT = {0x04};
-        byte[] c_ENQ = {0x05};
-        byte[] c_ACK = {0x06};
-        byte[] c_DLE = {0x10};
-        byte[] c_NAK = {0x0f};
-
-        byte[] c_DST = {0x09};
-        byte[] c_SRC = {0x00};
-        byte[] c_CMD = {0x06};
-        byte[] c_FNC = {0x03};
-        byte[] c_STS = {0x00};
-        byte[] c_TNS = {0x01, 0x00};
-        byte[] c_ADR = {0x11, 0x00};
-        byte[] c_SZE = {0x02};
-//        byte[] c_BCC = {-30};
-
-//        byte[] c_STN = {0x11};
-//        byte[] c_DST = {0x01};
-//        byte[] c_SRC = {0x00};
-//        byte[] c_SZE = {0x0c};
-//        byte[] c_TNS = {0x41, 0x00};
-//        byte[] c_ADR = {0x12, 0x00};
-//        byte[] c_CRC = {-49, 0x40};
-
-
-//        byte[] message = {0x10, 0x01, 0x11, 0x10, 0x02, 0x09, 0x00, 0x01, 0x00, 0x41, 0x00, 0x12, 0x00, 0x0c, 0x10, 0x03}; // halfduplex msg
-//        comPort.writeBytes(message, message.length);
-
-//        byte[] message = {0x10, 0x05, 0x11, -17};         // halfduplex poll
-//        comPort.writeBytes(message, message.length);
-
-
-//        comPort.writeBytes(c_DLE, 1);     // fullduplex msg Seite 235
-//        comPort.writeBytes(c_STX, 1);
-//        comPort.writeBytes(c_DST, 1);
-//        comPort.writeBytes(c_SRC, 1);
-//        comPort.writeBytes(c_CMD, 1);
-//        comPort.writeBytes(c_STS, 1);
-//        comPort.writeBytes(c_TNS, 2);
-//        comPort.writeBytes(c_FNC, 1);
-//        comPort.writeBytes(c_ADR, 2);
-//        comPort.writeBytes(c_SZE, 1);
-//        comPort.writeBytes(c_DLE, 1);
-//        comPort.writeBytes(c_ETX, 1);
-
-        byte[] msg = {0x10, 0x02,   0x09, 0x00,   0x01, 0x00,   0x01, 0x00,   0x0b, 0x00,   0x02,   0x10, 0x03};
-        comPort.writeBytes(msg, 13);
-
-
-//        int[] crcmsg = {c_DST[0], c_SRC[0], c_CMD[0], c_STS[0], c_TNS[0], c_TNS[1], c_ADR[0], c_ADR[1], c_SZE[0], c_ETX[0]}; // fullduplex CRC
-//        int[] crcmsg = {c_DST[0], c_SRC[0], c_CMD[0], c_STS[0], c_TNS[0], c_TNS[1], c_FNC[0], c_ETX[0]};                       // diagnostic status request
-//        int[] crcmsg = {0x11, 0x02, 0x09, 0x00, 0x01, 0x00, 0x41, 0x00, 0x12, 0x00, 0x0c, 0x03}; // halfduplex CRC
-        int[] crcmsg = { 0x09, 0x00,   0x01, 0x00,   0x01, 0x00,   0x0b, 0x00,   0x02,   0x03};
-
-        int[] c_CRC = CalcCRC(crcmsg);
-        byte[] crc1 = {(byte)c_CRC[0]};
-        byte[] crc2 = {(byte)c_CRC[1]};
-        System.out.println("crc1: " + Integer.toHexString(crc1[0]));
-        System.out.println("crc2: " + Integer.toHexString(crc2[0]));
-        comPort.writeBytes(crc1, 1);
-        comPort.writeBytes(crc2, 1);
-
-
-        while (comPort.bytesAvailable() == 0) {
-            Thread.sleep(22); }
-
-        byte[] readBuffer = new byte[comPort.bytesAvailable()];
-        int numRead = comPort.readBytes(readBuffer, readBuffer.length);
-        System.out.println("Read " + numRead + " bytes.");
-
-        for (byte c_RCV : readBuffer) {
-            System.out.print(Integer.toHexString(c_RCV) + " | "); }
-        System.out.println("");
-
-//        if (numRead > 1) {
-//            if (readBuffer[1] != 0x15) {
-//                comPort.writeBytes(c_DLE, 1);
-//                comPort.writeBytes(c_ACK, 1);
-//            }
-//        }
-
-        while (comPort.bytesAvailable() == 0) {
-            Thread.sleep(22); }
-
-
-        byte[] readBuffer2 = new byte[comPort.bytesAvailable()];
-        int numRead2 = comPort.readBytes(readBuffer2, readBuffer2.length);
-        System.out.println("Read " + numRead2 + " bytes.");
-
-        for (byte c_RCV2 : readBuffer2) {
-            System.out.print(Integer.toHexString(c_RCV2) + " | "); }
-        System.out.println("");
-
-        comPort.closePort();
-
-    }
-
-        private static int[] CalcCRC(int[] crcBytes) {
-            int tmp = 0;
-            int crcL, crcR;
-
-            for (int newByte : crcBytes ) {
-                crcL = tmp >> 8;
-                crcR = tmp & 0xFF;
-                tmp = (crcL << 8) + (newByte ^ crcR);
-                for (int j=0; j<8; j++)
-                    if (tmp % 2 == 1) {     // check if LSB shifted out is 1 or 0
-                        tmp = tmp >> 1;
-                        tmp = tmp ^ 0xA001;
-                    } else {
-                        tmp = tmp >> 1;
-                    }
-            }
-
-//            return ((tmp & 0xFF) << 8) + (tmp >> 8);  // returns lowbyte|highbyte as one number, change return to non-array
-
-            int[] tmparray = {(tmp & 0xFF), (tmp >> 8)};
-            return tmparray;
-        }
-
-        private static int CalcBCC(int[] crcBytes) {
-            int tmp = 0;
-            int j = 0;
-
-            for (int newByte : crcBytes) {
-                tmp = tmp + newByte;
-                if (newByte == 0x10) {
-                    j = ++j; }
-            }
-            tmp = tmp - ((j/2) * 0x10);  // get rid of double DLE
-            return ((~tmp) & 0b11111111) + 1;
-        }
-}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java
deleted file mode 100644
index 0927985..0000000
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.plc4x.protocol.amsads;
-
-import org.apache.plc4x.java.PlcDriverManager;
-import org.apache.plc4x.java.api.PlcConnection;
-import org.apache.plc4x.java.api.messages.PlcReadRequest;
-import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * TODO write comment
- *
- * @author julian
- * Created by julian on 2019-08-07
- */
-public class EndToEndTest {
-
-    @Test
-    @Disabled("Seems to cause problems on Windows if no COM4 is available")
-    public void helloDf1() {
-        try (PlcConnection plcConnection = new PlcDriverManager().getConnection("df1:serial:///COM4")) {
-            PlcReadRequest request = plcConnection.readRequestBuilder()
-                .addItem("hurz", "5:INTEGER")
-                .build();
-
-            PlcReadResponse response = request.execute().get(100, TimeUnit.SECONDS);
-
-
-            // TODO: get the actual read bytes from the response
-            System.out.println(response);
-            System.out.println("Response code was " + response.getResponseCode("erster"));
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}
diff --git a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java b/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java
deleted file mode 100644
index e944d0b..0000000
--- a/sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-package org.apache.plc4x.protocol.amsads;
-
-public class IOTest {
-
-/*    @Test
-    public void testXml() throws Exception {
-        byte[] rData = Hex.decodeHex("10020900010001001100021003546F");
-        ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
-        ReadBuffer rBuf = new ReadBuffer(rData, false);
-        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
-        String xml = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
-        System.out.println(xml);
-        DF1Symbol symbol2 = mapper.readValue(xml, DF1Symbol.class);
-        System.out.println(symbol2);
-    }
-
-    @Test
-    public void testJson() throws Exception {
-        byte[] rData = Hex.decodeHex("10020A0941000100FFFF1003DFB9");
-        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
-        ReadBuffer rBuf = new ReadBuffer(rData, false);
-        DF1Symbol symbol = new DF1SymbolIO().parse(rBuf);
-        String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(symbol);
-        System.out.println(json);
-        DF1Symbol symbol2 = mapper.readValue(json, DF1Symbol.class);
-        System.out.println(symbol2);
-    }*/
-
-    /*@Test
-    public void testParser() throws Exception {
-        byte[] rData = Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
-        long start = System.currentTimeMillis();
-        int numRunsParse = 20000;
-
-        KNXNetIPMessageIO knxNetIPMessageIO = new KNXNetIPMessageIO();
-
-        // Benchmark the parsing code
-        KNXNetIPMessage packet = null;
-        for(int i = 0; i < numRunsParse; i++) {
-            ReadBuffer rBuf = new ReadBuffer(rData);
-            packet = knxNetIPMessageIO.parse(rBuf);
-        }
-        long endParsing = System.currentTimeMillis();
-
-        System.out.println("Parsed " + numRunsParse + " packets in " + (endParsing - start) + "ms");
-        System.out.println("That's " + ((float) (endParsing - start) / numRunsParse) + "ms per packet");
-
-        // Benchmark the serializing code
-        int numRunsSerialize = 20000;
-        byte[] oData = null;
-        for(int i = 0; i < numRunsSerialize; i++) {
-            WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes());
-            knxNetIPMessageIO.serialize(wBuf, packet);
-            oData = wBuf.getData();
-        }
-        long endSerializing = System.currentTimeMillis();
-
-        System.out.println("Serialized " + numRunsSerialize + " packets in " + (endSerializing - endParsing) + "ms");
-        System.out.println("That's " + ((float) (endSerializing - endParsing) / numRunsSerialize) + "ms per packet");
-        if(!Arrays.equals(rData, oData)) {
-            for(int i = 0; i < rData.length; i++) {
-                if(rData[i] != oData[i]) {
-                    System.out.println("Difference in byte " + i);
-                }
-            }
-            System.out.println("Not equals");
-        } else {
-            System.out.println("Bytes equal");
-        }
-    }*/
-
-}
diff --git a/sandbox/test-java-amsads-driver/src/test/resources/testsuite/AdsParserSerializerTest.xml b/sandbox/test-java-amsads-driver/src/test/resources/testsuite/AdsParserSerializerTest.xml
new file mode 100644
index 0000000..ae2a836
--- /dev/null
+++ b/sandbox/test-java-amsads-driver/src/test/resources/testsuite/AdsParserSerializerTest.xml
@@ -0,0 +1,414 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd"
+                bigEndian="false">
+
+  <name>Beckhoff ADS/AMS</name>
+
+  <testcase>
+    <name>Ams-Single-Item-Read-Request</name>
+    <raw>00002c000000c0a8171401015303c0a817c801015303020004000c000000000000000200000005f000000000801a01000000</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>851</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>200</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>851</sourceAmsPort>
+          <commandId>ADS_READ</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>false</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>2</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadRequest">
+            <indexGroup>61445</indexGroup>
+            <indexOffset>444596224</indexOffset>
+            <length>1</length>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Single-Item-Read-Response</name>
+    <raw>000029000000c0a817c801015303c0a817140101530302000500090000000000000002000000000000000100000001</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>200</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>851</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>851</sourceAmsPort>
+          <commandId>ADS_READ</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>true</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>2</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadResponse">
+            <result>0</result>
+            <data>AQ==</data>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Resolve-Symbolic-Address-Request</name>
+    <raw>00004a000000c0a8171401015303c0a817cd0101feff090004002a000000000000000100000003f0000000000000040000001a0000006d61696e2e665f74726967446174656947656c6573656e2e4d00</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>851</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>65534</sourceAmsPort>
+          <commandId>ADS_READ_WRITE</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>false</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadWriteRequest">
+            <indexGroup>61443</indexGroup>
+            <indexOffset>0</indexOffset>
+            <readLength>4</readLength>
+            <items/>
+            <data>bWFpbi5mX3RyaWdEYXRlaUdlbGVzZW4uTQA=</data>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Resolve-Symbolic-Address-Response</name>
+    <raw>00002c000000c0a817cd0101feffc0a8171401015303090005000c000000000000000100000000000000040000000100801b</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>65534</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>851</sourceAmsPort>
+          <commandId>ADS_READ_WRITE</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>true</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadWriteResponse">
+            <result>0</result>
+            <data>AQCAGw==</data>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Read-Symbolic-Address-Request</name>
+    <raw>00002c000000c0a8171401015303c0a817cd0101feff020004000c000000000000000100000005f000000100801b04000000</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>851</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>65534</sourceAmsPort>
+          <commandId>ADS_READ</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>false</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadRequest">
+            <indexGroup>61445</indexGroup>
+            <indexOffset>461373441</indexOffset>
+            <length>4</length>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Read-Symbolic-Address-Response</name>
+    <raw>000029000000c0a817cd0101feffc0a817140101530302000500090000000000000001000000000000000100000001</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>65534</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>851</sourceAmsPort>
+          <commandId>ADS_READ</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>true</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsReadResponse">
+            <result>0</result>
+            <data>AQ==</data>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Release-Symbolic-Address-Handle-Request</name>
+    <raw>000030000000c0a8171401015303c0a817cd0101feff0300040010000000000000000100000006f0000000000000040000000100801b</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>851</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>65534</sourceAmsPort>
+          <commandId>ADS_WRITE</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>false</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsWriteRequest">
+            <indexGroup>61446</indexGroup>
+            <indexOffset>0</indexOffset>
+            <data>AQCAGw==</data>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>Ams-Release-Symbolic-Address-Handle-Response</name>
+    <raw>000024000000c0a817cd0101feffc0a81714010153030300050004000000000000000100000000000000</raw>
+    <root-type>AmsTCPPacket</root-type>
+    <xml>
+      <AmsTCPPacket className="org.apache.plc4x.java.amsads.readwrite.AmsTCPPacket">
+        <userdata className="org.apache.plc4x.java.amsads.readwrite.AmsPacket">
+          <targetAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>205</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </targetAmsNetId>
+          <targetAmsPort>65534</targetAmsPort>
+          <sourceAmsNetId className="org.apache.plc4x.java.amsads.readwrite.AmsNetId">
+            <octet1>192</octet1>
+            <octet2>168</octet2>
+            <octet3>23</octet3>
+            <octet4>20</octet4>
+            <octet5>1</octet5>
+            <octet6>1</octet6>
+          </sourceAmsNetId>
+          <sourceAmsPort>851</sourceAmsPort>
+          <commandId>ADS_WRITE</commandId>
+          <state className="org.apache.plc4x.java.amsads.readwrite.State">
+            <initCommand>false</initCommand>
+            <updCommand>false</updCommand>
+            <timestampAdded>false</timestampAdded>
+            <highPriorityCommand>false</highPriorityCommand>
+            <systemCommand>false</systemCommand>
+            <adsCommand>true</adsCommand>
+            <noReturn>false</noReturn>
+            <response>true</response>
+            <broadcast>false</broadcast>
+          </state>
+          <errorCode>0</errorCode>
+          <invokeId>1</invokeId>
+          <data className="org.apache.plc4x.java.amsads.readwrite.AdsWriteResponse">
+            <result>0</result>
+          </data>
+        </userdata>
+      </AmsTCPPacket>
+    </xml>
+  </testcase>
+
+</test:testsuite>
\ No newline at end of file
diff --git a/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml b/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml
deleted file mode 100644
index 2085003..0000000
--- a/sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
-  -->
-<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd"
-                bigEndian="true">
-
-  <name>Allen-Bradley DF1</name>
-
-  <testcase>
-    <name>Unprotected Read Address Request</name>
-    <raw>10020900010001001100021003546F</raw>
-    <root-type>DF1Symbol</root-type>
-    <xml>
-      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
-        <destinationAddress>9</destinationAddress>
-        <sourceAddress>0</sourceAddress>
-        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadRequest">
-          <status>0</status>
-          <transactionCounter>1</transactionCounter>
-          <address>17</address>
-          <size>2</size>
-        </command>
-      </DF1SymbolMessageFrame>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>Unprotected Read Address Response</name>
-    <raw>10020A0941000100FFFF1003DFB9</raw>
-    <root-type>DF1Symbol</root-type>
-    <xml>
-      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
-        <destinationAddress>10</destinationAddress>
-        <sourceAddress>9</sourceAddress>
-        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadResponse">
-          <status>0</status>
-          <transactionCounter>1</transactionCounter>
-          <data>
-            <data>255</data>
-            <data>255</data>
-          </data>
-        </command>
-      </DF1SymbolMessageFrame>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>Unprotected Read Address Response (Containing 0x10 in the data)</name>
-    <raw>10020A09410001001010FF1003BAAD</raw>
-    <root-type>DF1Symbol</root-type>
-    <xml>
-      <DF1SymbolMessageFrame className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrame">
-        <destinationAddress>10</destinationAddress>
-        <sourceAddress>9</sourceAddress>
-        <command className="org.apache.plc4x.java.df1.readwrite.DF1UnprotectedReadResponse">
-          <status>0</status>
-          <transactionCounter>1</transactionCounter>
-          <data>
-            <data>16</data>
-            <data>255</data>
-          </data>
-        </command>
-      </DF1SymbolMessageFrame>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>ACK Response</name>
-    <raw>1006</raw>
-    <root-type>DF1Symbol</root-type>
-    <xml>
-      <DF1SymbolMessageFrameACK className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrameACK"/>
-    </xml>
-  </testcase>
-
-  <testcase>
-    <name>NACK Response</name>
-    <raw>1015</raw>
-    <root-type>DF1Symbol</root-type>
-    <xml>
-      <DF1SymbolMessageFrameNAK className="org.apache.plc4x.java.df1.readwrite.DF1SymbolMessageFrameNAK"/>
-    </xml>
-  </testcase>
-
-</test:testsuite>
\ No newline at end of file