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:30 UTC

[plc4x] branch develop updated (f6524db -> a7b7b84)

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

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


    from f6524db  Merge pull request #173 from ottlinger/patch-1
     new aa6e15e  - Changed the code generator to not automatically pass all parent types arguments to the sub-types - Made it possible to reference enum constant properties in mspec
     new 8376247  - Adjusted the existing mspec files to the changes in the code-generation (Explicitly Forwarded parent parser arguments to the children, where needed) - Worked a lot on the AMS/ADS mspec
     new a7b7b84  - 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

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


Summary of changes:
 .../language/java/JavaLanguageTemplateHelper.java  |   4 +-
 .../main/resources/templates/java/io-template.ftlh |   2 +-
 .../mspec/parser/MessageFormatListener.java        |  11 +-
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |   2 +-
 .../java/spi/generation/EvaluationHelper.java      |   9 +
 .../main/resources/protocols/abeth/ab-eth.mspec    |   2 +-
 .../protocols/amsads/amsads-discovery.mspec        |  56 +++
 .../main/resources/protocols/amsads/amsads.mspec   | 146 +++++---
 .../resources/protocols/bacnetip/bacnetip.mspec    |  14 +-
 .../eip/src/main/resources/protocols/eip/eip.mspec |   6 +-
 .../main/resources/protocols/firmata/firmata.mspec |   4 +-
 .../s7/src/main/resources/protocols/s7/s7.mspec    |  10 +-
 .../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 -----
 31 files changed, 879 insertions(+), 738 deletions(-)
 create mode 100644 protocols/amsads/src/main/resources/protocols/amsads/amsads-discovery.mspec
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/connection/AdsAbstractPlcConnection.java (98%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/connection/AdsConnectionFactory.java (97%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/connection/AdsSerialPlcConnection.java (98%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/connection/AdsTcpPlcConnection.java (99%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/protocol/Ads2PayloadProtocol.java (96%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/protocol/Payload2SerialProtocol.java (95%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/protocol/Payload2TcpProtocol.java (91%)
 rename sandbox/test-java-amsads-driver/src/main/java/org/apache/plc4x/java/amsads/{ => attic}/protocol/Plc4x2AdsProtocol.java (94%)
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/java/amsads/AMSADSPlcDriverTest.java
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkGeneratedDf1.java
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/BenchmarkManualDf1.java
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/EndToEndTest.java
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/java/org/apache/plc4x/protocol/amsads/IOTest.java
 create mode 100644 sandbox/test-java-amsads-driver/src/test/resources/testsuite/AdsParserSerializerTest.xml
 delete mode 100644 sandbox/test-java-amsads-driver/src/test/resources/testsuite/Df1Testsuite.xml


[plc4x] 02/03: - Adjusted the existing mspec files to the changes in the code-generation (Explicitly Forwarded parent parser arguments to the children, where needed) - Worked a lot on the AMS/ADS mspec

Posted by cd...@apache.org.
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 83762471fd7213ac8d6067b8e54f64bd18c2e46c
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Aug 1 17:59:03 2020 +0200

    - Adjusted the existing mspec files to the changes in the code-generation (Explicitly Forwarded parent parser arguments to the children, where needed)
    - Worked a lot on the AMS/ADS mspec
---
 .../s7/readwrite/protocol/S7ProtocolLogic.java     |   2 +-
 .../main/resources/protocols/abeth/ab-eth.mspec    |   2 +-
 .../protocols/amsads/amsads-discovery.mspec        |  56 ++++++++
 .../main/resources/protocols/amsads/amsads.mspec   | 146 +++++++++++++--------
 .../resources/protocols/bacnetip/bacnetip.mspec    |  14 +-
 .../eip/src/main/resources/protocols/eip/eip.mspec |   6 +-
 .../main/resources/protocols/firmata/firmata.mspec |   4 +-
 .../s7/src/main/resources/protocols/s7/s7.mspec    |  10 +-
 8 files changed, 166 insertions(+), 74 deletions(-)

diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index f99b5ed..420ddb2 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -221,7 +221,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
         return toPlcReadResponse((InternalPlcReadRequest) readRequest, readInternal(s7MessageRequest));
     }
 
-    /** Maps the S7ReadResponse of a PlcReadRequest to a PlcReadRespoonse */
+    /** Maps the S7ReadResponse of a PlcReadRequest to a PlcReadResponse */
     private CompletableFuture<PlcReadResponse> toPlcReadResponse(InternalPlcReadRequest readRequest, CompletableFuture<S7MessageResponseData> response) {
         return response
             .thenApply(p -> {
diff --git a/protocols/ab-eth/src/main/resources/protocols/abeth/ab-eth.mspec b/protocols/ab-eth/src/main/resources/protocols/abeth/ab-eth.mspec
index 851a072..5d8d0ff 100644
--- a/protocols/ab-eth/src/main/resources/protocols/abeth/ab-eth.mspec
+++ b/protocols/ab-eth/src/main/resources/protocols/abeth/ab-eth.mspec
@@ -62,7 +62,7 @@
     [simple        uint 8  'status']
     [simple        uint 16 'transactionCounter']
     [typeSwitch 'commandCode'
-        ['0x4F' DF1CommandResponseMessageProtectedTypedLogicalRead [uint 8 'status']
+        ['0x4F' DF1CommandResponseMessageProtectedTypedLogicalRead [uint 16 'payloadLength', uint 8 'status']
             [array    uint 8 'data' length 'payloadLength - 8']
         ]
     ]
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads-discovery.mspec b/protocols/amsads/src/main/resources/protocols/amsads/amsads-discovery.mspec
new file mode 100644
index 0000000..f549d70
--- /dev/null
+++ b/protocols/amsads/src/main/resources/protocols/amsads/amsads-discovery.mspec
@@ -0,0 +1,56 @@
+//
+// 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.
+//
+
+////////////////////////////////////////////////////////////////
+// AMS/TCP Packet
+////////////////////////////////////////////////////////////////
+
+[type 'AmsTCPDiscoveryPacket'
+    [const uint 32 'header' '0x03661471']
+    [reserved   uint 32  '0x00000000']
+    [simple     uint 16  'something']
+    [reserved   uint 16  '0x0000']
+    [simple     AmsNetId 'amsNetId']
+    [reserved   uint 16  '0x1027']
+    [simple     uint 16  'something2']
+    [reserved   uint 32  '0x0000']
+    [simple     uint 16  'something3']
+    [implicit   uint 16  'hostnameLength' 'COUNT(hostname)']
+    [array      int 8    'hostname' COUNT 'hostnameLength']
+    [reserved   uint 16  '0x4000']
+    [simple     uint 16  'something4']
+    [simple     uint 16  'something5']
+    [reserved   uint 32  '0x0000']
+    [simple     uint 16  'something6']
+    [reserved   uint 32  '0x0000']
+    [reserved   uint 32  '0x00000000']
+    [reserved   uint 32  '0x00000000']
+    [reserved   uint 16  '0x0000']
+    [implicit   uint 16  'ipLength' 'COUNT(ip)']
+    [array      int 8    'ip' COUNT 'ipLength']
+]
+
+[type 'AmsNetId'
+    [simple     uint        8   'octet1'            ]
+    [simple     uint        8   'octet2'            ]
+    [simple     uint        8   'octet3'            ]
+    [simple     uint        8   'octet4'            ]
+    [simple     uint        8   'octet5'            ]
+    [simple     uint        8   'octet6'            ]
+]
diff --git a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
index 0319554..e5131f4 100644
--- a/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
+++ b/protocols/amsads/src/main/resources/protocols/amsads/amsads.mspec
@@ -22,19 +22,14 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AmsTCPPacket'
-    // The ams - tcp to be sent.
-    [simple AmsTcpHeader 'amsTcpHeader']
-    // The AMS packet to be sent.
-    [simple AmsPacket    'userdata'    ]
-]
-
-// AMS/TCP Header	6 bytes	contains the tcpLength of the data packet.
-[type 'AmsTcpHeader'
+    // AMS/TCP Header	6 bytes	contains the tcpLength of the data packet.
     // These bytes must be set to 0.
-    [reserved   uint       16       '0x0000' ]
+    [reserved   uint       16       '0x0000'                            ]
     // This array contains the length of the data packet.
     // It consists of the AMS-Header and the enclosed ADS data. The unit is bytes.
-    [simple     uint       32       'length']
+    [implicit   uint       32       'length'  'userdata.lengthInBytes'  ]
+    // The AMS packet to be sent.
+    [simple AmsPacket    'userdata'                                     ]
 ]
 
 ////////////////////////////////////////////////////////////////
@@ -59,7 +54,7 @@
     [simple     int          8  'fragmentNumber'     ]
     // The max. length of the AMS packet to be sent is 255. If larger AMS packets are to be sent then they have to be
     // fragmented (not published at the moment).
-    [simple     int          8  'length'     ]
+    [simple     int          8  'length'             ]
     [simple     uint        16  'crc'                ]
 ]
 
@@ -85,7 +80,7 @@
     [simple     int          8  'fragmentNumber'     ]
     // The max. length of the AMS packet to be sent is 255. If larger AMS packets are to be sent then they have to be
     // fragmented (not published at the moment).
-    [simple     int          8  'length'     ]
+    [simple     int          8  'length'             ]
     // The AMS packet to be sent.
     [simple AmsPacket           'userdata'           ]
     [simple     uint        16  'crc'                ]
@@ -117,12 +112,7 @@
 ////////////////////////////////////////////////////////////////
 
 [type 'AmsPacket'
-    [simple     AmsHeader  'amsHeader'                                                            ]
-    [simple     ADSData    'data'   ['amsHeader.commandId', 'amsHeader.state.response']              ]
-]
-
-// AMS Header	32 bytes	The AMS/TCP-Header contains the addresses of the transmitter and receiver. In addition the AMS error code , the ADS command Id and some other information.
-[type 'AmsHeader'
+    // AMS Header	32 bytes	The AMS/TCP-Header contains the addresses of the transmitter and receiver. In addition the AMS error code , the ADS command Id and some other information.
     // This is the AmsNetId of the station, for which the packet is intended. Remarks see below.
     [simple     AmsNetId        'targetAmsNetId'                            ]
     // This is the AmsPort of the station, for which the packet is intended.
@@ -136,12 +126,14 @@
     // 2 bytes.
     [simple     State           'state'                                     ]
     // 4 bytes	Size of the data range. The unit is byte.
-    [simple     uint        32  'length'                                ]
+    [implicit   uint        32  'length'   'data.lengthInBytes'             ]
     // 4 bytes	AMS error number. See ADS Return Codes.
     [simple     uint        32  'errorCode'                                 ]
     // free usable field of 4 bytes
     // 4 bytes	Free usable 32 bit array. Usually this array serves to send an Id. This Id makes is possible to assign a received response to a request, which was sent before.
     [simple      uint        32  'invokeId'                                 ]
+    // The payload
+    [simple     AdsData    'data'   ['commandId', 'state.response']         ]
 ]
 
 [enum uint 16 'CommandId'
@@ -158,8 +150,6 @@
 ]
 
 [type 'State'
-    [simple     bit 'broadcast'             ]
-    [reserved   int 7 '0x0'                 ]
     [simple     bit 'initCommand'           ]
     [simple     bit 'updCommand'            ]
     [simple     bit 'timestampAdded'        ]
@@ -168,6 +158,8 @@
     [simple     bit 'adsCommand'            ]
     [simple     bit 'noReturn'              ]
     [simple     bit 'response'              ]
+    [simple     bit 'broadcast'             ]
+    [reserved   int 7 '0x0'                 ]
 ]
 
 // It is not only possible to exchange data between TwinCAT modules on one PC, it is even possible to do so by ADS
@@ -198,10 +190,12 @@
     [simple     uint        8   'octet6'            ]
 ]
 
-[discriminatedType 'ADSData' [CommandId 'commandId', bit 'response']
+[discriminatedType 'AdsData' [CommandId 'commandId', bit 'response']
     [typeSwitch 'commandId', 'response'
-        ['CommandId.INVALID', 'true' AdsInvalidResponse]
         ['CommandId.INVALID', 'false' AdsInvalidRequest]
+        ['CommandId.INVALID', 'true' AdsInvalidResponse]
+
+        ['CommandId.ADS_READ_DEVICE_INFO', 'false' AdsReadDeviceInfoRequest]
         ['CommandId.ADS_READ_DEVICE_INFO', 'true' AdsReadDeviceInfoResponse
             // 4 bytes	ADS error number.
             [simple uint 32 'result']
@@ -214,15 +208,7 @@
             // Name	16 bytes	Name of ADS device
             [array int 8  'device' count '16']
         ]
-        ['CommandId.ADS_READ_DEVICE_INFO', 'false' AdsReadDeviceInfoRequest]
-        ['CommandId.ADS_READ', 'true' AdsReadResponse
-            // 4 bytes	ADS error number
-            [simple uint 32 'result']
-            // 4 bytes	Length of data which are supplied back.
-            [simple uint 32 'length']
-            // n bytes	Data which are supplied back.
-            [array int 8 'data' count 'length']
-        ]
+
         ['CommandId.ADS_READ', 'false' AdsReadRequest
             // 4 bytes	Index Group of the data which should be read.
             [simple uint 32 'indexGroup']
@@ -231,20 +217,31 @@
             // 4 bytes	Length of the data (in bytes) which should be read.
             [simple uint 32 'length']
         ]
-        ['CommandId.ADS_WRITE', 'true' AdsWriteResponse
+        ['CommandId.ADS_READ', 'true' AdsReadResponse
             // 4 bytes	ADS error number
             [simple uint 32 'result']
+            // 4 bytes	Length of data which are supplied back.
+            [implicit uint 32 'length' 'COUNT(data)']
+            // n bytes	Data which are supplied back.
+            [array int 8 'data' count 'length']
         ]
+
         ['CommandId.ADS_WRITE', 'false' AdsWriteRequest
             // 4 bytes	Index Group of the data which should be written.
             [simple uint 32 'indexGroup']
             // 4 bytes	Index Offset of the data which should be written.
             [simple uint 32 'indexOffset']
             // 4 bytes	Length of the data (in bytes) which should be written.
-            [simple uint 32 'length']
+            [implicit uint 32 'length' 'COUNT(data)']
             // n bytes	Data which are written in the ADS device.
             [array int 8 'data' count 'length']
         ]
+        ['CommandId.ADS_WRITE', 'true' AdsWriteResponse
+            // 4 bytes	ADS error number
+            [simple uint 32 'result']
+        ]
+
+        ['CommandId.ADS_READ_STATE', 'false' AdsReadStateRequest]
         ['CommandId.ADS_READ_STATE', 'true' AdsReadStateResponse
             // 4 bytes	ADS error number
             [simple uint 32 'result']
@@ -253,27 +250,22 @@
             // 2 bytes	New device status.
             [simple uint 16 'deviceState']
         ]
-        ['CommandId.ADS_READ_STATE', 'false' AdsReadStateRequest]
-        ['CommandId.ADS_WRITE_CONTROL', 'true' AdsWriteControlResponse
-            // 4 bytes	ADS error number
-            [simple uint 32 'result']
-        ]
+
         ['CommandId.ADS_WRITE_CONTROL', 'false' AdsWriteControlRequest
             // 2 bytes	New ADS status (see data type ADSSTATE of the ADS-DLL).
             [simple uint 16 'adsState']
             // 2 bytes	New device status.
             [simple uint 16 'deviceState']
             // 4 bytes	Length of data in byte.
-            [simple uint 32 'length']
+            [implicit uint 32 'length' 'COUNT(data)']
             // n bytes	Additional data which are sent to the ADS device
             [array int 8 'data' count 'length']
         ]
-        ['CommandId.ADS_ADD_DEVICE_NOTIFICATION', 'true' AdsAddDeviceNotificationResponse
+        ['CommandId.ADS_WRITE_CONTROL', 'true' AdsWriteControlResponse
             // 4 bytes	ADS error number
             [simple uint 32 'result']
-            // 4 bytes	Handle of notification
-            [simple uint 32 'notificationHandle']
         ]
+
         ['CommandId.ADS_ADD_DEVICE_NOTIFICATION', 'false' AdsAddDeviceNotificationRequest
             // 4 bytes	Index Group of the data, which should be sent per notification.
             [simple uint 32 'indexGroup']
@@ -291,15 +283,22 @@
             // 16bytes	Must be set to 0
             [reserved   uint       128       '0x0000' ]
         ]
-        ['CommandId.ADS_DELETE_DEVICE_NOTIFICATION', 'true' AdsDeleteDeviceNotificationResponse
+        ['CommandId.ADS_ADD_DEVICE_NOTIFICATION', 'true' AdsAddDeviceNotificationResponse
             // 4 bytes	ADS error number
             [simple uint 32 'result']
+            // 4 bytes	Handle of notification
+            [simple uint 32 'notificationHandle']
         ]
+
         ['CommandId.ADS_DELETE_DEVICE_NOTIFICATION', 'false' AdsDeleteDeviceNotificationRequest
             // 4 bytes	Handle of notification
             [simple uint 32 'notificationHandle']
         ]
-        ['CommandId.ADS_DEVICE_NOTIFICATION', 'true' AdsDeviceNotificationResponse]
+        ['CommandId.ADS_DELETE_DEVICE_NOTIFICATION', 'true' AdsDeleteDeviceNotificationResponse
+            // 4 bytes	ADS error number
+            [simple uint 32 'result']
+        ]
+
         ['CommandId.ADS_DEVICE_NOTIFICATION', 'false' AdsDeviceNotificationRequest
             // 4 bytes	Size of data in byte.
             [simple uint 32 'length']
@@ -308,14 +307,8 @@
             // n bytes	Array with elements of type AdsStampHeader.
             [array AdsStampHeader 'adsStampHeaders' count 'stamps']
         ]
-        ['CommandId.ADS_READ_WRITE', 'true' AdsReadWriteResponse
-            // 4 bytes	ADS error number
-            [simple uint 32 'result']
-            // 4 bytes	Length of data in byte.
-            [simple uint 32 'length']
-            // n bytes	Additional data which are sent to the ADS device
-            [array int 8 'data' count 'length']
-        ]
+        ['CommandId.ADS_DEVICE_NOTIFICATION', 'true' AdsDeviceNotificationResponse]
+
         ['CommandId.ADS_READ_WRITE', 'false' AdsReadWriteRequest
             // 4 bytes	Index Group of the data which should be written.
             [simple uint 32 'indexGroup']
@@ -324,9 +317,19 @@
             // 4 bytes	Length of data in bytes, which should be read.
             [simple uint 32 'readLength']
             // 4 bytes	Length of the data (in bytes) which should be written.
-            [simple uint 32 'writeLength']
+            [implicit uint 32 'writeLength' '(COUNT(items) * 12) + COUNT(data)']
+            // Only if the indexGroup implies a sum-read response, will the indexOffset indicate the number of elements.
+            [array  AdsReadRequest 'items' COUNT '(indexGroup == ReservedIndexGroups.ADSIGRP_MULTIPLE_READ.value) ? indexOffset : 0']
             // n bytes	Data which are written in the ADS device.
-            [array int 8 'data' count 'writeLength']
+            [array int 8 'data' count 'writeLength - (COUNT(items) * 12)']
+        ]
+        ['CommandId.ADS_READ_WRITE', 'true' AdsReadWriteResponse
+            // 4 bytes	ADS error number
+            [simple uint 32 'result']
+            // 4 bytes	Length of data in byte.
+            [implicit uint 32 'length'  'COUNT(data)']
+            // n bytes Additional data which are sent to the ADS device
+            [array int 8 'data' count 'length']
         ]
     ]
 ]
@@ -347,4 +350,37 @@
     [simple uint 32 'sampleSize']
     // n Bytes	Data
     [array int 8 'data' count 'sampleSize']
+]
+
+[enum uint 16 'ReservedIndexGroups'
+    ['0xF000' ADSIGRP_SYMTAB]
+    ['0xF001' ADSIGRP_SYMNAME]
+    ['0xF002' ADSIGRP_SYMVAL]
+    ['0xF003' ADSIGRP_SYM_HNDBYNAME]
+    ['0xF004' ADSIGRP_SYM_VALBYNAME]
+    ['0xF005' ADSIGRP_SYM_VALBYHND]
+    ['0xF006' ADSIGRP_SYM_RELEASEHND]
+    ['0xF007' ADSIGRP_SYM_INFOBYNAME]
+    ['0xF008' ADSIGRP_SYM_VERSION]
+    ['0xF009' ADSIGRP_SYM_INFOBYNAMEEX]
+    ['0xF00A' ADSIGRP_SYM_DOWNLOAD]
+    ['0xF00B' ADSIGRP_SYM_UPLOAD]
+    ['0xF00C' ADSIGRP_SYM_UPLOADINFO]
+    ['0xF010' ADSIGRP_SYMNOTE]
+    ['0xF020' ADSIGRP_IOIMAGE_RWIB]
+    ['0xF021' ADSIGRP_IOIMAGE_RWIX]
+    ['0xF025' ADSIGRP_IOIMAGE_RISIZE]
+    ['0xF030' ADSIGRP_IOIMAGE_RWOB]
+    ['0xF031' ADSIGRP_IOIMAGE_RWOX]
+    ['0xF035' ADSIGRP_IOIMAGE_RWOSIZE]
+    ['0xF040' ADSIGRP_IOIMAGE_CLEARI]
+    ['0xF050' ADSIGRP_IOIMAGE_CLEARO]
+    ['0xF060' ADSIGRP_IOIMAGE_RWIOB]
+    ['0xF080' ADSIGRP_MULTIPLE_READ]
+    ['0xF081' ADSIGRP_MULTIPLE_WRITE]
+    ['0xF082' ADSIGRP_MULTIPLE_GET_HANDLE]
+    ['0xF083' ADSIGRP_MULTIPLE_RELEASE_HANDLE]
+    ['0xF100' ADSIGRP_DEVICE_DATA]
+    ['0x0000' ADSIOFFS_DEVDATA_ADSSTATE]
+    ['0x0002' ADSIOFFS_DEVDATA_DEVSTATE]
 ]
\ No newline at end of file
diff --git a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
index eb001e9..870fe12 100644
--- a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
+++ b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
@@ -80,10 +80,10 @@
     [discriminator uint 8  'messageType']
     [optional      uint 16 'vendorId' '(messageType >= 128) && (messageType <= 255)']
     [typeSwitch 'messageType'
-        ['0x0' NLMWhoIsRouterToNetwork [uint 8  'messageType']
+        ['0x0' NLMWhoIsRouterToNetwork [uint 16 'apduLength', uint 8  'messageType']
             [array uint 16 'destinationNetworkAddress' length 'apduLength - (((messageType >= 128) && (messageType <= 255)) ? 3 : 1)']
         ]
-        ['0x1' NLMIAmRouterToNetwork [uint 8  'messageType']
+        ['0x1' NLMIAmRouterToNetwork [uint 16 'apduLength', uint 8  'messageType']
             [array uint 16 'destinationNetworkAddress' length 'apduLength - (((messageType >= 128) && (messageType <= 255)) ? 3 : 1)']
         ]
     ]
@@ -92,7 +92,7 @@
 [discriminatedType 'APDU' [uint 16 'apduLength']
     [discriminator uint 4 'apduType']
     [typeSwitch 'apduType'
-        ['0x0' APDUConfirmedRequest
+        ['0x0' APDUConfirmedRequest [uint 16 'apduLength']
             [simple   bit    'segmentedMessage'                       ]
             [simple   bit    'moreFollows'                            ]
             [simple   bit    'segmentedResponseAccepted'              ]
@@ -104,7 +104,7 @@
             [optional uint 8 'proposedWindowSize'   'segmentedMessage']
             [simple   BACnetConfirmedServiceRequest 'serviceRequest'  ['apduLength - (3 + (segmentedMessage ? 2 : 0))']]
         ]
-        ['0x1' APDUUnconfirmedRequest
+        ['0x1' APDUUnconfirmedRequest [uint 16 'apduLength']
             [reserved uint 4                          '0'             ]
             [simple   BACnetUnconfirmedServiceRequest 'serviceRequest' ['apduLength - 1']]
         ]
@@ -154,7 +154,7 @@
     [typeSwitch 'serviceChoice'
         ['0x00' BACnetConfirmedServiceRequestAcknowledgeAlarm
         ]
-        ['0x01' BACnetConfirmedServiceRequestConfirmedCOVNotification
+        ['0x01' BACnetConfirmedServiceRequestConfirmedCOVNotification [uint 16 'len']
             [const  uint 8               'subscriberProcessIdentifierHeader'         '0x09'                 ]
             [simple uint 8               'subscriberProcessIdentifier'                                      ]
             [const  uint 8               'monitoredObjectIdentifierHeader'           '0x1C'                 ]
@@ -224,7 +224,7 @@
         ]
         ['0x1A' BACnetConfirmedServiceRequestReadRange
         ]
-        ['0x0F' BACnetConfirmedServiceRequestWriteProperty
+        ['0x0F' BACnetConfirmedServiceRequestWriteProperty [uint 16 'len']
             [const    uint 8    'objectIdentifierHeader'    '0x0C'                          ]
             [simple   uint 10   'objectType'                                                ]
             [simple   uint 22   'objectInstanceNumber'                                      ]
@@ -300,7 +300,7 @@
         ]
         ['0x03' BACnetUnconfirmedServiceRequestUnconfirmedEventNotification
         ]
-        ['0x04' BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer
+        ['0x04' BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer [uint 16 'len']
             [const uint 8 'vendorIdHeader' '0x09']
             [simple uint 8 'vendorId']
             [const uint 8 'serviceNumberHeader' '0x1A']
diff --git a/protocols/eip/src/main/resources/protocols/eip/eip.mspec b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
index b772ff1..f375772 100644
--- a/protocols/eip/src/main/resources/protocols/eip/eip.mspec
+++ b/protocols/eip/src/main/resources/protocols/eip/eip.mspec
@@ -58,7 +58,7 @@
             [array      int     8   'tag'   length  '(RequestPathSize*2)']
             [simple     uint    16  'elementNb']
         ]
-        ['0xCC' CipReadResponse
+        ['0xCC' CipReadResponse [uint 16 'serviceLen']
               [reserved   uint            8   '0x00']
               [simple     uint            8   'status']
               [simple     uint            8   'extStatus']
@@ -77,12 +77,12 @@
             [simple     uint        8   'status']
             [simple     uint        8   'extStatus']
         ]
-        ['0x0A' MultipleServiceRequest
+        ['0x0A' MultipleServiceRequest [uint 16 'serviceLen']
                [const  int     8   'RequestPathSize'   '0x02']
                [const  uint    32  'RequestPath'       '0x01240220']   //Logical Segment: Class(0x20) 0x02, Instance(0x24) 01 (Message Router)
                [simple Services  'data'         ['serviceLen - 6 '] ]
         ]
-        ['0x8A' MultipleServiceResponse
+        ['0x8A' MultipleServiceResponse [uint 16 'serviceLen']
                [reserved   uint    8   '0x0']
                [simple     uint    8   'status']
                [simple     uint    8   'extStatus']
diff --git a/protocols/firmata/src/main/resources/protocols/firmata/firmata.mspec b/protocols/firmata/src/main/resources/protocols/firmata/firmata.mspec
index 20f88ad..17313db 100644
--- a/protocols/firmata/src/main/resources/protocols/firmata/firmata.mspec
+++ b/protocols/firmata/src/main/resources/protocols/firmata/firmata.mspec
@@ -50,7 +50,7 @@
         ]
 
         // Command
-        ['0xF' FirmataMessageCommand
+        ['0xF' FirmataMessageCommand [bit 'response']
             [simple FirmataCommand 'command' ['response']]
         ]
     ]
@@ -59,7 +59,7 @@
 [discriminatedType 'FirmataCommand' [bit 'response']
     [discriminator uint 4 'commandCode']
     [typeSwitch 'commandCode'
-        ['0x0' FirmataCommandSysex
+        ['0x0' FirmataCommandSysex [bit 'response']
             [simple SysexCommand 'command' ['response']]
             [reserved uint 8 '0xF7']
         ]
diff --git a/protocols/s7/src/main/resources/protocols/s7/s7.mspec b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
index e428620..10fbb80 100644
--- a/protocols/s7/src/main/resources/protocols/s7/s7.mspec
+++ b/protocols/s7/src/main/resources/protocols/s7/s7.mspec
@@ -84,7 +84,7 @@
         ['0xC3' COTPParameterChecksum
             [simple uint 8 'crc']
         ]
-        ['0xE0' COTPParameterDisconnectAdditionalInformation
+        ['0xE0' COTPParameterDisconnectAdditionalInformation [uint 8 'rest']
             [array  uint 8 'data' count 'rest']
         ]
     ]
@@ -213,16 +213,16 @@
 
 [discriminatedType 'S7Payload' [uint 8 'messageType', S7Parameter 'parameter']
     [typeSwitch 'parameter.parameterType', 'messageType'
-        ['0x04','0x03' S7PayloadReadVarResponse
+        ['0x04','0x03' S7PayloadReadVarResponse [S7Parameter 'parameter']
             [array S7VarPayloadDataItem 'items' count 'CAST(parameter, S7ParameterReadVarResponse).numItems' ['lastItem']]
         ]
-        ['0x05','0x01' S7PayloadWriteVarRequest
+        ['0x05','0x01' S7PayloadWriteVarRequest [S7Parameter 'parameter']
             [array S7VarPayloadDataItem 'items' count 'COUNT(CAST(parameter, S7ParameterWriteVarRequest).items)' ['lastItem']]
         ]
-        ['0x05','0x03' S7PayloadWriteVarResponse
+        ['0x05','0x03' S7PayloadWriteVarResponse [S7Parameter 'parameter']
             [array S7VarPayloadStatusItem 'items' count 'CAST(parameter, S7ParameterWriteVarResponse).numItems']
         ]
-        ['0x00','0x07' S7PayloadUserData
+        ['0x00','0x07' S7PayloadUserData [S7Parameter 'parameter']
             [array S7PayloadUserDataItem 'items' count 'COUNT(CAST(parameter, S7ParameterUserData).items)' ['CAST(CAST(parameter, S7ParameterUserData).items[0], S7ParameterUserDataItemCPUFunctions).cpuFunctionType']]
         ]
     ]


[plc4x] 01/03: - Changed the code generator to not automatically pass all parent types arguments to the sub-types - Made it possible to reference enum constant properties in mspec

Posted by cd...@apache.org.
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 aa6e15e0f8d58b3fa0c0d24dcd3749e63750ee85
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Aug 1 17:57:13 2020 +0200

    - Changed the code generator to not automatically pass all parent types arguments to the sub-types
    - Made it possible to reference enum constant properties in mspec
---
 .../plc4x/language/java/JavaLanguageTemplateHelper.java       |  4 +++-
 .../src/main/resources/templates/java/io-template.ftlh        |  2 +-
 .../language/mspec/parser/MessageFormatListener.java          | 11 ++---------
 .../apache/plc4x/java/spi/generation/EvaluationHelper.java    |  9 +++++++++
 4 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 4995724..012a676 100644
--- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -444,7 +444,9 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                 VariableLiteral variableLiteral = (VariableLiteral) term;
                 // If this literal references an Enum type, then we have to output it differently.
                 if(getTypeDefinitions().get(variableLiteral.getName()) instanceof EnumTypeDefinition) {
-                    return variableLiteral.getName() + "." + variableLiteral.getChild().getName();
+                    return variableLiteral.getName() + "." + variableLiteral.getChild().getName() +
+                        ((variableLiteral.getChild().getChild() != null) ?
+                            "." + toVariableExpressionRest(variableLiteral.getChild().getChild()) : "");
                 } else {
                     return variableExpressionGenerator.apply(term);
                 }
diff --git a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
index 2098fad..4c5ba3b 100644
--- a/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
+++ b/build-utils/language-java/src/main/resources/templates/java/io-template.ftlh
@@ -163,7 +163,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO<
             for(int curItem = 0; curItem < itemCount; curItem++) {
                 <#-- When parsing simple types, there is nothing that could require the "lastItem" -->
                 <#if !helper.isSimpleTypeReference(arrayField.type)>boolean lastItem = curItem == (itemCount - 1);</#if>
-                ${arrayField.name}[curItem] = <#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parserArgument,  [...]
+                ${arrayField.name}[curItem] = <#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parserArgument,  [...]
             }
         }
         <#-- In all other cases do we have to work with a list, that is later converted to an array -->
diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 45608e4..80e6e53 100644
--- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -343,15 +343,8 @@ public class MessageFormatListener extends MSpecBaseListener {
     public void exitCaseStatement(MSpecParser.CaseStatementContext ctx) {
         String typeName = ctx.name.getText();
         List<Argument> parserArguments = new LinkedList<>();
-        // Add all the arguments from the parent type.
-        if(ctx.parent.parent.parent.parent instanceof MSpecParser.ComplexTypeContext) {
-            if (((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params != null) {
-                parserArguments.addAll(Arrays.asList(getParserArguments(
-                    ((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent.parent).params.argument())));
-            }
-        }
-        // For dataIo there is one level less to navigate.
-        else {
+        // For DataIO types, add all the arguments from the parent type.
+        if(!(ctx.parent.parent.parent.parent instanceof MSpecParser.ComplexTypeContext)) {
             if (((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent).params != null) {
                 parserArguments.addAll(Arrays.asList(getParserArguments(
                     ((MSpecParser.ComplexTypeContext) ctx.parent.parent.parent).params.argument())));
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/EvaluationHelper.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/EvaluationHelper.java
index faef3ed..0b490a5 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/EvaluationHelper.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/EvaluationHelper.java
@@ -22,6 +22,12 @@ package org.apache.plc4x.java.spi.generation;
 public class EvaluationHelper {
 
     public static boolean equals(Object val1, Object val2) {
+        if((val1 == null) && (val2 == null)) {
+            return true;
+        }
+        if((val1 == null) || (val2 == null)){
+            return false;
+        }
         if(val1 instanceof Number && val2 instanceof Number) {
             Number number1 = (Number) val1;
             Number number2 = (Number) val2;
@@ -32,6 +38,9 @@ public class EvaluationHelper {
             Boolean boolean2 = (Boolean) val2;
             return boolean1.equals(boolean2);
         }
+        if(val1.getClass().isEnum() && val2.getClass().isEnum()) {
+            return val1.equals(val2);
+        }
         return false;
     }
 


[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

Posted by cd...@apache.org.
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