You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/02/18 15:23:39 UTC

[plc4x] branch develop updated (647d298 -> f8e019f)

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

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


    from 647d298  Merge pull request #120 from apache/opcua-integration
     new 069e910  - Removed tabs from the email templates
     new f6c8d1c  - Re-enabled the OPC-UA driver in the integrations and the examples
     new 740c975  - Restored the hello world example
     new f8e019f  - Implemented the automatic splitting of s7 requests (read and write)

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


Summary of changes:
 .../apache/plc4x/java/s7/readwrite/S7Driver.java   |   9 ++
 .../java/s7/readwrite/context/S7DriverContext.java | 135 ++++++++++++++++
 .../java/s7/readwrite/optimizer/S7Optimizer.java   | 174 +++++++++++++++++++++
 .../s7/readwrite/protocol/S7ProtocolLogic.java     | 142 +++--------------
 .../plc4x/java/examples/helloplc4x/HelloPlc4x.java |  28 ++--
 plc4j/examples/pom.xml                             |   6 +-
 plc4j/integrations/apache-kafka/pom.xml            |   6 +-
 .../apache-nifi/nifi-plc4x-nar/pom.xml             |   6 +-
 plc4j/integrations/logstash-plugin/pom.xml         |   6 +-
 .../apache/plc4x/java/spi/Plc4xProtocolBase.java   |  11 ++
 .../java/spi/configuration/HasConfiguration.java   |   2 -
 .../connection/SingleProtocolStackConfigurer.java  |  15 +-
 .../plc4x/java/spi/context/DriverContext.java}     |   4 +-
 .../plc4x/java/spi/optimizer/BaseOptimizer.java    |  19 ++-
 .../java/spi/optimizer/SingleFieldOptimizer.java   |   5 +-
 src/site/asciidoc/developers/release/release.adoc  |  26 ++-
 16 files changed, 423 insertions(+), 171 deletions(-)
 create mode 100644 plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/context/S7DriverContext.java
 create mode 100644 plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
 copy plc4j/{utils/test-utils/src/main/java/org/apache/plc4x/test/FastTests.java => spi/src/main/java/org/apache/plc4x/java/spi/context/DriverContext.java} (90%)


[plc4x] 01/04: - Removed tabs from the email templates

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 069e910b0c744eb3a2e26f5ee58bb49fe39e5d6c
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Feb 18 13:20:15 2020 +0100

    - Removed tabs from the email templates
---
 src/site/asciidoc/developers/release/release.adoc | 26 +++++++++++------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/src/site/asciidoc/developers/release/release.adoc b/src/site/asciidoc/developers/release/release.adoc
index da13df8..7bfe709 100644
--- a/src/site/asciidoc/developers/release/release.adoc
+++ b/src/site/asciidoc/developers/release/release.adoc
@@ -398,15 +398,15 @@ As it is sometimes to do the vote counting, if voting and discussions are going
 
 [subs="verbatim,attributes"]
 ----
-   E-Mail Topic:
-   [DISCUSS] Apache PLC4X {current-full-version} RC1
+E-Mail Topic:
+[DISCUSS] Apache PLC4X {current-full-version} RC1
 
-   Message:
-   This is the discussion thread for the corresponding VOTE thread.
+Message:
+This is the discussion thread for the corresponding VOTE thread.
 
-   Please keep discussions in this thread to simplify the counting of votes.
+Please keep discussions in this thread to simplify the counting of votes.
 
-   If you have to vote -1 please mention a brief description on why and then take the details to this thread.
+If you have to vote -1 please mention a brief description on why and then take the details to this thread.
 ----
 
 Now we have to wait 72 hours till we can announce the result of the vote.
@@ -423,9 +423,7 @@ E-Mail Topic:
 [RESULT] [VOTE] Apache PLC4X {current-full-version} RC1
 
 Message:
-So, the vote passes with 3 +1 votes by PMC members and one +1 vote by a non PMC member.
-
-{Release Manager Name}
+So, the vote passes with {number of +1 votes} +1 votes by PMC members {number of +1 votes from non-pmc members} +1 vote by a non PMC member.
 ----
 
 === Releasing after a successful vote
@@ -524,18 +522,18 @@ After that it is time to announce your release to the world:
 
 [subs="verbatim,attributes"]
 ----
-    From:
+From:
 your apache email address
-    To:
+To:
 announce@apache.org
 
-    CC:
+CC:
 dev@plc4x.apache.org
 
-    E-Mail Topic:
+E-Mail Topic:
 [ANNOUNCE] Apache PLC4X {current-full-version} released
 
-    Message:
+Message:
 The Apache PLC4X team is pleased to announce the release of Apache PLC4X {current-full-version}
 
 PLC4X is a set of libraries for communicating with industrial programmable


[plc4x] 02/04: - Re-enabled the OPC-UA driver in the integrations and the examples

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f6c8d1c099fc5608034c5a31c88922afe24f4f72
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Feb 18 16:07:33 2020 +0100

    - Re-enabled the OPC-UA driver in the integrations and the examples
---
 plc4j/examples/pom.xml                                | 6 +++---
 plc4j/integrations/apache-kafka/pom.xml               | 6 +++---
 plc4j/integrations/apache-nifi/nifi-plc4x-nar/pom.xml | 6 +++---
 plc4j/integrations/logstash-plugin/pom.xml            | 6 +++---
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/plc4j/examples/pom.xml b/plc4j/examples/pom.xml
index b21493e..c3ec6cd 100644
--- a/plc4j/examples/pom.xml
+++ b/plc4j/examples/pom.xml
@@ -96,7 +96,7 @@
             <usedDependency>org.apache.plc4x:plc4j-driver-ethernet-ip</usedDependency-->
             <usedDependency>org.apache.plc4x:plc4j-driver-knxnetip</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-modbus</usedDependency>
-            <!--usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency-->
+            <usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
           </usedDependencies>
@@ -167,12 +167,12 @@
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
     </dependency>
-    <!--dependency>
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-opcua</artifactId>
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
-    </dependency-->
+    </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-s7</artifactId>
diff --git a/plc4j/integrations/apache-kafka/pom.xml b/plc4j/integrations/apache-kafka/pom.xml
index 218fb08..47f8d14 100644
--- a/plc4j/integrations/apache-kafka/pom.xml
+++ b/plc4j/integrations/apache-kafka/pom.xml
@@ -61,7 +61,7 @@
             <usedDependency>org.apache.plc4x:plc4j-driver-ethernet-ip</usedDependency-->
             <usedDependency>org.apache.plc4x:plc4j-driver-knxnetip</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-modbus</usedDependency>
-            <!--usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency-->
+            <usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
           </usedDependencies>
@@ -136,12 +136,12 @@
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
     </dependency>
-    <!--dependency>
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-opcua</artifactId>
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
-    </dependency-->
+    </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-s7</artifactId>
diff --git a/plc4j/integrations/apache-nifi/nifi-plc4x-nar/pom.xml b/plc4j/integrations/apache-nifi/nifi-plc4x-nar/pom.xml
index 79857aa..7d8fac3 100644
--- a/plc4j/integrations/apache-nifi/nifi-plc4x-nar/pom.xml
+++ b/plc4j/integrations/apache-nifi/nifi-plc4x-nar/pom.xml
@@ -54,7 +54,7 @@
               <usedDependency>org.apache.plc4x:plc4j-driver-ethernet-ip</usedDependency-->
               <usedDependency>org.apache.plc4x:plc4j-driver-knxnetip</usedDependency>
               <usedDependency>org.apache.plc4x:plc4j-driver-modbus</usedDependency>
-              <!--usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency-->
+              <usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency>
               <usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
               <usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
             </usedDependencies>
@@ -102,11 +102,11 @@
       <artifactId>plc4j-driver-modbus</artifactId>
       <version>0.7.0-SNAPSHOT</version>
     </dependency>
-    <!--dependency>
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-opcua</artifactId>
       <version>0.7.0-SNAPSHOT</version>
-    </dependency-->
+    </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-s7</artifactId>
diff --git a/plc4j/integrations/logstash-plugin/pom.xml b/plc4j/integrations/logstash-plugin/pom.xml
index 9eb71ce..7978134 100644
--- a/plc4j/integrations/logstash-plugin/pom.xml
+++ b/plc4j/integrations/logstash-plugin/pom.xml
@@ -202,7 +202,7 @@
                   <usedDependency>org.apache.plc4x:plc4j-driver-ethernet-ip</usedDependency-->
             <usedDependency>org.apache.plc4x:plc4j-driver-knxnetip</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-modbus</usedDependency>
-            <!--usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency-->
+            <usedDependency>org.apache.plc4x:plc4j-driver-opcua</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-s7</usedDependency>
             <usedDependency>org.apache.plc4x:plc4j-driver-simulated</usedDependency>
           </usedDependencies>
@@ -265,12 +265,12 @@
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
     </dependency>
-    <!--dependency>
+    <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-opcua</artifactId>
       <version>0.7.0-SNAPSHOT</version>
       <scope>runtime</scope>
-    </dependency-->
+    </dependency>
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-driver-s7</artifactId>


[plc4x] 03/04: - Restored the hello world example

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 740c97595eb370838ddf2b31f4c09db461673cea
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Feb 18 16:08:09 2020 +0100

    - Restored the hello world example
---
 .../plc4x/java/examples/helloplc4x/HelloPlc4x.java | 28 ++++++++++++----------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/plc4j/examples/hello-world-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java b/plc4j/examples/hello-world-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
index f1a3ef3..f9bed87 100644
--- a/plc4j/examples/hello-world-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
+++ b/plc4j/examples/hello-world-plc4x/src/main/java/org/apache/plc4x/java/examples/helloplc4x/HelloPlc4x.java
@@ -22,8 +22,6 @@ import org.apache.plc4x.java.PlcDriverManager;
 import org.apache.plc4x.java.api.PlcConnection;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
 import org.apache.plc4x.java.api.messages.PlcReadResponse;
-import org.apache.plc4x.java.api.messages.PlcWriteRequest;
-import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.slf4j.Logger;
@@ -60,9 +58,9 @@ public class HelloPlc4x {
 
             // Create a new read request:
             // - Give the single item requested the alias name "value"
-            /*PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
+            PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
             for (int i = 0; i < options.getFieldAddress().length; i++) {
-                builder.addItem("r-" + i, options.getFieldAddress()[i]);
+                builder.addItem("value-" + i, options.getFieldAddress()[i]);
             }
             PlcReadRequest readRequest = builder.build();
 
@@ -74,16 +72,22 @@ public class HelloPlc4x {
             PlcReadResponse syncResponse = readRequest.execute().get();
             // Simply iterating over the field names returned in the response.
             printResponse(syncResponse);
-            PlcValue asPlcValue = syncResponse.getAsPlcValue();
-            System.out.println(asPlcValue);*/
 
-            final PlcWriteRequest.Builder writeRequestBuilder = plcConnection.writeRequestBuilder();
-            writeRequestBuilder.addItem("w-1", options.getFieldAddress()[0], 23, 42, 7);
-            PlcWriteRequest writeRequest = writeRequestBuilder.build();
-            System.out.println(writeRequest);
+            PlcValue asPlcValue = syncResponse.getAsPlcValue();
+            System.out.println(asPlcValue);
 
-            logger.info("Synchronous write ...");
-            final PlcWriteResponse plcWriteResponse = writeRequest.execute().get();
+            //////////////////////////////////////////////////////////
+            // Read asynchronously ...
+            // Register a callback executed as soon as a response arrives.
+            logger.info("Asynchronous request ...");
+            CompletionStage<? extends PlcReadResponse> asyncResponse = readRequest.execute();
+            asyncResponse.whenComplete((readResponse, throwable) -> {
+                if (readResponse != null) {
+                    printResponse(readResponse);
+                } else {
+                    logger.error("An error occurred: " + throwable.getMessage(), throwable);
+                }
+            });
 
             // Give the async request a little time...
             TimeUnit.MILLISECONDS.sleep(1000);


[plc4x] 04/04: - Implemented the automatic splitting of s7 requests (read and write)

Posted by cd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f8e019f2af97c65f0286f84e3df37e8176913e2a
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Feb 18 16:23:33 2020 +0100

    - Implemented the automatic splitting of s7 requests (read and write)
---
 .../apache/plc4x/java/s7/readwrite/S7Driver.java   |   9 ++
 .../java/s7/readwrite/context/S7DriverContext.java | 135 ++++++++++++++++
 .../java/s7/readwrite/optimizer/S7Optimizer.java   | 174 +++++++++++++++++++++
 .../s7/readwrite/protocol/S7ProtocolLogic.java     | 142 +++--------------
 .../apache/plc4x/java/spi/Plc4xProtocolBase.java   |  11 ++
 .../java/spi/configuration/HasConfiguration.java   |   2 -
 .../connection/SingleProtocolStackConfigurer.java  |  15 +-
 .../plc4x/java/spi/context/DriverContext.java      |  22 +++
 .../plc4x/java/spi/optimizer/BaseOptimizer.java    |  19 ++-
 .../java/spi/optimizer/SingleFieldOptimizer.java   |   5 +-
 10 files changed, 403 insertions(+), 131 deletions(-)

diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
index 6d569b7..476c4c2 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/S7Driver.java
@@ -21,13 +21,16 @@ package org.apache.plc4x.java.s7.readwrite;
 import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.api.PlcDriver;
 import org.apache.plc4x.java.s7.readwrite.configuration.S7Configuration;
+import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
 import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO;
+import org.apache.plc4x.java.s7.readwrite.optimizer.S7Optimizer;
 import org.apache.plc4x.java.s7.readwrite.protocol.S7ProtocolLogic;
 import org.apache.plc4x.java.s7.readwrite.field.S7PlcFieldHandler;
 import org.apache.plc4x.java.spi.configuration.Configuration;
 import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
 import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
 import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
 import org.osgi.service.component.annotations.Component;
 
 import java.util.function.Consumer;
@@ -69,6 +72,11 @@ public class S7Driver extends GeneratedDriverBase<TPKTPacket> {
     }
 
     @Override
+    protected BaseOptimizer getOptimizer() {
+        return new S7Optimizer();
+    }
+
+    @Override
     protected S7PlcFieldHandler getFieldHandler() {
         return new S7PlcFieldHandler();
     }
@@ -77,6 +85,7 @@ public class S7Driver extends GeneratedDriverBase<TPKTPacket> {
     protected ProtocolStackConfigurer<TPKTPacket> getStackConfigurer() {
         return SingleProtocolStackConfigurer.builder(TPKTPacket.class, TPKTPacketIO.class)
             .withProtocol(S7ProtocolLogic.class)
+            .withDriverContext(S7DriverContext.class)
             .withPacketSizeEstimator(ByteLengthEstimator.class)
             .withCorruptPacketRemover(CorruptPackageCleaner.class)
             .build();
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/context/S7DriverContext.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/context/S7DriverContext.java
new file mode 100644
index 0000000..6f04c21
--- /dev/null
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/context/S7DriverContext.java
@@ -0,0 +1,135 @@
+/*
+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.s7.readwrite.context;
+
+import org.apache.plc4x.java.s7.readwrite.configuration.S7Configuration;
+import org.apache.plc4x.java.s7.readwrite.types.COTPTpduSize;
+import org.apache.plc4x.java.s7.readwrite.types.DeviceGroup;
+import org.apache.plc4x.java.s7.readwrite.types.S7ControllerType;
+import org.apache.plc4x.java.s7.readwrite.utils.S7TsapIdEncoder;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
+import org.apache.plc4x.java.spi.context.DriverContext;
+
+public class S7DriverContext implements DriverContext, HasConfiguration<S7Configuration> {
+
+    private int callingTsapId;
+    private int calledTsapId;
+    private COTPTpduSize cotpTpduSize;
+    private int pduSize;
+    private int maxAmqCaller;
+    private int maxAmqCallee;
+    private S7ControllerType controllerType;
+
+    @Override
+    public void setConfiguration(S7Configuration configuration) {
+        this.callingTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.OTHERS,
+            configuration.localRack, configuration.localSlot);
+        this.calledTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC,
+            configuration.remoteRack, configuration.remoteSlot);
+
+        this.controllerType = configuration.controllerType == null ? S7ControllerType.ANY : S7ControllerType.valueOf(configuration.controllerType);
+        // The Siemens LOGO device seems to only work with very limited settings,
+        // so we're overriding some of the defaults.
+        if (this.controllerType == S7ControllerType.LOGO && configuration.pduSize == 1024) {
+            configuration.pduSize = 480;
+        }
+
+        // Initialize the parameters with initial version (Will be updated during the login process)
+        this.cotpTpduSize = getNearestMatchingTpduSize((short) configuration.getPduSize());
+        // The PDU size is theoretically not bound by the COTP TPDU size, however having a larger
+        // PDU size would make the code extremely complex. But even if the protocol would allow this
+        // I have never seen this happen in reality. Making is smaller would unnecessarily limit the
+        // size, so we're setting it to the maximum that can be included.
+        this.pduSize = cotpTpduSize.getSizeInBytes() - 16;
+        this.maxAmqCaller = configuration.maxAmqCaller;
+        this.maxAmqCallee = configuration.maxAmqCallee;
+    }
+
+    public int getCallingTsapId() {
+        return callingTsapId;
+    }
+
+    public void setCallingTsapId(int callingTsapId) {
+        this.callingTsapId = callingTsapId;
+    }
+
+    public int getCalledTsapId() {
+        return calledTsapId;
+    }
+
+    public void setCalledTsapId(int calledTsapId) {
+        this.calledTsapId = calledTsapId;
+    }
+
+    public COTPTpduSize getCotpTpduSize() {
+        return cotpTpduSize;
+    }
+
+    public void setCotpTpduSize(COTPTpduSize cotpTpduSize) {
+        this.cotpTpduSize = cotpTpduSize;
+    }
+
+    public int getPduSize() {
+        return pduSize;
+    }
+
+    public void setPduSize(int pduSize) {
+        this.pduSize = pduSize;
+    }
+
+    public int getMaxAmqCaller() {
+        return maxAmqCaller;
+    }
+
+    public void setMaxAmqCaller(int maxAmqCaller) {
+        this.maxAmqCaller = maxAmqCaller;
+    }
+
+    public int getMaxAmqCallee() {
+        return maxAmqCallee;
+    }
+
+    public void setMaxAmqCallee(int maxAmqCallee) {
+        this.maxAmqCallee = maxAmqCallee;
+    }
+
+    public S7ControllerType getControllerType() {
+        return controllerType;
+    }
+
+    public void setControllerType(S7ControllerType controllerType) {
+        this.controllerType = controllerType;
+    }
+
+    /**
+     * Iterate over all values until one is found that the given tpdu size will fit.
+     *
+     * @param tpduSizeParameter requested tpdu size.
+     * @return smallest {@link COTPTpduSize} which will fit a given size of tpdu.
+     */
+    protected COTPTpduSize getNearestMatchingTpduSize(short tpduSizeParameter) {
+        for (COTPTpduSize value : COTPTpduSize.values()) {
+            if (value.getSizeInBytes() >= tpduSizeParameter) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
new file mode 100644
index 0000000..c8084a8
--- /dev/null
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
@@ -0,0 +1,174 @@
+/*
+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.s7.readwrite.optimizer;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.*;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.s7.readwrite.*;
+import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
+import org.apache.plc4x.java.s7.readwrite.field.S7Field;
+import org.apache.plc4x.java.s7.readwrite.types.MemoryArea;
+import org.apache.plc4x.java.s7.readwrite.types.TransportSize;
+import org.apache.plc4x.java.spi.context.DriverContext;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
+
+import java.util.*;
+
+public class S7Optimizer extends BaseOptimizer {
+
+    public static final int EMPTY_READ_REQUEST_SIZE = new S7MessageRequest(0, new S7ParameterReadVarRequest(
+        new S7VarRequestParameterItem[0]), new S7PayloadReadVarRequest()).getLengthInBytes();
+    public static final int EMPTY_READ_RESPONSE_SIZE = new S7MessageResponse(0, new S7ParameterReadVarResponse(
+        (short) 0), new S7PayloadReadVarResponse(new S7VarPayloadDataItem[0]), (short) 0, (short) 0).getLengthInBytes();
+    public static final int EMPTY_WRITE_REQUEST_SIZE = new S7MessageRequest(0, new S7ParameterWriteVarRequest(
+        new S7VarRequestParameterItem[0]), new S7PayloadWriteVarRequest(new S7VarPayloadDataItem[0])).getLengthInBytes();
+    public static final int EMPTY_WRITE_RESPONSE_SIZE = new S7MessageResponse(0, new S7ParameterWriteVarResponse(
+        (short) 0), new S7PayloadWriteVarResponse(new S7VarPayloadStatusItem[0]), (short) 0, (short) 0).getLengthInBytes();
+    public static final int S7_ADDRESS_ANY_SIZE = 2 +
+        new S7AddressAny(TransportSize.INT, 1, 1, MemoryArea.DATA_BLOCKS, 1, (byte) 0).getLengthInBytes();
+
+    @Override
+    protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest, DriverContext driverContext) {
+        S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
+        List<PlcRequest> processedRequests = new LinkedList<>();
+
+        // This calculates the size of the header for the request and response.
+        int curRequestSize = EMPTY_READ_REQUEST_SIZE;
+        // An empty response has the same size as an empty request.
+        int curResponseSize = EMPTY_READ_RESPONSE_SIZE;
+
+        // List of all items in the current request.
+        LinkedHashMap<String, PlcField> curFields = new LinkedHashMap<>();
+
+        for (String fieldName : readRequest.getFieldNames()) {
+            S7Field field = (S7Field) readRequest.getField(fieldName);
+
+            int readRequestItemSize = S7_ADDRESS_ANY_SIZE;
+            int readResponseItemSize = 4 + (field.getNumElements() * field.getDataType().getSizeInBytes());
+            // If it's an odd number of bytes, add one to make it even
+            if (readResponseItemSize % 2 == 1) {
+                readResponseItemSize++;
+            }
+
+            // If adding the item would not exceed the sizes, add it to the current request.
+            if (((curRequestSize + readRequestItemSize) <= s7DriverContext.getPduSize()) &&
+                ((curResponseSize + readResponseItemSize) <= s7DriverContext.getPduSize())) {
+                // Increase the current request sizes.
+                curRequestSize += readRequestItemSize;
+                curResponseSize += readResponseItemSize;
+
+                // Add the item.
+            }
+            // If they would exceed, start a new request.
+            else {
+                // Create a new PlcReadRequest containing the current field item.
+                processedRequests.add(new DefaultPlcReadRequest(
+                    ((DefaultPlcReadRequest) readRequest).getReader(), curFields));
+
+                // Reset the size and item lists.
+                curRequestSize = EMPTY_READ_REQUEST_SIZE;
+                curResponseSize = EMPTY_READ_RESPONSE_SIZE;
+                curFields = new LinkedHashMap<>();
+
+                // Splitting of huge fields not yet implemented, throw an exception instead.
+                if(((curRequestSize + readRequestItemSize) > s7DriverContext.getPduSize()) &&
+                    ((curResponseSize + readResponseItemSize) > s7DriverContext.getPduSize())) {
+                    throw new PlcRuntimeException("Field size exceeds maximum payload for one item.");
+                }
+            }
+            curFields.put(fieldName, field);
+        }
+
+        // Create a new PlcReadRequest from the remaining field items.
+        if(!curFields.isEmpty()) {
+            processedRequests.add(new DefaultPlcReadRequest(
+                ((DefaultPlcReadRequest) readRequest).getReader(), curFields));
+        }
+
+        return processedRequests;
+    }
+
+    @Override
+    protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
+        S7DriverContext s7DriverContext = (S7DriverContext) driverContext;
+        List<PlcRequest> processedRequests = new LinkedList<>();
+
+        // This calculates the size of the header for the request and response.
+        int curRequestSize = EMPTY_WRITE_REQUEST_SIZE;
+        // An empty response has the same size as an empty request.
+        int curResponseSize = EMPTY_WRITE_RESPONSE_SIZE;
+
+        // List of all items in the current request.
+        LinkedHashMap<String, Pair<PlcField, PlcValue>> curFields = new LinkedHashMap<>();
+
+        for (String fieldName : writeRequest.getFieldNames()) {
+            S7Field field = (S7Field) writeRequest.getField(fieldName);
+            PlcValue value = ((DefaultPlcWriteRequest) writeRequest).getPlcValue(fieldName);
+
+            int writeRequestItemSize = S7_ADDRESS_ANY_SIZE + (field.getNumElements() * field.getDataType().getSizeInBytes());
+            // If it's an odd number of bytes, add one to make it even
+            if (writeRequestItemSize % 2 == 1) {
+                writeRequestItemSize++;
+            }
+            int writeResponseItemSize = 4;
+
+            // If adding the item would not exceed the sizes, add it to the current request.
+            if (((curRequestSize + writeRequestItemSize) <= s7DriverContext.getPduSize()) &&
+                ((curResponseSize + writeResponseItemSize) <= s7DriverContext.getPduSize())) {
+                // Increase the current request sizes.
+                curRequestSize += writeRequestItemSize;
+                curResponseSize += writeResponseItemSize;
+
+                // Add the item.
+            }
+            // If they would exceed, start a new request.
+            else {
+                // Create a new PlcWriteRequest containing the current field item.
+                processedRequests.add(new DefaultPlcWriteRequest(
+                    ((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
+
+                // Reset the size and item lists.
+                curRequestSize = EMPTY_WRITE_REQUEST_SIZE;
+                curResponseSize = EMPTY_WRITE_RESPONSE_SIZE;
+                curFields = new LinkedHashMap<>();
+
+                // Splitting of huge fields not yet implemented, throw an exception instead.
+                if(((curRequestSize + writeRequestItemSize) > s7DriverContext.getPduSize()) &&
+                    ((curResponseSize + writeResponseItemSize) > s7DriverContext.getPduSize())) {
+                    throw new PlcRuntimeException("Field size exceeds maximum payload for one item.");
+                }
+            }
+            curFields.put(fieldName, Pair.of(field, value));
+        }
+
+        // Create a new PlcWriteRequest from the remaining field items.
+        if(!curFields.isEmpty()) {
+            processedRequests.add(new DefaultPlcWriteRequest(
+                ((DefaultPlcWriteRequest) writeRequest).getWriter(), curFields));
+        }
+
+        return processedRequests;
+    }
+
+}
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index d83939d..ff12050 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -23,7 +23,6 @@ import io.netty.buffer.Unpooled;
 import io.vavr.control.Either;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.plc4x.java.api.exceptions.PlcException;
 import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.api.messages.PlcReadRequest;
@@ -72,22 +71,19 @@ import org.apache.plc4x.java.s7.readwrite.S7VarRequestParameterItemAddress;
 import org.apache.plc4x.java.s7.readwrite.SzlDataTreeItem;
 import org.apache.plc4x.java.s7.readwrite.SzlId;
 import org.apache.plc4x.java.s7.readwrite.TPKTPacket;
-import org.apache.plc4x.java.s7.readwrite.configuration.S7Configuration;
+import org.apache.plc4x.java.s7.readwrite.context.S7DriverContext;
 import org.apache.plc4x.java.s7.readwrite.io.DataItemIO;
-import org.apache.plc4x.java.s7.readwrite.optimizer.S7MessageProcessor;
 import org.apache.plc4x.java.s7.readwrite.types.COTPProtocolClass;
 import org.apache.plc4x.java.s7.readwrite.types.COTPTpduSize;
 import org.apache.plc4x.java.s7.readwrite.types.DataTransportErrorCode;
 import org.apache.plc4x.java.s7.readwrite.types.DataTransportSize;
-import org.apache.plc4x.java.s7.readwrite.types.DeviceGroup;
 import org.apache.plc4x.java.s7.readwrite.types.S7ControllerType;
 import org.apache.plc4x.java.s7.readwrite.types.SzlModuleTypeClass;
 import org.apache.plc4x.java.s7.readwrite.types.SzlSublist;
 import org.apache.plc4x.java.s7.readwrite.field.S7Field;
-import org.apache.plc4x.java.s7.readwrite.utils.S7TsapIdEncoder;
 import org.apache.plc4x.java.spi.ConversationContext;
-import org.apache.plc4x.java.spi.configuration.HasConfiguration;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.generation.ParseException;
 import org.apache.plc4x.java.spi.generation.ReadBuffer;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
@@ -103,7 +99,6 @@ import org.slf4j.LoggerFactory;
 
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -118,47 +113,19 @@ import java.util.function.Consumer;
  * So we need to limit those.
  * Thus, each request goes to a Work Queue and this Queue ensures, that only 3 are open at the same time.
  */
-public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements HasConfiguration<S7Configuration> {
+public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
 
     private static final Logger logger = LoggerFactory.getLogger(S7ProtocolLogic.class);
     public static final Duration REQUEST_TIMEOUT = Duration.ofMillis(10000);
 
-    private int callingTsapId;
-    private int calledTsapId;
-    private COTPTpduSize cotpTpduSize;
-    private int pduSize;
-    private int maxAmqCaller;
-    private int maxAmqCallee;
-    private S7ControllerType controllerType;
-
+    private S7DriverContext driverContext;
     private static final AtomicInteger tpduGenerator = new AtomicInteger(10);
     private RequestTransactionManager tm;
 
-    private S7MessageProcessor processor = null;
-
     @Override
-    public void setConfiguration(S7Configuration configuration) {
-        this.callingTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.OTHERS,
-            configuration.localRack, configuration.localSlot);
-        this.calledTsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC,
-            configuration.remoteRack, configuration.remoteSlot);
-
-        this.controllerType = configuration.controllerType == null ? S7ControllerType.ANY : S7ControllerType.valueOf(configuration.controllerType);
-        // The Siemens LOGO device seems to only work with very limited settings,
-        // so we're overriding some of the defaults.
-        if (this.controllerType == S7ControllerType.LOGO && configuration.pduSize == 1024) {
-            configuration.pduSize = 480;
-        }
-
-        // Initialize the parameters with initial version (Will be updated during the login process)
-        this.cotpTpduSize = getNearestMatchingTpduSize((short) configuration.getPduSize());
-        // The PDU size is theoretically not bound by the COTP TPDU size, however having a larger
-        // PDU size would make the code extremely complex. But even if the protocol would allow this
-        // I have never seen this happen in reality. Making is smaller would unnecessarily limit the
-        // size, so we're setting it to the maximum that can be included.
-        this.pduSize = cotpTpduSize.getSizeInBytes() - 16;
-        this.maxAmqCaller = configuration.maxAmqCaller;
-        this.maxAmqCallee = configuration.maxAmqCallee;
+    public void setDriverContext(DriverContext driverContext) {
+        super.setDriverContext(driverContext);
+        this.driverContext = (S7DriverContext) driverContext;
 
         // Initialize Transaction Manager.
         // Until the number of concurrent requests is successfully negotiated we set it to a
@@ -166,17 +133,14 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
         // No concurrent requests can be sent anyway. It will be updated when receiving the
         // S7ParameterSetupCommunication response.
         this.tm = new RequestTransactionManager(1);
-
-        // REMARK: Perhaps make this configurable.
-        // TODO: Comment in to enable ...
-        //this.processor = new DefaultS7MessageProcessor(tpduGenerator);
     }
 
     @Override
     public void onConnect(ConversationContext<TPKTPacket> context) {
         logger.debug("Sending COTP Connection Request");
         // Open the session on ISO Transport Protocol first.
-        TPKTPacket packet = new TPKTPacket(createCOTPConnectionRequest(calledTsapId, callingTsapId, cotpTpduSize));
+        TPKTPacket packet = new TPKTPacket(createCOTPConnectionRequest(
+            driverContext.getCalledTsapId(), driverContext.getCallingTsapId(), driverContext.getCotpTpduSize()));
 
         context.sendRequest(packet)
             .expectResponse(TPKTPacket.class, REQUEST_TIMEOUT)
@@ -196,20 +160,20 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
                     .handle(setupCommunication -> {
                         logger.debug("Got S7 Connection Response");
                         // Save some data from the response.
-                        maxAmqCaller = setupCommunication.getMaxAmqCaller();
-                        maxAmqCallee = setupCommunication.getMaxAmqCallee();
-                        pduSize = setupCommunication.getPduLength();
+                        driverContext.setMaxAmqCaller(setupCommunication.getMaxAmqCaller());
+                        driverContext.setMaxAmqCallee(setupCommunication.getMaxAmqCallee());
+                        driverContext.setPduSize(setupCommunication.getPduLength());
 
                         // Update the number of concurrent requests to the negotiated number.
                         // I have never seen anything else than equal values for caller and
                         // callee, but if they were different, we're only limiting the outgoing
                         // requests.
-                        tm.setNumberOfConcurrentRequests(maxAmqCaller);
+                        tm.setNumberOfConcurrentRequests(driverContext.getMaxAmqCallee());
 
                         // If the controller type is explicitly set, were finished with the login
                         // process. If it's set to ANY, we have to query the serial number information
                         // in order to detect the type of PLC.
-                        if (controllerType != S7ControllerType.ANY) {
+                        if (driverContext.getControllerType() != S7ControllerType.ANY) {
                             // Send an event that connection setup is complete.
                             context.fireConnected();
                             return;
@@ -236,7 +200,6 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
 
     @Override
     public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
-        CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
         DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
         List<S7VarRequestParameterItem> requestItems = new ArrayList<>(request.getNumberOfFields());
         for (PlcField field : request.getFields()) {
@@ -249,51 +212,8 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
             new S7ParameterReadVarRequest(requestItems.toArray(new S7VarRequestParameterItem[0])),
             new S7PayloadReadVarRequest());
 
-        // If no processor is provided the request is output as-is without any modification.
-        if (processor == null) {
-            // Just send a single response and chain it as Response
-            return toPlcReadResponse((InternalPlcReadRequest) readRequest, readInternal(s7MessageRequest));
-        }
-
-        try {
-            // Do the preprocessing and eventually split up into multiple requests.
-            final Collection<S7MessageRequest> s7MessageRequests = processor.processRequest(s7MessageRequest, pduSize);
-
-            // Only if more than one sub-request is returned, do something special ...
-            // otherwise just do the normal sending.
-            if (s7MessageRequests.size() == 1) {
-                return toPlcReadResponse((InternalPlcReadRequest) readRequest, readInternal(s7MessageRequest));
-            }
-
-            /////////////////////////////////////////////////////////////////
-            //  Here we are in the case that we have multiple requests,
-            //  so we need splitting
-            /////////////////////////////////////////////////////////////////
-            ParentFuture multiRequestFuture = new ParentFuture(
-                result -> {
-                    try {
-                        final S7MessageResponse s7MessageResponse =
-                            processor.processResponse(s7MessageRequest, result);
-                        final PlcReadResponse plcReadResponse = (PlcReadResponse)
-                            decodeReadResponse(s7MessageResponse, ((InternalPlcReadRequest) readRequest));
-                        future.complete(plcReadResponse);
-                    } catch (PlcException e) {
-                        logger.error("Something went wrong", e);
-                    }
-                });
-            for (S7MessageRequest messageRequest : s7MessageRequests) {
-                ChildFuture childFuture = new ChildFuture(messageRequest);
-                multiRequestFuture.addChildFuture(childFuture);
-
-                readInternal(messageRequest)
-                    // Forward everything to the remaining future
-                    .handle((res, ex) -> res != null ? childFuture.complete(res) : childFuture.completeExceptionally(ex));
-            }
-            return multiRequestFuture;
-        } catch (PlcException e) {
-            logger.error("Something went wrong", e);
-        }
-        return null;
+        // Just send a single response and chain it as Response
+        return toPlcReadResponse((InternalPlcReadRequest) readRequest, readInternal(s7MessageRequest));
     }
 
     /** Maps the S7ReadResponse of a PlcReadRequest to a PlcReadRespoonse */
@@ -404,7 +324,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
                     continue;
                 }
                 final String articleNumber = new String(readSzlResponseItemItem.getMlfb());
-                controllerType = decodeControllerType(articleNumber);
+                driverContext.setControllerType(decodeControllerType(articleNumber));
 
                 // Send an event that connection setup is complete.
                 context.fireConnected();
@@ -426,16 +346,16 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
         for (COTPParameter parameter : cotpPacketConnectionResponse.getParameters()) {
             if (parameter instanceof COTPParameterCalledTsap) {
                 COTPParameterCalledTsap cotpParameterCalledTsap = (COTPParameterCalledTsap) parameter;
-                calledTsapId = cotpParameterCalledTsap.getTsapId();
+                driverContext.setCalledTsapId(cotpParameterCalledTsap.getTsapId());
             } else if (parameter instanceof COTPParameterCallingTsap) {
                 COTPParameterCallingTsap cotpParameterCallingTsap = (COTPParameterCallingTsap) parameter;
-                if(cotpParameterCallingTsap.getTsapId() != callingTsapId) {
-                    callingTsapId = cotpParameterCallingTsap.getTsapId();
-                    logger.warn(String.format("Switching calling TSAP id to '%s'", callingTsapId));
+                if(cotpParameterCallingTsap.getTsapId() != driverContext.getCallingTsapId()) {
+                    driverContext.setCallingTsapId(cotpParameterCallingTsap.getTsapId());
+                    logger.warn(String.format("Switching calling TSAP id to '%s'", driverContext.getCallingTsapId()));
                 }
             } else if (parameter instanceof COTPParameterTpduSize) {
                 COTPParameterTpduSize cotpParameterTpduSize = (COTPParameterTpduSize) parameter;
-                cotpTpduSize = cotpParameterTpduSize.getTpduSize();
+                driverContext.setCotpTpduSize(cotpParameterTpduSize.getTpduSize());
             } else {
                 logger.warn(String.format("Got unknown parameter type '%s'", parameter.getClass().getName()));
             }
@@ -443,7 +363,8 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
 
         // Send an S7 login message.
         S7ParameterSetupCommunication s7ParameterSetupCommunication =
-            new S7ParameterSetupCommunication(maxAmqCaller, maxAmqCallee, pduSize);
+            new S7ParameterSetupCommunication(
+                driverContext.getMaxAmqCaller(), driverContext.getMaxAmqCallee(), driverContext.getPduSize());
         S7Message s7Message = new S7MessageRequest(0, s7ParameterSetupCommunication,
             new S7PayloadSetupCommunication());
         COTPPacketData cotpPacketData = new COTPPacketData(null, s7Message, true, (short) 1);
@@ -608,21 +529,6 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> implements Ha
             s7Field.getMemoryArea(), s7Field.getByteOffset(), s7Field.getBitOffset());
     }
 
-    /**
-     * Iterate over all values until one is found that the given tpdu size will fit.
-     *
-     * @param tpduSizeParameter requested tpdu size.
-     * @return smallest {@link COTPTpduSize} which will fit a given size of tpdu.
-     */
-    protected COTPTpduSize getNearestMatchingTpduSize(short tpduSizeParameter) {
-        for (COTPTpduSize value : COTPTpduSize.values()) {
-            if (value.getSizeInBytes() >= tpduSizeParameter) {
-                return value;
-            }
-        }
-        return null;
-    }
-
     private static class ChildFuture extends CompletableFuture<S7MessageResponse> {
 
         private final S7MessageRequest request;
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
index e2c23fb..d6bca70 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/Plc4xProtocolBase.java
@@ -28,6 +28,7 @@ import org.apache.plc4x.java.api.messages.PlcUnsubscriptionRequest;
 import org.apache.plc4x.java.api.messages.PlcUnsubscriptionResponse;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteResponse;
+import org.apache.plc4x.java.spi.context.DriverContext;
 
 import java.util.concurrent.CompletableFuture;
 
@@ -35,6 +36,16 @@ public abstract class Plc4xProtocolBase<T> {
 
     protected ConversationContext<T> context;
 
+    protected DriverContext driverContext;
+
+    public void setDriverContext(DriverContext driverContext) {
+        this.driverContext = driverContext;
+    }
+
+    public DriverContext getDriverContext() {
+        return driverContext;
+    }
+
     public void setContext(ConversationContext<T> context) {
         this.context = context;
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/configuration/HasConfiguration.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/configuration/HasConfiguration.java
index 0f84505..c5d306c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/configuration/HasConfiguration.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/configuration/HasConfiguration.java
@@ -19,8 +19,6 @@
 
 package org.apache.plc4x.java.spi.configuration;
 
-import org.apache.plc4x.java.spi.configuration.Configuration;
-
 /**
  * (Marker) Interface which can be used to tell PLC4X that a class (that is instantiated by PLC4X)
  * has a Configuration.
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
index 9787220..3f01cb6 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
@@ -28,6 +28,7 @@ import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
 import org.apache.plc4x.java.spi.Plc4xNettyWrapper;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
 import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.exceptions.InternalPlcRuntimeException;
 import org.apache.plc4x.java.spi.generation.Message;
 import org.apache.plc4x.java.spi.generation.MessageIO;
@@ -44,6 +45,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
     private final Class<BASE_PACKET_CLASS> basePacketClass;
     private boolean bigEndian = true;
     private final Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocolClass;
+    private final Class<? extends DriverContext> driverContextClass;
     private final MessageIO<BASE_PACKET_CLASS, BASE_PACKET_CLASS> protocolIO;
     private final Class<? extends ToIntFunction<ByteBuf>> packetSizeEstimatorClass;
     private final Class<? extends Consumer<ByteBuf>> corruptPacketRemoverClass;
@@ -58,6 +60,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
                                   boolean bigEndian,
                                   Object[] parserArgs,
                                   Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocol,
+                                  Class<? extends DriverContext> driverContextClass,
                                   MessageIO<BASE_PACKET_CLASS, BASE_PACKET_CLASS> protocolIO,
                                   Class<? extends ToIntFunction<ByteBuf>> packetSizeEstimatorClass,
                                   Class<? extends Consumer<ByteBuf>> corruptPacketRemoverClass) {
@@ -65,6 +68,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
         this.bigEndian = bigEndian;
         this.parserArgs = parserArgs;
         this.protocolClass = protocol;
+        this.driverContextClass = driverContextClass;
         this.protocolIO = protocolIO;
         this.packetSizeEstimatorClass = packetSizeEstimatorClass;
         this.corruptPacketRemoverClass = corruptPacketRemoverClass;
@@ -82,6 +86,9 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
             Configuration configuration, ChannelPipeline pipeline) {
         pipeline.addLast(getMessageCodec(configuration));
         Plc4xProtocolBase<BASE_PACKET_CLASS> protocol = configure(configuration, createInstance(protocolClass));
+        if(driverContextClass != null) {
+            protocol.setDriverContext(configure(configuration, createInstance(driverContextClass)));
+        }
         Plc4xNettyWrapper<BASE_PACKET_CLASS> context = new Plc4xNettyWrapper<>(pipeline, protocol, basePacketClass);
         pipeline.addLast(context);
         return protocol;
@@ -108,6 +115,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
 
         private final Class<BASE_PACKET_CLASS> basePacketClass;
         private final Class<? extends MessageIO<BASE_PACKET_CLASS, BASE_PACKET_CLASS>> messageIoClass;
+        private Class<? extends DriverContext> driverContextClass;
         private boolean bigEndian = true;
         private Object[] parserArgs;
         private Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocol;
@@ -119,6 +127,11 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
             this.messageIoClass = messageIoClass;
         }
 
+        public SingleProtocolStackBuilder<BASE_PACKET_CLASS> withDriverContext(Class<? extends DriverContext> driverContextClass) {
+            this.driverContextClass = driverContextClass;
+            return this;
+        }
+
         public SingleProtocolStackBuilder<BASE_PACKET_CLASS> littleEndian() {
             this.bigEndian = false;
             return this;
@@ -149,7 +162,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
             try {
                 final MessageIO messageIo = messageIoClass.getDeclaredConstructor().newInstance();
                 return new SingleProtocolStackConfigurer<>(
-                    basePacketClass, bigEndian, parserArgs, protocol, messageIo, packetSizeEstimator, corruptPacketRemover);
+                    basePacketClass, bigEndian, parserArgs, protocol, driverContextClass, messageIo, packetSizeEstimator, corruptPacketRemover);
             } catch (InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
                 throw new PlcRuntimeException("Error initializing MessageIO instance", e);
             }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/context/DriverContext.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/context/DriverContext.java
new file mode 100644
index 0000000..7308f13
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/context/DriverContext.java
@@ -0,0 +1,22 @@
+/*
+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.spi.context;
+
+public interface DriverContext {
+}
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
index c91886a..9d93d47 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.api.messages.*;
 import org.apache.plc4x.java.api.types.PlcResponseCode;
 import org.apache.plc4x.java.api.value.PlcValue;
 import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse;
 import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse;
 import org.apache.plc4x.java.spi.messages.InternalPlcReadRequest;
@@ -36,7 +37,7 @@ import java.util.function.Function;
 
 public abstract class BaseOptimizer {
 
-    protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest) {
+    protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest, DriverContext driverContext) {
         return Collections.singletonList(readRequest);
     }
 
@@ -59,7 +60,7 @@ public abstract class BaseOptimizer {
         return new DefaultPlcReadResponse((InternalPlcReadRequest) readRequest, fields);
     }
 
-    protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest) {
+    protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
         return Collections.singletonList(writeRequest);
     }
 
@@ -80,7 +81,8 @@ public abstract class BaseOptimizer {
         return new DefaultPlcWriteResponse((InternalPlcWriteRequest) writeRequest, fields);
     }
 
-    protected List<PlcRequest> processSubscriptionRequest(PlcSubscriptionRequest subscriptionRequest) {
+    protected List<PlcRequest> processSubscriptionRequest(PlcSubscriptionRequest subscriptionRequest,
+                                                          DriverContext driverContext) {
         return Collections.singletonList(subscriptionRequest);
     }
 
@@ -90,7 +92,8 @@ public abstract class BaseOptimizer {
         return null;
     }
 
-    protected List<PlcRequest> processUnsubscriptionRequest(PlcRequest unsubscriptionRequest) {
+    protected List<PlcRequest> processUnsubscriptionRequest(PlcRequest unsubscriptionRequest,
+                                                            DriverContext driverContext) {
         return Collections.singletonList(unsubscriptionRequest);
     }
 
@@ -101,27 +104,27 @@ public abstract class BaseOptimizer {
     }
 
     public CompletableFuture<PlcReadResponse> optimizedRead(PlcReadRequest readRequest, Plc4xProtocolBase reader) {
-        List<PlcRequest> subRequests = processReadRequest(readRequest);
+        List<PlcRequest> subRequests = processReadRequest(readRequest, reader.getDriverContext());
         return send(readRequest, subRequests, request -> reader.read((PlcReadRequest) request),
             response -> processReadResponses(readRequest, response));
     }
 
     public CompletableFuture<PlcWriteResponse> optimizedWrite(PlcWriteRequest writeRequest, Plc4xProtocolBase writer) {
-        List<PlcRequest> subRequests = processWriteRequest(writeRequest);
+        List<PlcRequest> subRequests = processWriteRequest(writeRequest, writer.getDriverContext());
         return send(writeRequest, subRequests, request -> writer.write((PlcWriteRequest) request),
             response -> processWriteResponses(writeRequest, response));
     }
 
     public CompletableFuture<PlcSubscriptionResponse> optimizedSubscribe(
             PlcSubscriptionRequest subscriptionRequest, Plc4xProtocolBase subscriber) {
-        List<PlcRequest> subRequests = processSubscriptionRequest(subscriptionRequest);
+        List<PlcRequest> subRequests = processSubscriptionRequest(subscriptionRequest, subscriber.getDriverContext());
         return send(subscriptionRequest, subRequests, request -> subscriber.subscribe((PlcSubscriptionRequest) request),
             response -> processSubscriptionResponses(subscriptionRequest, response));
     }
 
     public CompletableFuture<PlcUnsubscriptionResponse> optmizedUnsubscribe(
             PlcUnsubscriptionRequest unsubscriptionRequest, Plc4xProtocolBase subscriber) {
-        List<PlcRequest> subRequests = processUnsubscriptionRequest(unsubscriptionRequest);
+        List<PlcRequest> subRequests = processUnsubscriptionRequest(unsubscriptionRequest, subscriber.getDriverContext());
         return send(unsubscriptionRequest, subRequests, request -> subscriber.unsubscribe((PlcUnsubscriptionRequest) request),
             response -> processUnsubscriptionResponses(unsubscriptionRequest, response));
     }
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/SingleFieldOptimizer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/SingleFieldOptimizer.java
index 34ee8dc..e917da6 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/SingleFieldOptimizer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/SingleFieldOptimizer.java
@@ -24,6 +24,7 @@ import org.apache.plc4x.java.api.messages.PlcRequest;
 import org.apache.plc4x.java.api.messages.PlcWriteRequest;
 import org.apache.plc4x.java.api.model.PlcField;
 import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.spi.context.DriverContext;
 import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
 import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
 
@@ -35,7 +36,7 @@ import java.util.List;
 public class SingleFieldOptimizer extends BaseOptimizer {
 
     @Override
-    protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest) {
+    protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest, DriverContext driverContext) {
         if(readRequest.getNumberOfFields() == 1) {
             return Collections.singletonList(readRequest);
         }
@@ -51,7 +52,7 @@ public class SingleFieldOptimizer extends BaseOptimizer {
     }
 
     @Override
-    protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest) {
+    protected List<PlcRequest> processWriteRequest(PlcWriteRequest writeRequest, DriverContext driverContext) {
         if(writeRequest.getNumberOfFields() == 1) {
             return Collections.singletonList(writeRequest);
         }