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 20:10:23 UTC

[incubator-plc4x] branch feature/Beckhoff_ADS_protocol updated: fixed state mask and simplified generated requests.

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 2cd0c2c  fixed state mask and simplified generated requests.
2cd0c2c is described below

commit 2cd0c2c0ffb410c352c1bf85f19f9a6c8ce69404
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed Feb 7 21:10:15 2018 +0100

    fixed state mask and simplified generated requests.
---
 .../commands/ADSAddDeviceNotificationRequest.java  |  17 +-
 .../commands/ADSAddDeviceNotificationResponse.java |  11 +-
 ...tificationResponse.java => ADSCommandType.java} |  35 +---
 .../ADSDeleteDeviceNotificationRequest.java        |  15 +-
 .../ADSDeleteDeviceNotificationResponse.java       |  11 +-
 .../api/commands/ADSDeviceNotificationRequest.java |  15 +-
 .../commands/ADSDeviceNotificationResponse.java    |  11 +-
 .../ads/api/commands/ADSReadDeviceInfoRequest.java |  15 +-
 .../api/commands/ADSReadDeviceInfoResponse.java    |  11 +-
 .../java/ads/api/commands/ADSReadRequest.java      |  15 +-
 .../java/ads/api/commands/ADSReadResponse.java     |  11 +-
 .../java/ads/api/commands/ADSReadStateRequest.java |  15 +-
 .../ads/api/commands/ADSReadStateResponse.java     |  11 +-
 .../java/ads/api/commands/ADSReadWriteRequest.java |  15 +-
 .../ads/api/commands/ADSReadWriteResponse.java     |  11 +-
 .../ads/api/commands/ADSWriteControlRequest.java   |  15 +-
 .../ads/api/commands/ADSWriteControlResponse.java  |  11 +-
 .../java/ads/api/commands/ADSWriteRequest.java     |  16 +-
 .../java/ads/api/commands/ADSWriteResponse.java    |  11 +-
 .../java/ads/api/commands/UnknownCommand.java      |  11 +-
 .../plc4x/java/ads/api/generic/AMSTCPPaket.java    |  12 +-
 .../generic/calculated/CalculatedAMSHeader.java    |  18 +-
 .../plc4x/java/ads/api/generic/types/State.java    | 206 ++++++++++++++-------
 .../apache/plc4x/java/ads/netty/ADSProtocol.java   |  36 +---
 .../java/org/apache/plc4x/java/ads/ADSDumper.java  |   2 -
 .../apache/plc4x/java/ads/util/TcpHexDumper.java   |   9 +-
 26 files changed, 229 insertions(+), 337 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 5cffbc3..3c9b6da 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
@@ -19,12 +19,14 @@
 package 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.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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 
 /**
@@ -33,6 +35,7 @@ import org.apache.plc4x.java.ads.api.util.ByteValue;
  * Note: We recommend to announce not more then 550 notifications per device.
  * You can increase the payload by organizing the data in structures.
  */
+@ADSCommandType(Command.ADS_Add_Device_Notification)
 public class ADSAddDeviceNotificationRequest extends AMSTCPPaket {
 
     /**
@@ -99,16 +102,6 @@ public class ADSAddDeviceNotificationRequest extends AMSTCPPaket {
         return buildADSData(indexGroup, indexOffset, length, transmissionMode, maxDelay, cycleTime, reserved);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Add_Device_Notification;
-    }
-
-    @Override
-    protected State getStateId() {
-        return State.ADS_REQUEST_TCP;
-    }
-
     public static class Reserved extends ByteValue {
 
         private static final Reserved INSTANCE = new Reserved();
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 48f6fe2..27f3cf6 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
@@ -25,11 +25,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * A notification is created in an ADS device.
  */
+@ADSCommandType(Command.ADS_Add_Device_Notification)
 public class ADSAddDeviceNotificationResponse extends AMSTCPPaket {
 
     /**
@@ -53,13 +53,4 @@ public class ADSAddDeviceNotificationResponse extends AMSTCPPaket {
         return buildADSData(result, notificationHandle);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Add_Device_Notification;
-    }
-
-    @Override
-    protected State getStateId() {
-        return State.ADS_RESPONSE_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/ADSCommandType.java
similarity index 54%
copy from plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSDeviceNotificationResponse.java
copy to plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/ADSCommandType.java
index 4593dca..ec53fae 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/ADSCommandType.java
@@ -18,33 +18,18 @@
  */
 package org.apache.plc4x.java.ads.api.commands;
 
-import org.apache.plc4x.java.ads.api.generic.ADSData;
-import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.ads.api.generic.types.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
- * Data will carry forward independently from an ADS device to a Client
+ * Annotates a ADS command with the according command type flag.
  */
-public class ADSDeviceNotificationResponse extends AMSTCPPaket {
-
-    public ADSDeviceNotificationResponse() {
-        super(null, null);
-        // There is no {@link ADSDeviceNotificationResponse} specified
-    }
-
-    @Override
-    public ADSData getAdsData() {
-        return ADSData.EMPTY;
-    }
-
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Device_Notification;
-    }
-
-    @Override
-    protected State getStateId() {
-        return State.ADS_RESPONSE_TCP;
-    }
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface ADSCommandType {
+    Command value();
 }
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 a118342..1449f48 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
@@ -23,11 +23,15 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * One before defined notification is deleted in an ADS device.
  */
+@ADSCommandType(Command.ADS_Delete_Device_Notification)
 public class ADSDeleteDeviceNotificationRequest extends AMSTCPPaket {
 
     /**
@@ -55,13 +59,4 @@ public class ADSDeleteDeviceNotificationRequest extends AMSTCPPaket {
         return buildADSData(notificationHandle);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Delete_Device_Notification;
-    }
-
-    @Override
-    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 4dfeb7a..8aab12f 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
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * One before defined notification is deleted in an ADS device.
  */
+@ADSCommandType(Command.ADS_Delete_Device_Notification)
 public class ADSDeleteDeviceNotificationResponse extends AMSTCPPaket {
 
     /**
@@ -46,13 +46,4 @@ public class ADSDeleteDeviceNotificationResponse extends AMSTCPPaket {
         return buildADSData(result);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Delete_Device_Notification;
-    }
-
-    @Override
-    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 6c1eee1..fb12fe0 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
@@ -25,7 +25,10 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
 import java.util.List;
@@ -35,6 +38,7 @@ import java.util.List;
  * <p>
  * The data which are transfered at the Device Notification  are multiple nested into one another. The Notification Stream contains an array with elements of type AdsStampHeader. This array again contains elements of type AdsNotificationSample.
  */
+@ADSCommandType(Command.ADS_Device_Notification)
 public class ADSDeviceNotificationRequest extends AMSTCPPaket {
 
     /**
@@ -76,13 +80,4 @@ public class ADSDeviceNotificationRequest extends AMSTCPPaket {
         return buildADSData(length, stamps, buildADSData(adsStampHeaders.toArray(new ByteReadable[adsStampHeaders.size()])));
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Device_Notification;
-    }
-
-    @Override
-    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 4593dca..bfae33d 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
@@ -21,11 +21,11 @@ package org.apache.plc4x.java.ads.api.commands;
 import org.apache.plc4x.java.ads.api.generic.ADSData;
 import org.apache.plc4x.java.ads.api.generic.AMSTCPPaket;
 import org.apache.plc4x.java.ads.api.generic.types.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * Data will carry forward independently from an ADS device to a Client
  */
+@ADSCommandType(Command.ADS_Device_Notification)
 public class ADSDeviceNotificationResponse extends AMSTCPPaket {
 
     public ADSDeviceNotificationResponse() {
@@ -38,13 +38,4 @@ public class ADSDeviceNotificationResponse extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Device_Notification;
-    }
-
-    @Override
-    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 8d79896..5d40389 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
@@ -22,13 +22,17 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * Reads the name and the version number of the ADS device.
  * <p>
  * No additional data required
  */
+@ADSCommandType(Command.ADS_Read_Device_Info)
 public class ADSReadDeviceInfoRequest extends AMSTCPPaket {
     public ADSReadDeviceInfoRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader) {
         super(amstcpHeader, amsHeader);
@@ -47,13 +51,4 @@ public class ADSReadDeviceInfoRequest extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_Device_Info;
-    }
-
-    @Override
-    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 de4037d..e2daa2a 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
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * Reads the name and the version number of the ADS device.
  */
+@ADSCommandType(Command.ADS_Read_Device_Info)
 public class ADSReadDeviceInfoResponse extends AMSTCPPaket {
     /**
      * 4 bytes	ADS error number.
@@ -65,13 +65,4 @@ public class ADSReadDeviceInfoResponse extends AMSTCPPaket {
         return buildADSData(result, majorVersion, minorVersion, version, device);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_Device_Info;
-    }
-
-    @Override
-    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 356664c..1635929 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
@@ -25,11 +25,15 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * With ADS Read data can be read from an ADS device.  The data are addressed by the Index Group and the Index Offset
  */
+@ADSCommandType(Command.ADS_Read)
 public class ADSReadRequest extends AMSTCPPaket {
 
     /**
@@ -73,13 +77,4 @@ public class ADSReadRequest extends AMSTCPPaket {
         return buildADSData(indexGroup, indexOffset, length);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read;
-    }
-
-    @Override
-    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 799e03a..7bc9b2a 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
@@ -26,11 +26,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * With ADS Read data can be read from an ADS device
  */
+@ADSCommandType(Command.ADS_Read)
 public class ADSReadResponse extends AMSTCPPaket {
 
     /**
@@ -58,13 +58,4 @@ public class ADSReadResponse extends AMSTCPPaket {
         return buildADSData(result, length, data);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read;
-    }
-
-    @Override
-    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 09f21d4..85853d8 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
@@ -22,13 +22,17 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * Reads the ADS status and the device status of an ADS device.
  * <p>
  * No additional data required
  */
+@ADSCommandType(Command.ADS_Read_State)
 public class ADSReadStateRequest extends AMSTCPPaket {
     public ADSReadStateRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader) {
         super(amstcpHeader, amsHeader);
@@ -47,13 +51,4 @@ public class ADSReadStateRequest extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_State;
-    }
-
-    @Override
-    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 8068a99..2cb725a 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
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * Reads the ADS status and the device status of an ADS device.
  */
+@ADSCommandType(Command.ADS_Read_State)
 public class ADSReadStateResponse extends AMSTCPPaket {
 
     /**
@@ -46,13 +46,4 @@ public class ADSReadStateResponse extends AMSTCPPaket {
         return buildADSData(result);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_State;
-    }
-
-    @Override
-    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 9142b61..70c8ab9 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
@@ -23,13 +23,17 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * With ADS Read Write data will be written to an ADS device. Additionally, data can be read from the ADS device.
  * <p>
  * The data which can be read are addressed by the Index Group and the Index Offset
  */
+@ADSCommandType(Command.ADS_Read_Write)
 public class ADSReadWriteRequest extends AMSTCPPaket {
 
     /**
@@ -85,13 +89,4 @@ public class ADSReadWriteRequest extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_Write;
-    }
-
-    @Override
-    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 213135a..769c073 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
@@ -26,11 +26,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * With ADS Read Write data will be written to an ADS device. Additionally, data can be read from the ADS device.
  */
+@ADSCommandType(Command.ADS_Read_Write)
 public class ADSReadWriteResponse extends AMSTCPPaket {
 
     /**
@@ -60,13 +60,4 @@ public class ADSReadWriteResponse extends AMSTCPPaket {
         return ADSData.EMPTY;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Read_Write;
-    }
-
-    @Override
-    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 0ff8e7e..8393cd6 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
@@ -26,13 +26,17 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * Changes the ADS status and the device status of an ADS device.
  * Additionally it is possible to send data to the ADS device to transfer further information.
  * These data were not analysed from the current ADS devices (PLC, NC, ...)
  */
+@ADSCommandType(Command.ADS_Write_Control)
 public class ADSWriteControlRequest extends AMSTCPPaket {
 
     /**
@@ -81,13 +85,4 @@ public class ADSWriteControlRequest extends AMSTCPPaket {
         return buildADSData(adsState, deviceState, length, data);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Write_Control;
-    }
-
-    @Override
-    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 439a602..488adfe 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
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * Changes the ADS status and the device status of an ADS device.
  */
+@ADSCommandType(Command.ADS_Write_Control)
 public class ADSWriteControlResponse extends AMSTCPPaket {
     /**
      * 4 bytes	ADS error number
@@ -45,13 +45,4 @@ public class ADSWriteControlResponse extends AMSTCPPaket {
         return buildADSData(result);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Write_Control;
-    }
-
-    @Override
-    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 d2512e1..b7c0dea 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
@@ -26,11 +26,15 @@ 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.generic.types.AMSNetId;
+import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
+import org.apache.plc4x.java.ads.api.generic.types.Command;
+import org.apache.plc4x.java.ads.api.generic.types.Invoke;
 
 /**
  * With ADS Write data can be written to an ADS device. The data are addressed by the Index Group and the Index Offset.
  */
+@ADSCommandType(Command.ADS_Write)
 public class ADSWriteRequest extends AMSTCPPaket {
 
     /**
@@ -78,14 +82,4 @@ public class ADSWriteRequest extends AMSTCPPaket {
     public ADSData getAdsData() {
         return buildADSData(indexGroup, indexOffset, length, data);
     }
-
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Write;
-    }
-
-    @Override
-    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 e852588..a9c4188 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
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * With ADS Write data can be written to an ADS device.
  */
+@ADSCommandType(Command.ADS_Write)
 public class ADSWriteResponse extends AMSTCPPaket {
 
     /**
@@ -46,13 +46,4 @@ public class ADSWriteResponse extends AMSTCPPaket {
         return buildADSData(result);
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.ADS_Write;
-    }
-
-    @Override
-    protected State getStateId() {
-        return State.ADS_RESPONSE_TCP;
-    }
 }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
index c87ad4b..a959d5e 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/UnknownCommand.java
@@ -24,11 +24,11 @@ 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.Command;
-import org.apache.plc4x.java.ads.api.generic.types.State;
 
 /**
  * Unknown ADS Package
  */
+@ADSCommandType(Command.UNKNOWN)
 public class UnknownCommand extends AMSTCPPaket {
 
     final ByteBuf remainingBytes;
@@ -43,13 +43,4 @@ public class UnknownCommand extends AMSTCPPaket {
         return () -> remainingBytes;
     }
 
-    @Override
-    protected Command getCommandId() {
-        return Command.UNKNOWN;
-    }
-
-    @Override
-    protected State getStateId() {
-        return State.UNKNOWN;
-    }
 }
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 036e23b..933e4af 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
@@ -19,6 +19,7 @@
 package org.apache.plc4x.java.ads.api.generic;
 
 import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.ads.api.commands.ADSCommandType;
 import org.apache.plc4x.java.ads.api.generic.calculated.CalculatedAMSHeader;
 import org.apache.plc4x.java.ads.api.generic.calculated.CalculatedAMSTCPHeader;
 import org.apache.plc4x.java.ads.api.generic.types.*;
@@ -44,13 +45,16 @@ public abstract class AMSTCPPaket implements ByteReadable {
     }
 
     public AMSTCPPaket(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId) {
+        if (!getClass().isAnnotationPresent(ADSCommandType.class)) {
+            throw new IllegalArgumentException(ADSCommandType.class + " need to be present.");
+        }
         this.amsHeader = CalculatedAMSHeader.of(
             targetAmsNetId,
             targetAmsPort,
             sourceAmsNetId,
             sourceAmsPort,
-            this::getCommandId,
-            this::getStateId,
+            getClass().getAnnotation(ADSCommandType.class).value(),
+            State.DEFAULT,
             () -> DataLength.of(getAdsData().getLength()),
             invokeId);
         this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> getAdsData().getLength());
@@ -66,10 +70,6 @@ public abstract class AMSTCPPaket implements ByteReadable {
 
     public abstract ADSData getAdsData();
 
-    protected abstract Command getCommandId();
-
-    protected abstract State getStateId();
-
     @Override
     public ByteBuf getByteBuf() {
         return buildByteBuff(amstcpHeader, amsHeader, getAdsData());
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSHeader.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSHeader.java
index 0f6eea9..65fb6f7 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSHeader.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSHeader.java
@@ -26,21 +26,15 @@ import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff
 
 public class CalculatedAMSHeader extends AMSHeader {
 
-    protected final CommandIdSupplier commandIdSupplier;
-
-    protected final StateIdSupplier stateIdSupplier;
-
     protected final LengthSupplier lengthSupplier;
 
-    protected CalculatedAMSHeader(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, CommandIdSupplier commandIdSupplier, StateIdSupplier stateIdSupplier, LengthSupplier lengthSupplier, Invoke invokeId) {
-        super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, null, null, null, AMSError.NONE, invokeId);
-        this.commandIdSupplier = commandIdSupplier;
-        this.stateIdSupplier = stateIdSupplier;
+    protected CalculatedAMSHeader(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateId, LengthSupplier lengthSupplier, Invoke invokeId) {
+        super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateId, null, AMSError.NONE, invokeId);
         this.lengthSupplier = lengthSupplier;
     }
 
-    public static CalculatedAMSHeader of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, CommandIdSupplier commandIdSupplier, StateIdSupplier stateIdSupplier, LengthSupplier lengthSupplier, Invoke invokeId) {
-        return new CalculatedAMSHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandIdSupplier, stateIdSupplier, lengthSupplier, invokeId);
+    public static CalculatedAMSHeader of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateId, LengthSupplier lengthSupplier, Invoke invokeId) {
+        return new CalculatedAMSHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateId, lengthSupplier, invokeId);
     }
 
     @FunctionalInterface
@@ -64,8 +58,8 @@ public class CalculatedAMSHeader extends AMSHeader {
             targetAmsPort,
             sourceAmsNetId,
             sourceAmsPort,
-            commandIdSupplier.getCommandId(),
-            stateIdSupplier.getStateId(),
+            commandId,
+            stateFlags,
             lengthSupplier.getLength(),
             code,
             invokeId);
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 b58b15e..6c859d0 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
@@ -19,12 +19,14 @@
 package org.apache.plc4x.java.ads.api.generic.types;
 
 import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import org.apache.plc4x.java.ads.api.util.ByteReadable;
-import org.apache.plc4x.java.ads.api.util.ByteValue;
+import org.apache.plc4x.java.ads.api.util.UnsignedShortLEByteValue;
 
-import java.nio.ByteBuffer;
-import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.apache.plc4x.java.ads.api.generic.types.State.StateMask.*;
 
 /**
  * 2 bytes	see below.
@@ -42,82 +44,144 @@ import java.util.Arrays;
  * 0x004x	UDP Protocol
  * Bit number 7 marks, if it should be transfered with TCP or UDP.
  */
-public enum State implements ByteReadable {
-    ADS_REQUEST_TCP(0x04),
-    ADS_RESPONSE_TCP(0x05),
-    ADS_REQUEST_UDP(0x44),
-    ADS_RESPONSE_UDP(0x45),
-    UNKNOWN();
-
-    // TODO: refactor as this is not really an enum, its more a flag collection:
-    //.... .... .... ...0 = RESPONSE: Not set
-    //.... .... .... ..0. = NO RETURN: Not set
-    //.... .... .... .1.. = ADS COMMAND: Set
-    //.... .... .... 0... = SYSTEM COMMAND: Not set
-    //.... .... ...0 .... = HIGH PRIORITY COMMAND: Not set
-    //.... .... ..0. .... = TIMESTAMP ADDED: Not set
-    //.... .... .0.. .... = UDP COMMAND: Not set
-    //.... .... 0... .... = INIT COMMAND: Not set
-    //0... .... .... .... = BROADCAST: Not set
-
-    public static final int NUM_BYTES = 2;
-
-    final byte[] value;
-
-    final int intValue;
-
-    State() {
-        value = new byte[0];
-        intValue = 0;
-    }
-
-    State(int value) {
-        ByteValue.checkUnsignedBounds(value, NUM_BYTES);
-        this.intValue = value;
-        this.value = ByteBuffer.allocate(NUM_BYTES)
-            // LE
-            .put((byte) (value & 0xff))
-            .put((byte) (value >> 8 & 0xff))
-            .array();
-    }
-
-    @Override
-    public byte[] getBytes() {
-        if (this == UNKNOWN) {
-            throw new IllegalStateException("Unknown enum can't be serialized");
+public class State extends UnsignedShortLEByteValue {
+
+    public enum StateMask {
+        RESPONSE(0b0000_0000_0000_0001),
+        NO_RETURN(0b0000_0000_0000_0010),
+        ADS_COMMAND(0b0000_0000_0000_0100),
+        SYSTEM_COMMAND(0b0000_0000_0000_1000),
+        HIGH_PRIORITY_COMMAND(0b0000_0000_0001_0000),
+        TIMESTAMP_ADDED(0b0000_0000_0010_0000),
+        UDP_COMMAND(0b0000_0000_0100_0000),
+        INIT_COMMAND(0b0000_0000_1000_0000),
+        BROADCAST(0b1000_0000_0000_0000);
+
+        private final int mask;
+
+        StateMask(int mask) {
+            this.mask = mask;
         }
-        return value;
-    }
 
-    public ByteBuf getByteBuf() {
-        if (this == UNKNOWN) {
-            throw new IllegalStateException("Unknown enum can't be serialized");
+        public boolean applies(int value) {
+            return (value & this.mask) != 0;
         }
-        return Unpooled.buffer().writeBytes(value);
-    }
 
-    public static State of(byte... bytes) {
-        // TODO: improve by using a map
-        for (State command : values()) {
-            if (Arrays.equals(bytes, command.value)) {
-                return command;
-            }
+        public boolean applies(State state) {
+            return (state.getAsInt() & this.mask) != 0;
+        }
+
+        public int getMask() {
+            return mask;
         }
-        return UNKNOWN;
     }
 
+    public static final State DEFAULT = State.of(ADS_COMMAND);
 
-    public static State of(int intValue) {
-        // TODO: improve by using a map
-        for (State state : values()) {
-            if (state.intValue == intValue) {
-                return state;
-            }
-        }
-        return UNKNOWN;
+    public static final int NUM_BYTES = UnsignedShortLEByteValue.NUM_BYTES;
+
+    protected State(byte... values) {
+        super(values);
+    }
+
+    protected State(int value) {
+        super(value);
+    }
+
+    protected State(ByteBuf byteBuf) {
+        super(byteBuf);
+    }
+
+    public static State of(byte... values) {
+        return new State(values);
+    }
+
+    public static State of(int value) {
+        checkUnsignedBounds(value, NUM_BYTES);
+        return new State(value);
     }
 
     public static State of(ByteBuf byteBuf) {
-        return of(byteBuf.readUnsignedShortLE());
+        return new State(byteBuf);
+    }
+
+    public static State of(String length) {
+        return of(Integer.parseInt(length));
+    }
+
+    public static State of(StateMask... stateMasks) {
+        return State.of(Stream.of(stateMasks).map(StateMask::getMask).reduce(0, (a, b) -> a | b));
+    }
+
+    public EnumSet<StateMask> getStateMaskEnumSet() {
+        List<StateMask> result = new LinkedList<>();
+        if (isResponse()) {
+            result.add(StateMask.RESPONSE);
+        }
+        if (isNoReturn()) {
+            result.add(NO_RETURN);
+        }
+        if (isADSCommand()) {
+            result.add(StateMask.ADS_COMMAND);
+        }
+        if (isSystemCommand()) {
+            result.add(StateMask.SYSTEM_COMMAND);
+        }
+        if (isHighPriorityCommand()) {
+            result.add(StateMask.HIGH_PRIORITY_COMMAND);
+        }
+        if (isTimestampAdded()) {
+            result.add(StateMask.TIMESTAMP_ADDED);
+        }
+        if (isUDPCommand()) {
+            result.add(StateMask.UDP_COMMAND);
+        }
+        if (isInitCommand()) {
+            result.add(StateMask.INIT_COMMAND);
+        }
+        if (isBroadcast()) {
+            result.add(StateMask.BROADCAST);
+        }
+        return EnumSet.copyOf(result);
+    }
+
+    public boolean isResponse() {
+        return RESPONSE.applies(this);
+    }
+
+    public boolean isRequest() {
+        return !isResponse();
+    }
+
+    public boolean isNoReturn() {
+        return NO_RETURN.applies(this);
+    }
+
+    public boolean isADSCommand() {
+        return ADS_COMMAND.applies(this);
+    }
+
+    public boolean isSystemCommand() {
+        return SYSTEM_COMMAND.applies(this);
+    }
+
+    public boolean isHighPriorityCommand() {
+        return HIGH_PRIORITY_COMMAND.applies(this);
+    }
+
+    public boolean isTimestampAdded() {
+        return TIMESTAMP_ADDED.applies(this);
+    }
+
+    public boolean isUDPCommand() {
+        return UDP_COMMAND.applies(this);
+    }
+
+    public boolean isInitCommand() {
+        return INIT_COMMAND.applies(this);
+    }
+
+    public boolean isBroadcast() {
+        return BROADCAST.applies(this);
     }
 }
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
index d28c292..f7d8ac8 100644
--- 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
@@ -74,32 +74,14 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
             throw new IllegalStateException("Overflow in datalength: " + dataLength.getAsLong());
         }
         ByteBuf commandBuffer = byteBuf.readBytes((int) dataLength.getAsLong());
-        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) {
+                if (stateId.isRequest()) {
                     out.add(new ADSReadDeviceInfoRequest(amstcpHeader, amsHeader));
                 } else {
                     Result result = Result.of(commandBuffer);
@@ -111,7 +93,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Read:
-                if (request) {
+                if (stateId.isRequest()) {
                     IndexGroup indexGroup = IndexGroup.of(commandBuffer);
                     IndexOffset indexOffset = IndexOffset.of(commandBuffer);
                     Length length = Length.of(commandBuffer);
@@ -127,7 +109,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Write:
-                if (request) {
+                if (stateId.isRequest()) {
                     IndexGroup indexGroup = IndexGroup.of(commandBuffer);
                     IndexOffset indexOffset = IndexOffset.of(commandBuffer);
                     Length length = Length.of(byteBuf);
@@ -142,7 +124,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Read_State:
-                if (request) {
+                if (stateId.isRequest()) {
                     out.add(new ADSReadStateRequest(amstcpHeader, amsHeader));
                 } else {
                     Result result = Result.of(commandBuffer);
@@ -150,7 +132,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Write_Control:
-                if (request) {
+                if (stateId.isRequest()) {
                     ADSState adsState = ADSState.of(commandBuffer);
                     DeviceState deviceState = DeviceState.of(commandBuffer);
                     Length length = Length.of(byteBuf);
@@ -165,7 +147,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Add_Device_Notification:
-                if (request) {
+                if (stateId.isRequest()) {
                     IndexGroup indexGroup = IndexGroup.of(commandBuffer);
                     IndexOffset indexOffset = IndexOffset.of(commandBuffer);
                     Length length = Length.of(commandBuffer);
@@ -180,7 +162,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Delete_Device_Notification:
-                if (request) {
+                if (stateId.isRequest()) {
                     NotificationHandle notificationHandle = NotificationHandle.of(commandBuffer);
                     out.add(new ADSDeleteDeviceNotificationRequest(amstcpHeader, amsHeader, notificationHandle));
                 } else {
@@ -189,7 +171,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Device_Notification:
-                if (request) {
+                if (stateId.isRequest()) {
                     Length length = Length.of(commandBuffer);
                     if (length.getAsLong() > Integer.MAX_VALUE) {
                         throw new IllegalStateException("Overflow in datalength: " + length.getAsLong());
@@ -226,7 +208,7 @@ public class ADSProtocol extends MessageToMessageCodec<ByteBuf, AMSTCPPaket> {
                 }
                 break;
             case ADS_Read_Write:
-                if (request) {
+                if (stateId.isRequest()) {
                     IndexGroup indexGroup = IndexGroup.of(commandBuffer);
                     IndexOffset indexOffset = IndexOffset.of(commandBuffer);
                     ReadLength readLength = ReadLength.of(commandBuffer);
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 798d99f..ddd8d63 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
@@ -42,7 +42,6 @@ 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 {
 
@@ -70,7 +69,6 @@ public class ADSDumper {
 
             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();
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/util/TcpHexDumper.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/util/TcpHexDumper.java
index 4eb726f..72d1d7a 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/util/TcpHexDumper.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/util/TcpHexDumper.java
@@ -85,8 +85,15 @@ public class TcpHexDumper implements BeforeEachCallback, AfterEachCallback, Para
     }
 
     public void stop() throws IOException, InterruptedException {
+        stop(false);
+    }
+
+    public void stop(boolean await) throws IOException, InterruptedException {
         serverSocket.close();
-        pool.awaitTermination(shutdownTimeout, TimeUnit.SECONDS);
+        if (await)
+            pool.awaitTermination(shutdownTimeout, TimeUnit.SECONDS);
+        else
+            pool.shutdownNow();
         logger.info("Stopped");
     }
 

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