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

[incubator-plc4x] branch feature/Beckhoff_ADS_protocol updated: implemented basic ADS Protocol handler

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

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


The following commit(s) were added to refs/heads/feature/Beckhoff_ADS_protocol by this push:
     new da08dbb  implemented basic ADS Protocol handler
da08dbb is described below

commit da08dbbcb75b0b5b5edbc3c1e7a49d297ddf72a9
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Feb 7 14:54:50 2018 +0100

    implemented basic ADS Protocol handler
---
 .../commands/ADSAddDeviceNotificationRequest.java  |   4 +-
 .../commands/ADSAddDeviceNotificationResponse.java |   4 +-
 .../ADSDeleteDeviceNotificationRequest.java        |   4 +-
 .../ADSDeleteDeviceNotificationResponse.java       |   4 +-
 .../api/commands/ADSDeviceNotificationRequest.java |  23 +-
 .../commands/ADSDeviceNotificationResponse.java    |   6 +-
 .../ads/api/commands/ADSReadDeviceInfoRequest.java |   4 +-
 .../api/commands/ADSReadDeviceInfoResponse.java    |   4 +-
 .../java/ads/api/commands/ADSReadRequest.java      |   4 +-
 .../java/ads/api/commands/ADSReadResponse.java     |   4 +-
 .../java/ads/api/commands/ADSReadStateRequest.java |   4 +-
 .../ads/api/commands/ADSReadStateResponse.java     |   4 +-
 .../java/ads/api/commands/ADSReadWriteRequest.java |  16 +-
 .../ads/api/commands/ADSReadWriteResponse.java     |   4 +-
 .../ads/api/commands/ADSWriteControlRequest.java   |   4 +-
 .../ads/api/commands/ADSWriteControlResponse.java  |   4 +-
 .../java/ads/api/commands/ADSWriteRequest.java     |   5 +-
 .../java/ads/api/commands/ADSWriteResponse.java    |   4 +-
 .../{ADSWriteResponse.java => UnknownCommand.java} |  25 +-
 .../ads/api/commands/types/AdsStampHeader.java     |  14 +-
 .../plc4x/java/ads/api/commands/types/Stamps.java  |  13 +
 .../plc4x/java/ads/api/generic/AMSHeader.java      |  42 +++-
 .../plc4x/java/ads/api/generic/AMSTCPHeader.java   |   5 +-
 .../plc4x/java/ads/api/generic/AMSTCPPaket.java    |   4 +-
 .../plc4x/java/ads/api/generic/types/Command.java  |  12 +
 .../plc4x/java/ads/api/generic/types/Invoke.java   |   2 +
 .../plc4x/java/ads/api/generic/types/State.java    |  12 +
 .../apache/plc4x/java/ads/api/util/ByteValue.java  |  16 ++
 .../java/ads/connection/ADSPlcConnection.java      |   2 +
 .../apache/plc4x/java/ads/netty/ADSProtocol.java   | 274 +++++++++++++++++++++
 .../plc4x/java/ads/netty/Plc4XADSProtocol.java     |  19 +-
 .../java/org/apache/plc4x/java/ads/ADSDumper.java  |  15 +-
 32 files changed, 468 insertions(+), 93 deletions(-)

diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationRequest.java
index e160065..5cffbc3 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationRequest.java
@@ -100,12 +100,12 @@ public class ADSAddDeviceNotificationRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Add_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationResponse.java
index 94edd27..48f6fe2 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSAddDeviceNotificationResponse.java
@@ -54,12 +54,12 @@ public class ADSAddDeviceNotificationResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Add_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationRequest.java
index 8d88dc3..a118342 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationRequest.java
@@ -56,12 +56,12 @@ public class ADSDeleteDeviceNotificationRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Delete_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationResponse.java
index 9f68481..4dfeb7a 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeleteDeviceNotificationResponse.java
@@ -47,12 +47,12 @@ public class ADSDeleteDeviceNotificationResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Delete_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationRequest.java
index d29ed2c..6c1eee1 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationRequest.java
@@ -26,6 +26,9 @@ import org.apache.plc4x.java.ads.api.generic.AMSHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.ads.api.generic.types.*;
+import org.apache.plc4x.java.ads.api.util.ByteReadable;
+
+import java.util.List;
 
 /**
  * Data will carry forward independently from an ADS device to a Client
@@ -45,41 +48,41 @@ public class ADSDeviceNotificationRequest extends AMSTCPPaket {
     /**
      * n bytes	Array with elements of type AdsStampHeader.
      */
-    private final AdsStampHeader adsStampHeader;
+    private final List<AdsStampHeader> adsStampHeaders;
 
-    public ADSDeviceNotificationRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Length length, Stamps stamps, AdsStampHeader adsStampHeader) {
+    public ADSDeviceNotificationRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(amstcpHeader, amsHeader);
         this.length = length;
         this.stamps = stamps;
-        this.adsStampHeader = adsStampHeader;
+        this.adsStampHeaders = adsStampHeaders;
     }
 
-    public ADSDeviceNotificationRequest(AMSHeader amsHeader, Length length, Stamps stamps, AdsStampHeader adsStampHeader) {
+    public ADSDeviceNotificationRequest(AMSHeader amsHeader, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(amsHeader);
         this.length = length;
         this.stamps = stamps;
-        this.adsStampHeader = adsStampHeader;
+        this.adsStampHeaders = adsStampHeaders;
     }
 
-    public ADSDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Length length, Stamps stamps, AdsStampHeader adsStampHeader) {
+    public ADSDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
         this.length = length;
         this.stamps = stamps;
-        this.adsStampHeader = adsStampHeader;
+        this.adsStampHeaders = adsStampHeaders;
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(length, stamps, adsStampHeader);
+        return buildADSData(length, stamps, buildADSData(adsStampHeaders.toArray(new ByteReadable[adsStampHeaders.size()])));
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationResponse.java
index 55c50a0..4593dca 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationResponse.java
@@ -28,7 +28,7 @@ import org.apache.plc4x.java.ads.api.generic.types.State;
  */
 public class ADSDeviceNotificationResponse extends AMSTCPPaket {
 
-    private ADSDeviceNotificationResponse() {
+    public ADSDeviceNotificationResponse() {
         super(null, null);
         // There is no {@link ADSDeviceNotificationResponse} specified
     }
@@ -39,12 +39,12 @@ public class ADSDeviceNotificationResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Device_Notification;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoRequest.java
index af8252d..8d79896 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoRequest.java
@@ -48,12 +48,12 @@ public class ADSReadDeviceInfoRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_Device_Info;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoResponse.java
index ea345bf..de4037d 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadDeviceInfoResponse.java
@@ -66,12 +66,12 @@ public class ADSReadDeviceInfoResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_Device_Info;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadRequest.java
index 801164b..356664c 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadRequest.java
@@ -74,12 +74,12 @@ public class ADSReadRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
index 8877ef2..799e03a 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadResponse.java
@@ -59,12 +59,12 @@ public class ADSReadResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateRequest.java
index 600f5c4..09f21d4 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateRequest.java
@@ -48,12 +48,12 @@ public class ADSReadStateRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_State;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateResponse.java
index 27cc405..8068a99 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadStateResponse.java
@@ -47,12 +47,12 @@ public class ADSReadStateResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_State;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteRequest.java
index 4a59dda..9142b61 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteRequest.java
@@ -18,16 +18,12 @@
  */
 package org.apache.plc4x.java.ads.api.commands;
 
-import org.apache.plc4x.java.ads.api.commands.types.IndexGroup;
-import org.apache.plc4x.java.ads.api.commands.types.IndexOffset;
-import org.apache.plc4x.java.ads.api.commands.types.ReadLength;
-import org.apache.plc4x.java.ads.api.commands.types.WriteLength;
+import org.apache.plc4x.java.ads.api.commands.types.*;
 import org.apache.plc4x.java.ads.api.generic.ADSData;
 import org.apache.plc4x.java.ads.api.generic.AMSHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.ads.api.generic.types.*;
-import org.apache.plc4x.java.ads.api.util.ByteValue;
 
 /**
  * With ADS Read Write data will be written to an ADS device. Additionally, data can be read from the ADS device.
@@ -89,19 +85,13 @@ public class ADSReadWriteRequest extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    public static class Data extends ByteValue {
-        public Data(byte... value) {
-            super(value);
-        }
-    }
-
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_Write;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteResponse.java
index 0c6ad3e..213135a 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSReadWriteResponse.java
@@ -61,12 +61,12 @@ public class ADSReadWriteResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Read_Write;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlRequest.java
index e81a510..0ff8e7e 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlRequest.java
@@ -82,12 +82,12 @@ public class ADSWriteControlRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Write_Control;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlResponse.java
index 4f8b111..439a602 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteControlResponse.java
@@ -46,12 +46,12 @@ public class ADSWriteControlResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Write_Control;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteRequest.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteRequest.java
index 888f17e..d2512e1 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteRequest.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteRequest.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.ads.api.commands;
 import org.apache.plc4x.java.ads.api.commands.types.Data;
 import org.apache.plc4x.java.ads.api.commands.types.IndexGroup;
 import org.apache.plc4x.java.ads.api.commands.types.IndexOffset;
+import org.apache.plc4x.java.ads.api.commands.types.Length;
 import org.apache.plc4x.java.ads.api.generic.ADSData;
 import org.apache.plc4x.java.ads.api.generic.AMSHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
@@ -79,12 +80,12 @@ public class ADSWriteRequest extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Write;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_REQUEST_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
index 84db899..e852588 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
@@ -47,12 +47,12 @@ public class ADSWriteResponse extends AMSTCPPaket {
     }
 
     @Override
-    public Command getCommandId() {
+    protected Command getCommandId() {
         return Command.ADS_Write;
     }
 
     @Override
-    public State getStateId() {
+    protected State getStateId() {
         return State.ADS_RESPONSE_TCP;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
similarity index 70%
copy from plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
copy to plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
index 84db899..c87ad4b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSWriteResponse.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
@@ -18,7 +18,7 @@
  */
 package org.apache.plc4x.java.ads.api.commands;
 
-import org.apache.plc4x.java.ads.api.commands.types.Result;
+import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.generic.ADSData;
 import org.apache.plc4x.java.ads.api.generic.AMSHeader;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
@@ -27,32 +27,29 @@ import org.apache.plc4x.java.ads.api.generic.types.Command;
 import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
- * With ADS Write data can be written to an ADS device.
+ * Unknown ADS Package
  */
-public class ADSWriteResponse extends AMSTCPPaket {
+public class UnknownCommand extends AMSTCPPaket {
 
-    /**
-     * 4 bytes	ADS error number
-     */
-    private final Result result;
+    final ByteBuf remainingBytes;
 
-    public ADSWriteResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
+    public UnknownCommand(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, ByteBuf remainingBytes) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
+        this.remainingBytes = remainingBytes;
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(result);
+        return () -> remainingBytes;
     }
 
     @Override
-    public Command getCommandId() {
-        return Command.ADS_Write;
+    protected Command getCommandId() {
+        return Command.UNKNOWN;
     }
 
     @Override
-    public State getStateId() {
-        return State.ADS_RESPONSE_TCP;
+    protected State getStateId() {
+        return State.UNKNOWN;
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsStampHeader.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsStampHeader.java
index f12d8cc..c282df7 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsStampHeader.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsStampHeader.java
@@ -21,6 +21,8 @@ package org.apache.plc4x.java.ads.api.commands.types;
 import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
+import java.util.List;
+
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
 public class AdsStampHeader implements ByteReadable {
@@ -36,20 +38,20 @@ public class AdsStampHeader implements ByteReadable {
     /**
      * n bytes	Array with elements of type AdsNotificationSample.
      */
-    private final AdsNotificationSample adsNotificationSample;
+    private final List<AdsNotificationSample> adsNotificationSamples;
 
-    AdsStampHeader(TimeStamp timeStamp, Samples samples, AdsNotificationSample adsNotificationSample) {
+    AdsStampHeader(TimeStamp timeStamp, Samples samples, List<AdsNotificationSample> adsNotificationSamples) {
         this.timeStamp = timeStamp;
         this.samples = samples;
-        this.adsNotificationSample = adsNotificationSample;
+        this.adsNotificationSamples = adsNotificationSamples;
     }
 
-    public static AdsStampHeader of(TimeStamp timeStamp, Samples samples, AdsNotificationSample adsNotificationSample) {
-        return new AdsStampHeader(timeStamp, samples, adsNotificationSample);
+    public static AdsStampHeader of(TimeStamp timeStamp, Samples samples, List<AdsNotificationSample> adsNotificationSamples) {
+        return new AdsStampHeader(timeStamp, samples, adsNotificationSamples);
     }
 
     @Override
     public ByteBuf getByteBuf() {
-        return buildByteBuff(timeStamp, samples, adsNotificationSample);
+        return buildByteBuff(timeStamp, samples, () -> buildByteBuff(adsNotificationSamples.toArray(new ByteReadable[adsNotificationSamples.size()])));
     }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Stamps.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Stamps.java
index 7b39ee1..475ef3c 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Stamps.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/Stamps.java
@@ -20,6 +20,8 @@ package org.apache.plc4x.java.ads.api.commands.types;
 
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 
+import java.nio.ByteBuffer;
+
 public class Stamps extends ByteValue {
 
     public static final int NUM_BYTES = 4;
@@ -29,6 +31,17 @@ public class Stamps extends ByteValue {
         assertLength(NUM_BYTES);
     }
 
+    public static Stamps of(long length) {
+        checkUnsignedBounds(length, NUM_BYTES);
+        return new Stamps(ByteBuffer.allocate(NUM_BYTES)
+            // LE
+            .put((byte) (length & 0xff))
+            .put((byte) (length >> 8 & 0xff))
+            .put((byte) (length >> 16 & 0xff))
+            .put((byte) (length >> 24 & 0xff))
+            .array());
+    }
+
     public static Stamps of(byte... values) {
         return new Stamps(values);
     }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSHeader.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSHeader.java
index f08548d..ef5a1fb 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSHeader.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSHeader.java
@@ -67,7 +67,7 @@ public class AMSHeader implements ByteReadable {
      */
     protected final Invoke invokeId;
 
-    public AMSHeader(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateFlags, DataLength dataLength, AMSError code, Invoke invokeId) {
+    protected AMSHeader(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateFlags, DataLength dataLength, AMSError code, Invoke invokeId) {
         this.targetAmsNetId = targetAmsNetId;
         this.targetAmsPort = targetAmsPort;
         this.sourceAmsNetId = sourceAmsNetId;
@@ -79,6 +79,10 @@ public class AMSHeader implements ByteReadable {
         this.invokeId = invokeId;
     }
 
+    public static AMSHeader of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateFlags, DataLength dataLength, AMSError code, Invoke invokeId) {
+        return new AMSHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateFlags, dataLength, code, invokeId);
+    }
+
     @Override
     public ByteBuf getByteBuf() {
         return buildByteBuff(
@@ -92,4 +96,40 @@ public class AMSHeader implements ByteReadable {
             code,
             invokeId);
     }
+
+    public AMSNetId getTargetAmsNetId() {
+        return targetAmsNetId;
+    }
+
+    public AMSPort getTargetAmsPort() {
+        return targetAmsPort;
+    }
+
+    public AMSNetId getSourceAmsNetId() {
+        return sourceAmsNetId;
+    }
+
+    public AMSPort getSourceAmsPort() {
+        return sourceAmsPort;
+    }
+
+    public Command getCommandId() {
+        return commandId;
+    }
+
+    public State getStateFlags() {
+        return stateFlags;
+    }
+
+    public DataLength getDataLength() {
+        return dataLength;
+    }
+
+    public AMSError getCode() {
+        return code;
+    }
+
+    public Invoke getInvokeId() {
+        return invokeId;
+    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPHeader.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPHeader.java
index 2df6ab1..83bb944 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPHeader.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPHeader.java
@@ -39,7 +39,7 @@ public class AMSTCPHeader implements ByteReadable {
         this.length = length;
     }
 
-    public static AMSTCPHeader of(int length) {
+    public static AMSTCPHeader of(long length) {
         return new AMSTCPHeader(Length.of(length));
     }
 
@@ -62,4 +62,7 @@ public class AMSTCPHeader implements ByteReadable {
         }
     }
 
+    public Length getLengthValue() {
+        return length;
+    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
index 1b14eb9..036e23b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/AMSTCPPaket.java
@@ -66,9 +66,9 @@ public abstract class AMSTCPPaket implements ByteReadable {
 
     public abstract ADSData getAdsData();
 
-    public abstract Command getCommandId();
+    protected abstract Command getCommandId();
 
-    public abstract State getStateId();
+    protected abstract State getStateId();
 
     @Override
     public ByteBuf getByteBuf() {
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Command.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Command.java
index b5b8da2..609939b 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Command.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Command.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.ads.api.util.ByteReadable;
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 
 public enum Command implements ByteReadable {
     Invalid(0x00),
@@ -73,4 +74,15 @@ public enum Command implements ByteReadable {
         }
         return Unpooled.buffer().writeBytes(value);
     }
+
+    // TODO: improve by accepting int
+    public static Command of(byte... bytes) {
+        // TODO: improve by using a map
+        for (Command command : values()) {
+            if (Arrays.equals(bytes, command.value)) {
+                return command;
+            }
+        }
+        return UNKNOWN;
+    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Invoke.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Invoke.java
index ea3e070..fb60c07 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Invoke.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/Invoke.java
@@ -24,6 +24,8 @@ public class Invoke extends ByteValue {
 
     public static final int NUM_BYTES = 4;
 
+    public static final Invoke NONE = of((byte) 0, (byte) 0, (byte) 0, (byte) 0);
+
     Invoke(byte... values) {
         super(values);
         assertLength(NUM_BYTES);
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/State.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/State.java
index 47fbb40..4505e7c 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/State.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/types/State.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.ads.api.util.ByteReadable;
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 
 /**
  * 2 bytes	see below.
@@ -79,4 +80,15 @@ public enum State implements ByteReadable {
         }
         return Unpooled.buffer().writeBytes(value);
     }
+
+    // TODO: improve by accepting int
+    public static State of(byte... bytes) {
+        // TODO: improve by using a map
+        for (State command : values()) {
+            if (Arrays.equals(bytes, command.value)) {
+                return command;
+            }
+        }
+        return UNKNOWN;
+    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteValue.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteValue.java
index e500b6f..bce6456 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteValue.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/util/ByteValue.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.ads.api.util;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 public class ByteValue implements ByteReadable {
@@ -54,4 +55,19 @@ public class ByteValue implements ByteReadable {
     public ByteBuf getByteBuf() {
         return Unpooled.buffer().writeBytes(value);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ByteValue byteValue = (ByteValue) o;
+
+        return Arrays.equals(value, byteValue.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(value);
+    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/ADSPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/ADSPlcConnection.java
index 40d7a0a..dde99d9 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/ADSPlcConnection.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/ADSPlcConnection.java
@@ -25,6 +25,7 @@ import io.netty.channel.socket.nio.NioSocketChannel;
 import org.apache.plc4x.java.ads.api.generic.types.AMSNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
 import org.apache.plc4x.java.ads.model.ADSAddress;
+import org.apache.plc4x.java.ads.netty.ADSProtocol;
 import org.apache.plc4x.java.ads.netty.Plc4XADSProtocol;
 import org.apache.plc4x.java.api.connection.AbstractPlcConnection;
 import org.apache.plc4x.java.api.connection.PlcReader;
@@ -119,6 +120,7 @@ public class ADSPlcConnection extends AbstractPlcConnection implements PlcReader
                     // Build the protocol stack for communicating with the ads protocol.
                     ChannelPipeline pipeline = channel.pipeline();
                     pipeline.addLast(new Plc4XADSProtocol());
+                    pipeline.addLast(new ADSProtocol());
                 }
             });
             // Start the client.
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
new file mode 100644
index 0000000..a5e7227
--- /dev/null
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/ADSProtocol.java
@@ -0,0 +1,274 @@
+/*
+ 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.ads.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageCodec;
+import org.apache.plc4x.java.ads.api.commands.*;
+import org.apache.plc4x.java.ads.api.commands.types.*;
+import org.apache.plc4x.java.ads.api.commands.types.Length;
+import org.apache.plc4x.java.ads.api.generic.AMSHeader;
+import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
+import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
+import org.apache.plc4x.java.ads.api.generic.types.*;
+
+import java.util.*;
+
+public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
+
+    // TODO: better track this a layer above as this here might be useless
+    private Map<Invoke, AMSTCPPaket> requests;
+
+    public ADSProtocol() {
+        this.requests = new HashMap<>();
+    }
+
+    @Override
+    protected void encode(ChannelHandlerContext channelHandlerContext, AMSTCPPaket amstcpPaket, List<Object> out) throws Exception {
+        Invoke invokeId = amstcpPaket.getAmsHeader().getInvokeId();
+        if (invokeId != Invoke.NONE) {
+            requests.put(invokeId, amstcpPaket);
+        }
+        out.add(amstcpPaket.getByteBuf());
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> out) throws Exception {
+        // Reserved
+        byteBuf.skipBytes(2);
+        long packetLength = byteBuf.readUnsignedIntLE();
+        AMSNetId targetAmsNetId = AMSNetId.of(byteBuf.readBytes(6).array());
+        AMSPort targetAmsPort = AMSPort.of(byteBuf.readUnsignedShortLE());
+        AMSNetId sourceAmsNetId = AMSNetId.of(byteBuf.readBytes(6).array());
+        AMSPort sourceAmsPort = AMSPort.of(byteBuf.readUnsignedShortLE());
+        // TODO: could be transformed to readUnsignedShortLE someday
+        Command commandId = Command.of(byteBuf.readBytes(2).array());
+        // TODO: could be transformed to readUnsignedShortLE someday
+        State stateId = State.of(byteBuf.readBytes(2).array());
+        long dataLengthLong = byteBuf.readUnsignedIntLE();
+        DataLength dataLength = DataLength.of(dataLengthLong);
+        AMSError errorCode = AMSError.of(byteBuf.readBytes(4).array());
+        Invoke invoke = Invoke.of(byteBuf.readBytes(4).array());
+        AMSTCPPaket correlatedAmstcpPaket = requests.get(invoke);
+        if (dataLengthLong > Integer.MAX_VALUE) {
+            throw new IllegalStateException("Overflow in datalength: " + dataLengthLong);
+        }
+        ByteBuf commandBuffer = byteBuf.readBytes((int) dataLengthLong);
+        boolean request = false;
+        AMSTCPHeader amstcpHeader = AMSTCPHeader.of(packetLength);
+        AMSHeader amsHeader = AMSHeader.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateId, dataLength, errorCode, invoke);
+        switch (stateId) {
+            case ADS_REQUEST_TCP:
+                request = true;
+                break;
+            case ADS_RESPONSE_TCP:
+                request = false;
+                break;
+            case ADS_REQUEST_UDP:
+                request = true;
+                break;
+            case ADS_RESPONSE_UDP:
+                request = false;
+                break;
+            case UNKNOWN:
+                out.add(new UnknownCommand(amstcpHeader, amsHeader, commandBuffer));
+                return;
+        }
+        switch (commandId) {
+            case Invalid:
+                out.add(new UnknownCommand(amstcpHeader, amsHeader, commandBuffer));
+                break;
+            case ADS_Read_Device_Info:
+                if (request) {
+                    out.add(new ADSReadDeviceInfoRequest(amstcpHeader, amsHeader));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    MajorVersion majorVersion = MajorVersion.of(commandBuffer.readByte());
+                    MinorVersion minorVersion = MinorVersion.of(commandBuffer.readByte());
+                    // TODO: could be transformed to readUnsignedShortLE someday
+                    Version version = Version.of(commandBuffer.readBytes(2).array());
+                    Device device = Device.of(commandBuffer.readBytes(16).array());
+                    out.add(new ADSReadDeviceInfoResponse(amstcpHeader, amsHeader, result, majorVersion, minorVersion, version, device));
+                }
+                break;
+            case ADS_Read:
+                if (request) {
+                    IndexGroup indexGroup = IndexGroup.of(commandBuffer.readBytes(4).array());
+                    IndexOffset indexOffset = IndexOffset.of(commandBuffer.readBytes(4).array());
+                    Length length = Length.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSReadRequest(amstcpHeader, amsHeader, indexGroup, indexOffset, length));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    long adsReadLength = byteBuf.readUnsignedIntLE();
+                    Length length = Length.of(adsReadLength);
+                    if (adsReadLength > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + adsReadLength);
+                    }
+                    Data data = Data.of(commandBuffer.readBytes((int) adsReadLength).array());
+                    out.add(new ADSReadResponse(amstcpHeader, amsHeader, result, length, data));
+                }
+                break;
+            case ADS_Write:
+                if (request) {
+                    IndexGroup indexGroup = IndexGroup.of(commandBuffer.readBytes(4).array());
+                    IndexOffset indexOffset = IndexOffset.of(commandBuffer.readBytes(4).array());
+                    long adsWriteLength = byteBuf.readUnsignedIntLE();
+                    Length length = Length.of(adsWriteLength);
+                    if (adsWriteLength > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + adsWriteLength);
+                    }
+                    Data data = Data.of(commandBuffer.readBytes((int) adsWriteLength).array());
+                    out.add(new ADSWriteRequest(amstcpHeader, amsHeader, indexGroup, indexOffset, length, data));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSWriteResponse(amstcpHeader, amsHeader, result));
+                }
+                break;
+            case ADS_Read_State:
+                if (request) {
+                    out.add(new ADSReadStateRequest(amstcpHeader, amsHeader));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSReadStateResponse(amstcpHeader, amsHeader, result));
+                }
+                break;
+            case ADS_Write_Control:
+                if (request) {
+                    // TODO: could be transformed to readUnsignedShortLE someday
+                    ADSState adsState = ADSState.of(commandBuffer.readBytes(2).array());
+                    // TODO: could be transformed to readUnsignedShortLE someday
+                    DeviceState deviceState = DeviceState.of(commandBuffer.readBytes(2).array());
+                    long adsWriteControlLength = byteBuf.readUnsignedIntLE();
+                    Length length = Length.of(adsWriteControlLength);
+                    if (adsWriteControlLength > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + adsWriteControlLength);
+                    }
+                    Data data = Data.of(commandBuffer.readBytes((int) adsWriteControlLength).array());
+                    out.add(new ADSWriteControlRequest(amstcpHeader, amsHeader, adsState, deviceState, length, data));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSWriteControlResponse(amstcpHeader, amsHeader, result));
+                }
+                break;
+            case ADS_Add_Device_Notification:
+                if (request) {
+                    IndexGroup indexGroup = IndexGroup.of(commandBuffer.readBytes(4).array());
+                    IndexOffset indexOffset = IndexOffset.of(commandBuffer.readBytes(4).array());
+                    Length length = Length.of(commandBuffer.readUnsignedIntLE());
+                    TransmissionMode transmissionMode = TransmissionMode.of(commandBuffer.readBytes(4).array());
+                    MaxDelay maxDelay = MaxDelay.of(commandBuffer.readBytes(4).array());
+                    CycleTime cycleTime = CycleTime.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSAddDeviceNotificationRequest(amstcpHeader, amsHeader, indexGroup, indexOffset, length, transmissionMode, maxDelay, cycleTime));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    NotificationHandle notificationHandle = NotificationHandle.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSAddDeviceNotificationResponse(amstcpHeader, amsHeader, result, notificationHandle));
+                }
+                break;
+            case ADS_Delete_Device_Notification:
+                if (request) {
+                    NotificationHandle notificationHandle = NotificationHandle.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSDeleteDeviceNotificationRequest(amstcpHeader, amsHeader, notificationHandle));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    out.add(new ADSDeleteDeviceNotificationResponse(amstcpHeader, amsHeader, result));
+                }
+                break;
+            case ADS_Device_Notification:
+                if (request) {
+                    long adsDeviceNotificationLength = commandBuffer.readUnsignedIntLE();
+                    Length length = Length.of(adsDeviceNotificationLength);
+                    if (adsDeviceNotificationLength > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + adsDeviceNotificationLength);
+                    }
+                    long numberOfStamps = commandBuffer.readUnsignedIntLE();
+                    Stamps stamps = Stamps.of(numberOfStamps);
+                    if (numberOfStamps > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + numberOfStamps);
+                    }
+                    ByteBuf adsDeviceNotificationBuffer = commandBuffer.readBytes((int) adsDeviceNotificationLength);
+                    List<AdsStampHeader> adsStampHeaders = new ArrayList<>((int) numberOfStamps);
+                    for (int i = 1; i <= numberOfStamps; i++) {
+                        TimeStamp timeStamp = TimeStamp.of(adsDeviceNotificationBuffer.readBytes(8).array());
+                        long numberOfSamples = adsDeviceNotificationBuffer.readUnsignedIntLE();
+                        Samples samples = Samples.of(numberOfSamples);
+
+                        List<AdsNotificationSample> adsNotificationSamples = new LinkedList<>();
+                        for (int j = 1; j <= numberOfSamples; j++) {
+                            NotificationHandle notificationHandle = NotificationHandle.of(adsDeviceNotificationBuffer.readBytes(4).array());
+                            long sampleSizeLong = adsDeviceNotificationBuffer.readUnsignedIntLE();
+                            SampleSize sampleSize = SampleSize.of(sampleSizeLong);
+                            if (sampleSizeLong > Integer.MAX_VALUE) {
+                                throw new IllegalStateException("Overflow in datalength: " + sampleSizeLong);
+                            }
+                            Data data = Data.of(adsDeviceNotificationBuffer.readBytes((int) sampleSizeLong).array());
+                            AdsNotificationSample adsNotificationSample = AdsNotificationSample.of(notificationHandle, sampleSize, data);
+                            adsNotificationSamples.add(adsNotificationSample);
+
+                        }
+                        AdsStampHeader adsStampHeader = AdsStampHeader.of(timeStamp, samples, adsNotificationSamples);
+                        adsStampHeaders.add(adsStampHeader);
+                    }
+                    out.add(new ADSDeviceNotificationRequest(amstcpHeader, amsHeader, length, stamps, adsStampHeaders));
+                } else {
+                    out.add(new UnknownCommand(amstcpHeader, amsHeader, commandBuffer));
+                }
+                break;
+            case ADS_Read_Write:
+                if (request) {
+                    IndexGroup indexGroup = IndexGroup.of(commandBuffer.readBytes(4).array());
+                    IndexOffset indexOffset = IndexOffset.of(commandBuffer.readBytes(4).array());
+                    long readLengthLong = commandBuffer.readUnsignedIntLE();
+                    ReadLength readLength = ReadLength.of(readLengthLong);
+                    if (readLengthLong > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + readLengthLong);
+                    }
+                    long writeLengthLong = commandBuffer.readUnsignedIntLE();
+                    WriteLength writeLength = WriteLength.of(writeLengthLong);
+                    if (writeLengthLong > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + writeLengthLong);
+                    }
+                    if (readLengthLong + writeLengthLong > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + readLengthLong + writeLengthLong);
+                    }
+                    Data data = Data.of(commandBuffer.readBytes((int) (readLengthLong + writeLengthLong)).array());
+                    out.add(new ADSReadWriteRequest(amstcpHeader, amsHeader, indexGroup, indexOffset, readLength, writeLength, data));
+                } else {
+                    Result result = Result.of(commandBuffer.readBytes(4).array());
+                    long adsReadLength = byteBuf.readUnsignedIntLE();
+                    Length length = Length.of(adsReadLength);
+                    if (adsReadLength > Integer.MAX_VALUE) {
+                        throw new IllegalStateException("Overflow in datalength: " + adsReadLength);
+                    }
+                    Data data = Data.of(commandBuffer.readBytes((int) adsReadLength).array());
+                    out.add(new ADSReadWriteResponse(amstcpHeader, amsHeader, result, length, data));
+                }
+                break;
+            case UNKNOWN:
+                out.add(new UnknownCommand(amstcpHeader, amsHeader, commandBuffer));
+        }
+        if (commandBuffer.readableBytes() > 0) {
+            throw new IllegalStateException("Unread bytes left: " + commandBuffer.readableBytes());
+        }
+    }
+
+}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
index 358e33b..5172909 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/netty/Plc4XADSProtocol.java
@@ -18,10 +18,10 @@ under the License.
 */
 package org.apache.plc4x.java.ads.netty;
 
-import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToMessageCodec;
+import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -34,11 +34,11 @@ import org.apache.plc4x.java.api.messages.items.WriteRequestItem;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
-public class Plc4XADSProtocol extends MessageToMessageCodec<ByteBuf, PlcRequestContainer> {
+public class Plc4XADSProtocol extends MessageToMessageCodec<AMSTCPPaket, PlcRequestContainer> {
 
-    private static final AtomicInteger tpduGenerator = new AtomicInteger(1);
+    private static final AtomicLong correlationBuilder = new AtomicLong(1);
 
     private Map<Short, PlcRequestContainer> requests;
 
@@ -56,6 +56,11 @@ public class Plc4XADSProtocol extends MessageToMessageCodec<ByteBuf, PlcRequestC
         }
     }
 
+    @Override
+    protected void decode(ChannelHandlerContext channelHandlerContext, AMSTCPPaket amstcpPaket, List<Object> out) throws Exception {
+
+    }
+
     private void encodeWriteRequest(PlcRequestContainer msg, List<Object> out) throws PlcException {
         PlcWriteRequest writeRequest = (PlcWriteRequest) msg.getRequest();
         if (writeRequest.getRequestItems().size() != 1) {
@@ -76,10 +81,4 @@ public class Plc4XADSProtocol extends MessageToMessageCodec<ByteBuf, PlcRequestC
         out.add(Unpooled.buffer());
     }
 
-    @SuppressWarnings("unchecked")
-    @Override
-    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
-
-    }
-
 }
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ADSDumper.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ADSDumper.java
index 176f5b8..c0da0f4 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ADSDumper.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/ADSDumper.java
@@ -26,6 +26,7 @@ import org.apache.plc4x.java.ads.api.generic.types.AMSNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
 import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 import org.apache.plc4x.java.ads.api.generic.types.Length;
+import org.apache.plc4x.java.ads.util.TcpHexDumper;
 import org.pcap4j.core.PcapDumper;
 import org.pcap4j.core.PcapHandle;
 import org.pcap4j.core.Pcaps;
@@ -37,8 +38,10 @@ import org.slf4j.LoggerFactory;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.Socket;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
 
 public class ADSDumper {
 
@@ -50,19 +53,25 @@ public class ADSDumper {
         try (PcapHandle handle = Pcaps.openDead(DataLinkType.EN10MB, 65536);
              PcapDumper dumper = handle.dumpOpen(dumpFile.toAbsolutePath().toString())) {
 
+            String crhit= "Hallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine NachrichtHallo Christoph das ist eine Nachricht";
+
             ADSWriteRequest adsWriteRequest = new ADSWriteRequest(
                 AMSNetId.of("192.168.0.70.1.2"),
                 AMSPort.of(12),
                 AMSNetId.of("192.168.0.70.1.1"),
                 AMSPort.of(14),
                 Invoke.of((byte) 0, (byte) 0, (byte) 0, (byte) 0),
-                org.apache.plc4x.java.ads.api.generic.types.Data.of((byte) 0),
                 IndexGroup.of((byte) 0, (byte) 0, (byte) 0, (byte) 0),
                 IndexOffset.of((byte) 0, (byte) 0, (byte) 0, (byte) 0),
-                Length.of(1),
-                Data.of((byte) 0x42)
+                Length.of(crhit.getBytes().length),
+                Data.of(crhit.getBytes())
             );
 
+            try (TcpHexDumper tcpHexDumper = TcpHexDumper.runOn(55862); Socket localhost = new Socket("localhost", tcpHexDumper.getPort())) {
+                localhost.getOutputStream().write(adsWriteRequest.getBytes());
+                TimeUnit.SECONDS.sleep(30);
+            }
+
             UnknownPacket.Builder amsPacket = new UnknownPacket.Builder();
             amsPacket.rawData(adsWriteRequest.getBytes());
 

-- 
To stop receiving notification emails like this one, please contact
sruehl@apache.org.