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

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

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);
         }