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/16 17:32:31 UTC

[incubator-plc4x] branch feature/Beckhoff_ADS_protocol updated: + added convinience methods for automatically calculating lengths. + Integrated CalculatedClass into normal classes + added couple more nullchecks

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 1283cf1  + added convinience methods for automatically calculating lengths. + Integrated CalculatedClass into normal classes + added couple more nullchecks
1283cf1 is described below

commit 1283cf1c0ac7155ea3694367223c1c50a3a654aa
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Feb 16 18:32:25 2018 +0100

    + added convinience methods for automatically calculating lengths.
    + Integrated CalculatedClass into normal classes
    + added couple more nullchecks
---
 .../commands/ADSAddDeviceNotificationRequest.java  | 38 ++++++------
 .../commands/ADSAddDeviceNotificationResponse.java | 10 +--
 .../ADSDeleteDeviceNotificationRequest.java        |  8 ++-
 .../ADSDeleteDeviceNotificationResponse.java       |  6 +-
 .../api/commands/ADSDeviceNotificationRequest.java | 49 ++++++++++-----
 .../api/commands/ADSReadDeviceInfoResponse.java    | 22 ++++---
 .../java/ads/api/commands/ADSReadRequest.java      | 20 +++---
 .../java/ads/api/commands/ADSReadResponse.java     | 38 ++++++++----
 .../ads/api/commands/ADSReadStateResponse.java     |  6 +-
 .../java/ads/api/commands/ADSReadWriteRequest.java | 56 +++++++++++------
 .../ads/api/commands/ADSReadWriteResponse.java     | 36 +++++++----
 .../ads/api/commands/ADSWriteControlRequest.java   | 50 ++++++++++-----
 .../ads/api/commands/ADSWriteControlResponse.java  |  6 +-
 .../java/ads/api/commands/ADSWriteRequest.java     | 55 ++++++++++-------
 .../java/ads/api/commands/ADSWriteResponse.java    |  6 +-
 .../java/ads/api/commands/UnknownCommand.java      |  4 +-
 .../api/commands/types/AdsNotificationSample.java  | 34 ++++++++--
 .../java/ads/api/commands/types/AdsReturnCode.java |  4 +-
 .../ads/api/commands/types/AdsStampHeader.java     |  7 ++-
 .../plc4x/java/ads/api/generic/AMSHeader.java      | 57 +++++++++++++----
 .../plc4x/java/ads/api/generic/AMSTCPHeader.java   | 40 ++++++++++--
 .../plc4x/java/ads/api/generic/AMSTCPPaket.java    | 32 +++++-----
 .../generic/calculated/CalculatedAMSHeader.java    | 72 ----------------------
 .../generic/calculated/CalculatedAMSTCPHeader.java | 66 --------------------
 .../plc4x/java/ads/netty/Plc4XADSProtocol.java     |  2 +-
 .../java/org/apache/plc4x/java/ads/ADSDumper.java  |  2 -
 .../plc4x/java/ads/netty/ADSProtocolTest.java      |  9 +--
 27 files changed, 396 insertions(+), 339 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 1b1807b..f1b19c1 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
@@ -26,6 +26,8 @@ import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
 import org.apache.plc4x.java.ads.api.generic.types.*;
 import org.apache.plc4x.java.ads.api.util.ByteValue;
 
+import java.util.Objects;
+
 /**
  * A notification is created in an ADS device.
  * <p>
@@ -66,32 +68,32 @@ public class ADSAddDeviceNotificationRequest extends ADSAbstractRequest {
 
     protected ADSAddDeviceNotificationRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length, TransmissionMode transmissionMode, MaxDelay maxDelay, CycleTime cycleTime) {
         super(amstcpHeader, amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.transmissionMode = transmissionMode;
-        this.maxDelay = maxDelay;
-        this.cycleTime = cycleTime;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
+        this.transmissionMode = Objects.requireNonNull(transmissionMode);
+        this.maxDelay = Objects.requireNonNull(maxDelay);
+        this.cycleTime = Objects.requireNonNull(cycleTime);
     }
 
     protected ADSAddDeviceNotificationRequest(AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length, TransmissionMode transmissionMode, MaxDelay maxDelay, CycleTime cycleTime) {
         super(amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.transmissionMode = transmissionMode;
-        this.maxDelay = maxDelay;
-        this.cycleTime = cycleTime;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
+        this.transmissionMode = Objects.requireNonNull(transmissionMode);
+        this.maxDelay = Objects.requireNonNull(maxDelay);
+        this.cycleTime = Objects.requireNonNull(cycleTime);
     }
 
     protected ADSAddDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Length length, TransmissionMode transmissionMode, MaxDelay maxDelay, CycleTime cycleTime) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, State.DEFAULT, invokeId);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.transmissionMode = transmissionMode;
-        this.maxDelay = maxDelay;
-        this.cycleTime = cycleTime;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
+        this.transmissionMode = Objects.requireNonNull(transmissionMode);
+        this.maxDelay = Objects.requireNonNull(maxDelay);
+        this.cycleTime = Objects.requireNonNull(cycleTime);
     }
 
     @Override
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 44ecb50..a5cf8b7 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
@@ -28,6 +28,8 @@ 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 java.util.Objects;
+
 /**
  * A notification is created in an ADS device.
  */
@@ -46,14 +48,14 @@ public class ADSAddDeviceNotificationResponse extends ADSAbstractResponse {
 
     protected ADSAddDeviceNotificationResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, NotificationHandle notificationHandle) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
-        this.notificationHandle = notificationHandle;
+        this.result = Objects.requireNonNull(result);
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
     }
 
     protected ADSAddDeviceNotificationResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, NotificationHandle notificationHandle) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
-        this.notificationHandle = notificationHandle;
+        this.result = Objects.requireNonNull(result);
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
     }
 
     public static ADSAddDeviceNotificationResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, NotificationHandle notificationHandle) {
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 096247f..ecda040 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * One before defined notification is deleted in an ADS device.
  */
@@ -40,17 +42,17 @@ public class ADSDeleteDeviceNotificationRequest extends ADSAbstractRequest {
 
     protected ADSDeleteDeviceNotificationRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, NotificationHandle notificationHandle) {
         super(amstcpHeader, amsHeader);
-        this.notificationHandle = notificationHandle;
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
     }
 
     protected ADSDeleteDeviceNotificationRequest(AMSHeader amsHeader, NotificationHandle notificationHandle) {
         super(amsHeader);
-        this.notificationHandle = notificationHandle;
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
     }
 
     protected ADSDeleteDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, NotificationHandle notificationHandle) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.notificationHandle = notificationHandle;
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
     }
 
     public static ADSDeleteDeviceNotificationRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, NotificationHandle notificationHandle) {
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 f3e4c11..688a95c 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * One before defined notification is deleted in an ADS device.
  */
@@ -40,12 +42,12 @@ public class ADSDeleteDeviceNotificationResponse extends ADSAbstractResponse {
 
     protected ADSDeleteDeviceNotificationResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     protected ADSDeleteDeviceNotificationResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     public static ADSDeleteDeviceNotificationResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
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 978c4cd..da7c9ab 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
@@ -29,8 +29,10 @@ 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 org.apache.plc4x.java.ads.api.util.LengthSupplier;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Data will carry forward independently from an ADS device to a Client
@@ -53,25 +55,44 @@ public class ADSDeviceNotificationRequest extends ADSAbstractRequest {
      */
     private final List<AdsStampHeader> adsStampHeaders;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSDeviceNotificationRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(amstcpHeader, amsHeader);
-        this.length = length;
-        this.stamps = stamps;
-        this.adsStampHeaders = adsStampHeaders;
+        this.length = Objects.requireNonNull(length);
+        this.stamps = Objects.requireNonNull(stamps);
+        this.adsStampHeaders = Objects.requireNonNull(adsStampHeaders);
+        calculated = false;
+        lengthSupplier = null;
     }
 
     protected ADSDeviceNotificationRequest(AMSHeader amsHeader, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(amsHeader);
-        this.length = length;
-        this.stamps = stamps;
-        this.adsStampHeaders = adsStampHeaders;
+        this.length = Objects.requireNonNull(length);
+        this.stamps = Objects.requireNonNull(stamps);
+        this.adsStampHeaders = Objects.requireNonNull(adsStampHeaders);
+        calculated = false;
+        lengthSupplier = null;
     }
 
-    protected ADSDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
+    protected ADSDeviceNotificationRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.length = length;
-        this.stamps = stamps;
-        this.adsStampHeaders = adsStampHeaders;
+        this.length = null;
+        this.stamps = Objects.requireNonNull(stamps);
+        this.adsStampHeaders = Objects.requireNonNull(adsStampHeaders);
+        calculated = true;
+        this.lengthSupplier = () -> {
+            long aggregateLength = 0;
+            for (LengthSupplier supplier : adsStampHeaders) {
+                aggregateLength += supplier.getCalculatedLength();
+            }
+            return aggregateLength;
+        };
     }
 
     public static ADSDeviceNotificationRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
@@ -82,19 +103,19 @@ public class ADSDeviceNotificationRequest extends ADSAbstractRequest {
         return new ADSDeviceNotificationRequest(amsHeader, length, stamps, adsStampHeaders);
     }
 
-    public static ADSDeviceNotificationRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Length length, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
-        return new ADSDeviceNotificationRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, length, stamps, adsStampHeaders);
+    public static ADSDeviceNotificationRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Stamps stamps, List<AdsStampHeader> adsStampHeaders) {
+        return new ADSDeviceNotificationRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, stamps, adsStampHeaders);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(length, stamps, buildADSData(adsStampHeaders.toArray(new ByteReadable[adsStampHeaders.size()])));
+        return buildADSData((calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length), stamps, buildADSData(adsStampHeaders.toArray(new ByteReadable[adsStampHeaders.size()])));
     }
 
     @Override
     public String toString() {
         return "ADSDeviceNotificationRequest{" +
-            "length=" + length +
+            "length=" + (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length) +
             ", stamps=" + stamps +
             ", adsStampHeaders=" + adsStampHeaders +
             "} " + super.toString();
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 d780890..ffccbb6 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * Reads the name and the version number of the ADS device.
  */
@@ -56,20 +58,20 @@ public class ADSReadDeviceInfoResponse extends ADSAbstractResponse {
 
     protected ADSReadDeviceInfoResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, MajorVersion majorVersion, MinorVersion minorVersion, Version version, Device device) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
-        this.majorVersion = majorVersion;
-        this.minorVersion = minorVersion;
-        this.version = version;
-        this.device = device;
+        this.result = Objects.requireNonNull(result);
+        this.majorVersion = Objects.requireNonNull(majorVersion);
+        this.minorVersion = Objects.requireNonNull(minorVersion);
+        this.version = Objects.requireNonNull(version);
+        this.device = Objects.requireNonNull(device);
     }
 
     protected ADSReadDeviceInfoResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, MajorVersion majorVersion, MinorVersion minorVersion, Version version, Device device) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
-        this.majorVersion = majorVersion;
-        this.minorVersion = minorVersion;
-        this.version = version;
-        this.device = device;
+        this.result = Objects.requireNonNull(result);
+        this.majorVersion = Objects.requireNonNull(majorVersion);
+        this.minorVersion = Objects.requireNonNull(minorVersion);
+        this.version = Objects.requireNonNull(version);
+        this.device = Objects.requireNonNull(device);
     }
 
     public static ADSReadDeviceInfoResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, MajorVersion majorVersion, MinorVersion minorVersion, Version version, Device device) {
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 f64d166..2c0356b 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
@@ -29,6 +29,8 @@ 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 java.util.Objects;
+
 /**
  * With ADS Read data can be read from an ADS device.  The data are addressed by the Index Group and the Index Offset
  */
@@ -52,23 +54,23 @@ public class ADSReadRequest extends ADSAbstractRequest {
 
     protected ADSReadRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length) {
         super(amstcpHeader, amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
     }
 
     protected ADSReadRequest(AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length) {
         super(amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
     }
 
     protected ADSReadRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Length length) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
     }
 
     public static ADSReadRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length) {
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 91ee085..a4668ed 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
@@ -28,6 +28,9 @@ 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.LengthSupplier;
+
+import java.util.Objects;
 
 /**
  * With ADS Read data can be read from an ADS device
@@ -48,31 +51,42 @@ public class ADSReadResponse extends ADSAbstractResponse {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSReadResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, Length length, Data data) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
-        this.length = length;
-        this.data = data;
+        this.result = Objects.requireNonNull(result);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
-    protected ADSReadResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Length length, Data data) {
+    protected ADSReadResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Data data) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
-        this.length = length;
-        this.data = data;
+        this.result = Objects.requireNonNull(result);
+        this.length = null;
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = () -> data.getCalculatedLength();
+        this.calculated = Objects.requireNonNull(true);
     }
 
     public static ADSReadResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, Length length, Data data) {
         return new ADSReadResponse(amstcpHeader, amsHeader, result, length, data);
     }
 
-    public static ADSReadResponse of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Length length, Data data) {
-        return new ADSReadResponse(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, result, length, data);
+    public static ADSReadResponse of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Data data) {
+        return new ADSReadResponse(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, result, data);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(result, length, data);
+        return buildADSData(result, (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length), data);
     }
 
     public Result getResult() {
@@ -80,7 +94,7 @@ public class ADSReadResponse extends ADSAbstractResponse {
     }
 
     public Length getLength() {
-        return length;
+        return (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length);
     }
 
     public Data getData() {
@@ -91,7 +105,7 @@ public class ADSReadResponse extends ADSAbstractResponse {
     public String toString() {
         return "ADSReadResponse{" +
             "result=" + result +
-            ", length=" + length +
+            ", length=" + (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length) +
             ", data=" + data +
             "} " + super.toString();
     }
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 f552e25..6c3d08b 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * Reads the ADS status and the device status of an ADS device.
  */
@@ -40,12 +42,12 @@ public class ADSReadStateResponse extends ADSAbstractResponse {
 
     protected ADSReadStateResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     protected ADSReadStateResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     public static ADSReadStateResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
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 e6245dd..89b9b7f 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
@@ -26,6 +26,9 @@ 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.LengthSupplier;
+
+import java.util.Objects;
 
 /**
  * With ADS Read Write data will be written to an ADS device. Additionally, data can be read from the ADS device.
@@ -56,31 +59,44 @@ public class ADSReadWriteRequest extends ADSAbstractRequest {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSReadWriteRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, WriteLength writeLength, Data data) {
         super(amstcpHeader, amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.readLength = readLength;
-        this.writeLength = writeLength;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.readLength = Objects.requireNonNull(readLength);
+        this.writeLength = Objects.requireNonNull(writeLength);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
     protected ADSReadWriteRequest(AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, WriteLength writeLength, Data data) {
         super(amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.readLength = readLength;
-        this.writeLength = writeLength;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.readLength = Objects.requireNonNull(readLength);
+        this.writeLength = Objects.requireNonNull(writeLength);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
-    protected ADSReadWriteRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, WriteLength writeLength, Data data) {
+    protected ADSReadWriteRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, Data data) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.readLength = readLength;
-        this.writeLength = writeLength;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.readLength = Objects.requireNonNull(readLength);
+        this.writeLength = null;
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = () -> data.getCalculatedLength();
+        this.calculated = true;
     }
 
     public static ADSReadWriteRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, WriteLength writeLength, Data data) {
@@ -91,13 +107,13 @@ public class ADSReadWriteRequest extends ADSAbstractRequest {
         return new ADSReadWriteRequest(amsHeader, indexGroup, indexOffset, readLength, writeLength, data);
     }
 
-    public static ADSReadWriteRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, WriteLength writeLength, Data data) {
-        return new ADSReadWriteRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, readLength, writeLength, data);
+    public static ADSReadWriteRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, ReadLength readLength, Data data) {
+        return new ADSReadWriteRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, readLength, data);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(indexGroup, indexOffset, readLength, writeLength, data);
+        return buildADSData(indexGroup, indexOffset, readLength, (calculated ? WriteLength.of(lengthSupplier.getCalculatedLength()) : writeLength), data);
     }
 
     @Override
@@ -106,7 +122,7 @@ public class ADSReadWriteRequest extends ADSAbstractRequest {
             "indexGroup=" + indexGroup +
             ", indexOffset=" + indexOffset +
             ", readLength=" + readLength +
-            ", writeLength=" + writeLength +
+            ", writeLength=" + (calculated ? WriteLength.of(lengthSupplier.getCalculatedLength()) : writeLength) +
             ", data=" + data +
             "} " + super.toString();
     }
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 663d5de..3230f0e 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
@@ -28,6 +28,9 @@ 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.LengthSupplier;
+
+import java.util.Objects;
 
 /**
  * With ADS Read Write data will be written to an ADS device. Additionally, data can be read from the ADS device.
@@ -50,38 +53,49 @@ public class ADSReadWriteResponse extends ADSAbstractResponse {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSReadWriteResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, Length length, Data data) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
-        this.length = length;
-        this.data = data;
+        this.result = Objects.requireNonNull(result);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
-    protected ADSReadWriteResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Length length, Data data) {
+    protected ADSReadWriteResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Data data) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
-        this.length = length;
-        this.data = data;
+        this.result = Objects.requireNonNull(result);
+        this.length = null;
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = () -> data.getCalculatedLength();
+        this.calculated = true;
     }
 
     public static ADSReadWriteResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result, Length length, Data data) {
         return new ADSReadWriteResponse(amstcpHeader, amsHeader, result, length, data);
     }
 
-    public static ADSReadWriteResponse of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Length length, Data data) {
-        return new ADSReadWriteResponse(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, result, length, data);
+    public static ADSReadWriteResponse of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result, Data data) {
+        return new ADSReadWriteResponse(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, result, data);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(result, length, data);
+        return buildADSData(result, (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length), data);
     }
 
     @Override
     public String toString() {
         return "ADSReadWriteResponse{" +
             "result=" + result +
-            ", length=" + length +
+            ", length=" + (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length) +
             ", data=" + data +
             "} " + super.toString();
     }
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 40c6cee..e9e7845 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
@@ -29,6 +29,9 @@ 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.LengthSupplier;
+
+import java.util.Objects;
 
 /**
  * Changes the ADS status and the device status of an ADS device.
@@ -55,28 +58,41 @@ public class ADSWriteControlRequest extends ADSAbstractRequest {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSWriteControlRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, ADSState adsState, DeviceState deviceState, Length length, Data data) {
         super(amstcpHeader, amsHeader);
-        this.adsState = adsState;
-        this.deviceState = deviceState;
-        this.length = length;
-        this.data = data;
+        this.adsState = Objects.requireNonNull(adsState);
+        this.deviceState = Objects.requireNonNull(deviceState);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
     protected ADSWriteControlRequest(AMSHeader amsHeader, ADSState adsState, DeviceState deviceState, Length length, Data data) {
         super(amsHeader);
-        this.adsState = adsState;
-        this.deviceState = deviceState;
-        this.length = length;
-        this.data = data;
+        this.adsState = Objects.requireNonNull(adsState);
+        this.deviceState = Objects.requireNonNull(deviceState);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
-    protected ADSWriteControlRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, ADSState adsState, DeviceState deviceState, Length length, Data data) {
+    protected ADSWriteControlRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, ADSState adsState, DeviceState deviceState, Data data) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.adsState = adsState;
-        this.deviceState = deviceState;
-        this.length = length;
-        this.data = data;
+        this.adsState = Objects.requireNonNull(adsState);
+        this.deviceState = Objects.requireNonNull(deviceState);
+        this.length = null;
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = data;
+        this.calculated = true;
     }
 
     public static ADSWriteControlRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, ADSState adsState, DeviceState deviceState, Length length, Data data) {
@@ -87,13 +103,13 @@ public class ADSWriteControlRequest extends ADSAbstractRequest {
         return new ADSWriteControlRequest(amsHeader, adsState, deviceState, length, data);
     }
 
-    public static ADSWriteControlRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, ADSState adsState, DeviceState deviceState, Length length, Data data) {
-        return new ADSWriteControlRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, adsState, deviceState, length, data);
+    public static ADSWriteControlRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, ADSState adsState, DeviceState deviceState, Data data) {
+        return new ADSWriteControlRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, adsState, deviceState, data);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(adsState, deviceState, length, data);
+        return buildADSData(adsState, deviceState, (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length), data);
     }
 
     @Override
@@ -101,7 +117,7 @@ public class ADSWriteControlRequest extends ADSAbstractRequest {
         return "ADSWriteControlRequest{" +
             "adsState=" + adsState +
             ", deviceState=" + deviceState +
-            ", length=" + length +
+            ", length=" + (calculated ? Length.of(lengthSupplier.getCalculatedLength()) : length) +
             ", data=" + data +
             "} " + super.toString();
     }
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 19d3282..207e9bd 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * Changes the ADS status and the device status of an ADS device.
  */
@@ -39,12 +41,12 @@ public class ADSWriteControlResponse extends ADSAbstractResponse {
 
     protected ADSWriteControlResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     protected ADSWriteControlResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     public static ADSWriteControlResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
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 e60eb42..bd3d054 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
@@ -18,10 +18,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.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;
@@ -29,6 +26,9 @@ 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.LengthSupplier;
+
+import java.util.Objects;
 
 /**
  * With ADS Write data can be written to an ADS device. The data are addressed by the Index Group and the Index Offset.
@@ -53,28 +53,41 @@ public class ADSWriteRequest extends ADSAbstractRequest {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     protected ADSWriteRequest(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length, Data data) {
         super(amstcpHeader, amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
     protected ADSWriteRequest(AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length, Data data) {
         super(amsHeader);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = Objects.requireNonNull(length);
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = null;
+        this.calculated = false;
     }
 
-    protected ADSWriteRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Length length, Data data) {
+    protected ADSWriteRequest(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Data data) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.indexGroup = indexGroup;
-        this.indexOffset = indexOffset;
-        this.length = length;
-        this.data = data;
+        this.indexGroup = Objects.requireNonNull(indexGroup);
+        this.indexOffset = Objects.requireNonNull(indexOffset);
+        this.length = null;
+        this.data = Objects.requireNonNull(data);
+        this.lengthSupplier = () -> data.getCalculatedLength();
+        this.calculated = true;
     }
 
     public static ADSWriteRequest of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, IndexGroup indexGroup, IndexOffset indexOffset, Length length, Data data) {
@@ -85,13 +98,13 @@ public class ADSWriteRequest extends ADSAbstractRequest {
         return new ADSWriteRequest(amsHeader, indexGroup, indexOffset, length, data);
     }
 
-    public static ADSWriteRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Length length, Data data) {
-        return new ADSWriteRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length, data);
+    public static ADSWriteRequest of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, IndexGroup indexGroup, IndexOffset indexOffset, Data data) {
+        return new ADSWriteRequest(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
     }
 
     @Override
     public ADSData getAdsData() {
-        return buildADSData(indexGroup, indexOffset, length, data);
+        return buildADSData(indexGroup, indexOffset, (calculated ? WriteLength.of(lengthSupplier.getCalculatedLength()) : length), data);
     }
 
     @Override
@@ -99,7 +112,7 @@ public class ADSWriteRequest extends ADSAbstractRequest {
         return "ADSWriteRequest{" +
             "indexGroup=" + indexGroup +
             ", indexOffset=" + indexOffset +
-            ", length=" + length +
+            ", length=" + (calculated ? WriteLength.of(lengthSupplier.getCalculatedLength()) : length) +
             ", data=" + data +
             "} " + super.toString();
     }
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 9b2925b..a2f7a1b 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
@@ -27,6 +27,8 @@ 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 java.util.Objects;
+
 /**
  * With ADS Write data can be written to an ADS device.
  */
@@ -40,12 +42,12 @@ public class ADSWriteResponse extends ADSAbstractResponse {
 
     protected ADSWriteResponse(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
         super(amstcpHeader, amsHeader);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     protected ADSWriteResponse(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Invoke invokeId, Result result) {
         super(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId);
-        this.result = result;
+        this.result = Objects.requireNonNull(result);
     }
 
     public static ADSWriteResponse of(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, Result result) {
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 d1e3aa9..0e983d7 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
@@ -25,6 +25,8 @@ 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 java.util.Objects;
+
 /**
  * Unknown ADS Package
  */
@@ -35,7 +37,7 @@ public class UnknownCommand extends AMSTCPPaket {
 
     protected UnknownCommand(AMSTCPHeader amstcpHeader, AMSHeader amsHeader, ByteBuf remainingBytes) {
         super(amstcpHeader, amsHeader);
-        this.remainingBytes = remainingBytes;
+        this.remainingBytes = Objects.requireNonNull(remainingBytes);
     }
 
     @Override
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsNotificationSample.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsNotificationSample.java
index 24282a0..0f224fa 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsNotificationSample.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsNotificationSample.java
@@ -20,6 +20,9 @@ package org.apache.plc4x.java.ads.api.commands.types;
 
 import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
+import org.apache.plc4x.java.ads.api.util.LengthSupplier;
+
+import java.util.Objects;
 
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
@@ -38,10 +41,31 @@ public class AdsNotificationSample implements ByteReadable {
      */
     private final Data data;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
+    protected AdsNotificationSample(NotificationHandle notificationHandle, Data data) {
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
+        this.sampleSize = null;
+        this.data = Objects.requireNonNull(data);
+        calculated = true;
+        lengthSupplier = () -> data.getCalculatedLength();
+    }
+
     protected AdsNotificationSample(NotificationHandle notificationHandle, SampleSize sampleSize, Data data) {
-        this.notificationHandle = notificationHandle;
-        this.sampleSize = sampleSize;
-        this.data = data;
+        this.notificationHandle = Objects.requireNonNull(notificationHandle);
+        this.sampleSize = Objects.requireNonNull(sampleSize);
+        this.data = Objects.requireNonNull(data);
+        calculated = true;
+        lengthSupplier = null;
+    }
+
+    public static AdsNotificationSample of(NotificationHandle notificationHandle, Data data) {
+        return new AdsNotificationSample(notificationHandle, data);
     }
 
     public static AdsNotificationSample of(NotificationHandle notificationHandle, SampleSize sampleSize, Data data) {
@@ -50,14 +74,14 @@ public class AdsNotificationSample implements ByteReadable {
 
     @Override
     public ByteBuf getByteBuf() {
-        return buildByteBuff(notificationHandle, sampleSize, data);
+        return buildByteBuff(notificationHandle, (calculated ? SampleSize.of(lengthSupplier.getCalculatedLength()) : sampleSize), data);
     }
 
     @Override
     public String toString() {
         return "AdsNotificationSample{" +
             "notificationHandle=" + notificationHandle +
-            ", sampleSize=" + sampleSize +
+            ", sampleSize=" + (calculated ? SampleSize.of(lengthSupplier.getCalculatedLength()) : sampleSize) +
             ", data=" + data +
             '}';
     }
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
index 9a7c534..e9e1b13 100644
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
+++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/commands/types/AdsReturnCode.java
@@ -18,6 +18,8 @@
  */
 package org.apache.plc4x.java.ads.api.commands.types;
 
+import java.util.Objects;
+
 /**
  * Based on spec from: https://infosys.beckhoff.com/content/1033/tcadscommon/html/ads_returncodes.htm
  */
@@ -171,7 +173,7 @@ public enum AdsReturnCode {
         if (hex != dec) {
             throw new IllegalArgumentException("hex " + hex + " is different from dec " + dec);
         }
-        this.description = description;
+        this.description = Objects.requireNonNull(description);
         this.possibleCauses = possibleCauses;
         this.solution = solution;
     }
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 29f00b7..701768b 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
@@ -22,6 +22,7 @@ import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
 import java.util.List;
+import java.util.Objects;
 
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
@@ -41,9 +42,9 @@ public class AdsStampHeader implements ByteReadable {
     private final List<AdsNotificationSample> adsNotificationSamples;
 
     protected AdsStampHeader(TimeStamp timeStamp, Samples samples, List<AdsNotificationSample> adsNotificationSamples) {
-        this.timeStamp = timeStamp;
-        this.samples = samples;
-        this.adsNotificationSamples = adsNotificationSamples;
+        this.timeStamp = Objects.requireNonNull(timeStamp);
+        this.samples = Objects.requireNonNull(samples);
+        this.adsNotificationSamples = Objects.requireNonNull(adsNotificationSamples);
     }
 
     public static AdsStampHeader of(TimeStamp timeStamp, Samples samples, List<AdsNotificationSample> adsNotificationSamples) {
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 09dffdc..679ae4c 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
@@ -22,6 +22,7 @@ import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.generic.types.*;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
 /**
@@ -67,22 +68,49 @@ public class AMSHeader implements ByteReadable {
      */
     protected final Invoke invokeId;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final DataLengthSupplier lengthSupplier;
+    private final boolean calculated;
+    //
+    ///
+
     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;
-        this.sourceAmsPort = sourceAmsPort;
-        this.commandId = commandId;
-        this.stateFlags = stateFlags;
-        this.dataLength = dataLength;
-        this.code = code;
-        this.invokeId = invokeId;
+        this.targetAmsNetId = requireNonNull(targetAmsNetId);
+        this.targetAmsPort = requireNonNull(targetAmsPort);
+        this.sourceAmsNetId = requireNonNull(sourceAmsNetId);
+        this.sourceAmsPort = requireNonNull(sourceAmsPort);
+        this.commandId = requireNonNull(commandId);
+        this.stateFlags = requireNonNull(stateFlags);
+        this.dataLength = requireNonNull(dataLength);
+        this.code = requireNonNull(code);
+        this.invokeId = requireNonNull(invokeId);
+        lengthSupplier = null;
+        calculated = false;
+    }
+
+    protected AMSHeader(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateFlags, DataLengthSupplier dataLengthSupplier, AMSError code, Invoke invokeId) {
+        this.targetAmsNetId = requireNonNull(targetAmsNetId);
+        this.targetAmsPort = requireNonNull(targetAmsPort);
+        this.sourceAmsNetId = requireNonNull(sourceAmsNetId);
+        this.sourceAmsPort = requireNonNull(sourceAmsPort);
+        this.commandId = requireNonNull(commandId);
+        this.stateFlags = requireNonNull(stateFlags);
+        this.dataLength = null;
+        this.code = requireNonNull(code);
+        this.invokeId = requireNonNull(invokeId);
+        lengthSupplier = requireNonNull(dataLengthSupplier);
+        calculated = true;
     }
 
     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);
     }
 
+    public static AMSHeader of(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, Command commandId, State stateFlags, DataLengthSupplier dataLengthSupplier, AMSError code, Invoke invokeId) {
+        return new AMSHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateFlags, dataLengthSupplier, code, invokeId);
+    }
+
     @Override
     public ByteBuf getByteBuf() {
         return buildByteBuff(
@@ -92,7 +120,7 @@ public class AMSHeader implements ByteReadable {
             sourceAmsPort,
             commandId,
             stateFlags,
-            dataLength,
+            calculated ? DataLength.of(lengthSupplier.getCalculatedLength()) : dataLength,
             code,
             invokeId);
     }
@@ -122,7 +150,7 @@ public class AMSHeader implements ByteReadable {
     }
 
     public DataLength getDataLength() {
-        return dataLength;
+        return calculated ? DataLength.of(lengthSupplier.getCalculatedLength()) : dataLength;
     }
 
     public AMSError getCode() {
@@ -142,9 +170,14 @@ public class AMSHeader implements ByteReadable {
             ", sourceAmsPort=" + sourceAmsPort +
             ", commandId=" + commandId +
             ", stateFlags=" + stateFlags +
-            ", dataLength=" + dataLength +
+            ", dataLength=" + (calculated ? DataLength.of(lengthSupplier.getCalculatedLength()) : dataLength) +
             ", code=" + code +
             ", invokeId=" + invokeId +
             '}';
     }
+
+    @FunctionalInterface
+    public interface DataLengthSupplier {
+        long getCalculatedLength();
+    }
 }
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 1d257ab..b5d18db 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
@@ -22,7 +22,9 @@ import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.ads.api.generic.types.Length;
 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.LengthSupplier;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
 /**
@@ -34,18 +36,38 @@ public class AMSTCPHeader implements ByteReadable {
 
     protected final Length length;
 
+    ////
+    // Used when fields should be calculated. TODO: check if we better work with a subclass.
+    private final LengthSupplier[] lengthSuppliers;
+    private final boolean calculated;
+    //
+    ///
+
     protected AMSTCPHeader(Length length) {
-        this.reserved = Reserved.CONSTANT;
-        this.length = length;
+        this.reserved = requireNonNull(Reserved.CONSTANT);
+        this.length = requireNonNull(length);
+        lengthSuppliers = null;
+        calculated = false;
+    }
+
+    protected AMSTCPHeader(LengthSupplier... lengthSuppliers) {
+        this.reserved = requireNonNull(Reserved.CONSTANT);
+        this.length = null;
+        this.lengthSuppliers = requireNonNull(lengthSuppliers);
+        calculated = true;
     }
 
     public static AMSTCPHeader of(long length) {
         return new AMSTCPHeader(Length.of(length));
     }
 
+    public static AMSTCPHeader of(LengthSupplier... lengthSuppliers) {
+        return new AMSTCPHeader(lengthSuppliers);
+    }
+
     @Override
     public ByteBuf getByteBuf() {
-        return buildByteBuff(reserved, length);
+        return buildByteBuff(reserved, (calculated ? Length.of(getCalculatedLength()) : length));
     }
 
     /**
@@ -65,14 +87,22 @@ public class AMSTCPHeader implements ByteReadable {
     }
 
     public long getCalculatedLength() {
-        return length.getAsLong();
+        if (calculated) {
+            long aggregateLength = 0;
+            for (LengthSupplier supplier : lengthSuppliers) {
+                aggregateLength += supplier.getCalculatedLength();
+            }
+            return aggregateLength;
+        } else {
+            return length.getAsLong();
+        }
     }
 
     @Override
     public String toString() {
         return "AMSTCPHeader{" +
             "reserved=" + reserved +
-            ", length=" + length +
+            ", length=" + (calculated ? Length.of(getCalculatedLength()) : 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 328440b..b3acc37 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
@@ -20,11 +20,10 @@ 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.*;
 import org.apache.plc4x.java.ads.api.util.ByteReadable;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
 
 public abstract class AMSTCPPaket implements ByteReadable {
@@ -33,31 +32,32 @@ public abstract class AMSTCPPaket implements ByteReadable {
     private final AMSHeader amsHeader;
 
     public AMSTCPPaket(AMSTCPHeader amstcpHeader, AMSHeader amsHeader) {
-        this.amstcpHeader = amstcpHeader;
-        this.amsHeader = amsHeader;
+        this.amstcpHeader = requireNonNull(amstcpHeader);
+        this.amsHeader = requireNonNull(amsHeader);
     }
 
     public AMSTCPPaket(AMSHeader amsHeader) {
         // It is important that we wrap the ads data call as this will initialized in the constructor
         // so this value will be null if we call adsData now.
-        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> getAdsData().getCalculatedLength());
-        this.amsHeader = amsHeader;
+        this.amstcpHeader = AMSTCPHeader.of(requireNonNull(amsHeader), () -> getAdsData().getCalculatedLength());
+        this.amsHeader = requireNonNull(amsHeader);
     }
 
     public AMSTCPPaket(AMSNetId targetAmsNetId, AMSPort targetAmsPort, AMSNetId sourceAmsNetId, AMSPort sourceAmsPort, State stateId, Invoke invokeId) {
         if (!getClass().isAnnotationPresent(ADSCommandType.class)) {
             throw new IllegalArgumentException(ADSCommandType.class + " need to be present.");
         }
-        this.amsHeader = CalculatedAMSHeader.of(
-            targetAmsNetId,
-            targetAmsPort,
-            sourceAmsNetId,
-            sourceAmsPort,
-            getClass().getAnnotation(ADSCommandType.class).value(),
-            stateId,
-            () -> DataLength.of(getAdsData().getCalculatedLength()),
-            invokeId);
-        this.amstcpHeader = CalculatedAMSTCPHeader.of(amsHeader, () -> getAdsData().getCalculatedLength());
+        this.amsHeader = AMSHeader.of(
+            requireNonNull(targetAmsNetId),
+            requireNonNull(targetAmsPort),
+            requireNonNull(sourceAmsNetId),
+            requireNonNull(sourceAmsPort),
+            requireNonNull(getClass().getAnnotation(ADSCommandType.class).value()),
+            requireNonNull(stateId),
+            () -> getAdsData().getCalculatedLength(),
+            requireNonNull(AMSError.NONE),
+            requireNonNull(invokeId));
+        this.amstcpHeader = AMSTCPHeader.of(amsHeader, () -> getAdsData().getCalculatedLength());
     }
 
     public AMSTCPHeader getAmstcpHeader() {
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
deleted file mode 100644
index 92134cb..0000000
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSHeader.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.plc4x.java.ads.api.generic.calculated;
-
-import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.ads.api.generic.AMSHeader;
-import org.apache.plc4x.java.ads.api.generic.types.*;
-
-import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
-
-public class CalculatedAMSHeader extends AMSHeader {
-
-    protected final LengthSupplier lengthSupplier;
-
-    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, Command commandId, State stateId, LengthSupplier lengthSupplier, Invoke invokeId) {
-        return new CalculatedAMSHeader(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, commandId, stateId, lengthSupplier, invokeId);
-    }
-
-    public interface LengthSupplier {
-        DataLength getLength();
-    }
-
-    @Override
-    public ByteBuf getByteBuf() {
-        return buildByteBuff(
-            targetAmsNetId,
-            targetAmsPort,
-            sourceAmsNetId,
-            sourceAmsPort,
-            commandId,
-            stateFlags,
-            lengthSupplier.getLength(),
-            code,
-            invokeId);
-    }
-
-    @Override
-    public String toString() {
-        return "CalculatedAMSHeader{" +
-            "targetAmsNetId=" + targetAmsNetId +
-            ", targetAmsPort=" + targetAmsPort +
-            ", sourceAmsNetId=" + sourceAmsNetId +
-            ", sourceAmsPort=" + sourceAmsPort +
-            ", commandId=" + commandId +
-            ", stateFlags=" + stateFlags +
-            ", dataLength=" + lengthSupplier.getLength() +
-            ", code=" + code +
-            ", invokeId=" + invokeId +
-            '}';
-    }
-}
diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
deleted file mode 100644
index 5afcd99..0000000
--- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/generic/calculated/CalculatedAMSTCPHeader.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.plc4x.java.ads.api.generic.calculated;
-
-import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.ads.api.generic.AMSTCPHeader;
-import org.apache.plc4x.java.ads.api.generic.types.Length;
-import org.apache.plc4x.java.ads.api.util.LengthSupplier;
-
-import static org.apache.plc4x.java.ads.api.util.ByteReadableUtils.buildByteBuff;
-
-/**
- * AMS/TCP Header	6 bytes	contains the length of the data packet.
- * This Header is caluclated. Can be used when sending.
- */
-public class CalculatedAMSTCPHeader extends AMSTCPHeader {
-
-    protected final LengthSupplier[] lengthSupplier;
-
-    protected CalculatedAMSTCPHeader(LengthSupplier... lengthSupplier) {
-        super(null);
-        this.lengthSupplier = lengthSupplier;
-    }
-
-    public static CalculatedAMSTCPHeader of(LengthSupplier... lengthSupplier) {
-        return new CalculatedAMSTCPHeader(lengthSupplier);
-    }
-
-    @Override
-    public ByteBuf getByteBuf() {
-        return buildByteBuff(reserved, Length.of(getCalculatedLength()));
-    }
-
-    @Override
-    public long getCalculatedLength() {
-        long aggregateLength = 0;
-        for (LengthSupplier supplier : lengthSupplier) {
-            aggregateLength += supplier.getCalculatedLength();
-        }
-        return aggregateLength;
-    }
-
-    @Override
-    public String toString() {
-        return "CalculatedAMSTCPHeader{" +
-            "reserved=" + reserved +
-            ", length=" + getCalculatedLength() +
-            '}';
-    }
-}
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 8a80d55..95f90f5 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
@@ -115,7 +115,7 @@ public class Plc4XADSProtocol extends MessageToMessageCodec<AMSTCPPaket, PlcRequ
         byte[] bytes = byteArrayOutputStream.toByteArray();
         Length length = Length.of(bytes.length);
         Data data = Data.of(bytes);
-        AMSTCPPaket amstcpPaket = ADSWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, length, data);
+        AMSTCPPaket amstcpPaket = ADSWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
         out.add(amstcpPaket);
     }
 
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 7846ba8..f9881f0 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
@@ -23,7 +23,6 @@ import org.apache.plc4x.java.ads.api.commands.ADSWriteRequest;
 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.types.AMSNetId;
 import org.apache.plc4x.java.ads.api.generic.types.AMSPort;
 import org.apache.plc4x.java.ads.api.generic.types.Invoke;
@@ -63,7 +62,6 @@ public class ADSDumper {
                 Invoke.of(0),
                 IndexGroup.of(1),
                 IndexOffset.of(3),
-                Length.of(randomString.getBytes().length),
                 Data.of(randomString.getBytes())
             );
 
diff --git a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/netty/ADSProtocolTest.java b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/netty/ADSProtocolTest.java
index a6d12f2..d5e0a2f 100644
--- a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/netty/ADSProtocolTest.java
+++ b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/netty/ADSProtocolTest.java
@@ -78,15 +78,13 @@ public class ADSProtocolTest {
             ),
             ADSDeviceNotificationRequest.of(
                 targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId,
-                // TODO: must be calculated when using this constructor
-                Length.of(32),
                 Stamps.of(1),
                 Collections.singletonList(
                     // Nano times need to be offset by (1.1.1970 - 1.1.1601) years in nanos
                     AdsStampHeader.of(TimeStamp.of(System.nanoTime()),
                         Samples.of(1),
                         Collections.singletonList(
-                            AdsNotificationSample.of(NotificationHandle.of(0), SampleSize.of(data.getCalculatedLength()), data))
+                            AdsNotificationSample.of(NotificationHandle.of(0), data))
                     )
                 )
             ),
@@ -113,7 +111,6 @@ public class ADSProtocolTest {
             ADSReadResponse.of(
                 targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId,
                 Result.of(0),
-                Length.of(data.getCalculatedLength()),
                 data
             ),
             ADSReadStateRequest.of(
@@ -128,20 +125,17 @@ public class ADSProtocolTest {
                 IndexGroup.of(0),
                 IndexOffset.of(0),
                 ReadLength.of(data.getCalculatedLength()),
-                WriteLength.of(data.getCalculatedLength()),
                 data
             ),
             ADSReadWriteResponse.of(
                 targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId,
                 Result.of(0),
-                Length.of(data.getCalculatedLength()),
                 data
             ),
             ADSWriteControlRequest.of(
                 targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId,
                 ADSState.of(0xaffe),
                 DeviceState.of(0xaffe),
-                Length.of(data.getCalculatedLength()),
                 data
             ),
             ADSWriteControlResponse.of(
@@ -152,7 +146,6 @@ public class ADSProtocolTest {
                 targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId,
                 IndexGroup.of(0),
                 IndexOffset.of(0),
-                Length.of(data.getCalculatedLength()),
                 data
             ),
             ADSWriteResponse.of(

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