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

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


The following commit(s) were added to refs/heads/master by this push:
     new 24cdf38  - Removed the cyclic dependencies within the protocol layers.
24cdf38 is described below

commit 24cdf38c03ebc788259ed67e85acd2872a2a3ff2
Author: Christofer Dutz <christofer.d...@c-ware.de>
AuthorDate: Thu Apr 12 16:23:43 2018 +0200

    - Removed the cyclic dependencies within the protocol layers.
---
 .../java/isoontcp/netty/IsoOnTcpProtocol.java      |   8 +
 .../plc4x/java/isotp/netty/IsoTPProtocol.java      |  92 ++++---
 .../netty/model/params/CalledTsapParameter.java    |   5 +-
 .../netty/model/params/CallingTsapParameter.java   |   5 +-
 .../isotp/netty/model/params/TsapParameter.java    |  30 +-
 .../plc4x/java/s7/connection/S7PlcConnection.java  |   7 +-
 .../plc4x/java/s7/netty/Plc4XS7Protocol.java       | 305 +++++++++++----------
 .../org/apache/plc4x/java/s7/netty/S7Protocol.java | 103 ++++---
 .../utils/S7TsapIdEncoder.java}                    |  30 +-
 .../plc4x/java/isotp/netty/IsoTPProtocolTest.java  |  73 ++---
 .../netty/model/params/TsapParameterTests.java     |  17 +-
 11 files changed, 358 insertions(+), 317 deletions(-)

diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java
index 2a330e8..14ed866 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isoontcp/netty/IsoOnTcpProtocol.java
@@ -36,6 +36,10 @@ public class IsoOnTcpProtocol extends 
PlcMessageToMessageCodec<ByteBuf, IsoOnTcp
 
     private static final Logger logger = 
LoggerFactory.getLogger(IsoOnTcpProtocol.class);
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Encoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void encode(ChannelHandlerContext ctx, IsoOnTcpMessage in, 
List<Object> out) throws Exception {
         logger.debug("ISO on TCP RawMessage sent");
@@ -63,6 +67,10 @@ public class IsoOnTcpProtocol extends 
PlcMessageToMessageCodec<ByteBuf, IsoOnTcp
         out.add(buf);
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Decoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> 
out) throws Exception {
         if(logger.isTraceEnabled()) {
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java
index b295db6..5ff5407 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocol.java
@@ -44,19 +44,24 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
 
     private static final Logger logger = 
LoggerFactory.getLogger(IsoTPProtocol.class);
 
-    private final byte rackNo;
-    private final byte slotNo;
-    private final TpduSize tpduSize;
+    private short callingTsapId;
+    private short calledTsapId;
+    private TpduSize tpduSize;
 
-    private CalledTsapParameter calledTsapParameter;
-    private TpduSizeParameter tpduSizeParameter;
-
-    public IsoTPProtocol(byte rackNo, byte slotNo, TpduSize tpduSize) {
-        this.rackNo = rackNo;
-        this.slotNo = slotNo;
+    public IsoTPProtocol(short callingTsapId, short calledTsapId, TpduSize 
tpduSize) {
+        this.callingTsapId = callingTsapId;
+        this.calledTsapId = calledTsapId;
         this.tpduSize = tpduSize;
     }
 
+    /**
+     * If the IsoTP protocol is used on top of the ISO on TCP protocol, then 
as soon as the pipeline receives the
+     * request to connect, an IsoTP connection request TPDU must be sent in 
order to initialize the connection.
+     *
+     * @param ctx the current protocol layers context
+     * @param evt the event
+     * @throws Exception throws an exception if something goes wrong internally
+     */
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) 
throws Exception {
         ChannelHandler prevHandler = getPrevChannelHandler(ctx);
@@ -69,8 +74,8 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
             ConnectionRequestTpdu connectionRequest = new 
ConnectionRequestTpdu(
                 (short) 0x0000, (short) 0x000F, ProtocolClass.CLASS_0,
                 Arrays.asList(
-                    new CalledTsapParameter(DeviceGroup.PG_OR_PC, (byte) 0, 
(byte) 0),
-                    new CallingTsapParameter(DeviceGroup.OTHERS, rackNo, 
slotNo),
+                    new CalledTsapParameter(calledTsapId),
+                    new CallingTsapParameter(callingTsapId),
                     new TpduSizeParameter(tpduSize)),
                 Unpooled.buffer());
             ctx.channel().writeAndFlush(connectionRequest);
@@ -80,6 +85,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
     }
 
     
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Encoding
     
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
     @Override
@@ -100,17 +106,17 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         switch (in.getTpduCode()) {
             case CONNECTION_REQUEST:
             case CONNECTION_CONFIRM:
-                encodeConnecton(in, buf);
+                encodeConnectionTpdu(in, buf);
                 break;
             case DATA:
-                encodeData((DataTpdu) in, buf);
+                encodeDataTpdu((DataTpdu) in, buf);
                 break;
             case DISCONNECT_REQUEST:
             case DISCONNECT_CONFIRM:
-                encodeDisconnect(in, buf);
+                encodeDisconnectTpdu(in, buf);
                 break;
             case TPDU_ERROR:
-                encodeError(in, buf);
+                encodeErrorTpdu(in, buf);
                 break;
             default:
                 if (logger.isErrorEnabled()) {
@@ -130,14 +136,14 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         }
     }
 
-    private void encodeError(Tpdu in, ByteBuf buf) {
+    private void encodeErrorTpdu(Tpdu in, ByteBuf buf) {
         ErrorTpdu errorTpdu = (ErrorTpdu) in;
         buf.writeShort(errorTpdu.getDestinationReference());
         buf.writeByte(errorTpdu.getRejectCause().getCode());
         encodeParameters(buf, in.getParameters());
     }
 
-    private void encodeDisconnect(Tpdu in, ByteBuf buf) {
+    private void encodeDisconnectTpdu(Tpdu in, ByteBuf buf) {
         DisconnectTpdu disconnectTpdu = (DisconnectTpdu) in;
         buf.writeShort(disconnectTpdu.getDestinationReference());
         buf.writeShort(disconnectTpdu.getSourceReference());
@@ -148,13 +154,13 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         encodeParameters(buf, in.getParameters());
     }
 
-    private void encodeData(DataTpdu in, ByteBuf buf) {
+    private void encodeDataTpdu(DataTpdu in, ByteBuf buf) {
         // EOT (Bit 8 = 1) / TPDU (All other bits 0)
         buf.writeByte((byte) (in.getTpduRef() | (in.isEot() ? 0x80 : 0x00)));
         // Note: A Data TPDU in Class 0 doesn't have parameters
     }
 
-    private void encodeConnecton(Tpdu in, ByteBuf buf) {
+    private void encodeConnectionTpdu(Tpdu in, ByteBuf buf) {
         ConnectionTpdu connectionTpdu = (ConnectionTpdu) in;
         buf.writeShort(connectionTpdu.getDestinationReference());
         buf.writeShort(connectionTpdu.getSourceReference());
@@ -174,8 +180,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
                 case CALLED_TSAP:
                 case CALLING_TSAP:
                     TsapParameter tsap = (TsapParameter) parameter;
-                    out.writeByte(tsap.getDeviceGroup().getCode());
-                    out.writeByte((byte) ((tsap.getRackNumber() << 4) | 
(tsap.getSlotNumber() & 0x0F)));
+                    out.writeShort(tsap.getTsapId());
                     break;
                 case CHECKSUM:
                     ChecksumParameter checksum = (ChecksumParameter) parameter;
@@ -198,6 +203,10 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         }
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Decoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void decode(ChannelHandlerContext ctx, IsoOnTcpMessage in, 
List<Object> out) {
         if (logger.isTraceEnabled()) {
@@ -224,17 +233,17 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         switch (tpduCode) {
             case CONNECTION_REQUEST:
             case CONNECTION_CONFIRM:
-                tpdu = decodeConnection(ctx, userData, tpduCode, parameters);
+                tpdu = decodeConnectTpdu(ctx, userData, tpduCode, parameters);
                 break;
             case DATA:
-                tpdu = decodeData(userData, parameters);
+                tpdu = decodeDataTpdu(userData, parameters);
                 break;
             case DISCONNECT_REQUEST:
             case DISCONNECT_CONFIRM:
-                tpdu = decodeDisconnect(userData, tpduCode, parameters);
+                tpdu = decodeDisconnectTpdu(userData, tpduCode, parameters);
                 break;
             case TPDU_ERROR:
-                tpdu = decodeError(userData, parameters);
+                tpdu = decodeErrorTpdu(userData, parameters);
                 break;
             default:
                 if (logger.isErrorEnabled()) {
@@ -257,16 +266,16 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
             // Save some of the information in the session and tell the next
             // layer to negotiate the connection parameters.
             if (tpdu instanceof ConnectionConfirmTpdu) {
-                // TODO: check if null is a valid value (fails test: 
org.apache.plc4x.java.isotp.netty.IsoTPProtocolTest.decodeConnectionConfirm)
-                calledTsapParameter = 
tpdu.getParameter(CalledTsapParameter.class).orElse(null);
-                // TODO: check if null is a valid value (fails test: 
org.apache.plc4x.java.isotp.netty.IsoTPProtocolTest.decodeConnectionConfirm)
-                tpduSizeParameter = 
tpdu.getParameter(TpduSizeParameter.class).orElse(null);
+                tpdu.getParameter(CalledTsapParameter.class).ifPresent(
+                    calledTsapParameter -> calledTsapId = 
calledTsapParameter.getTsapId());
+                tpdu.getParameter(TpduSizeParameter.class).ifPresent(
+                    tpduSizeParameter -> tpduSize = 
tpduSizeParameter.getTpduSize());
             }
             out.add(new IsoTPMessage(tpdu, userData));
         }
     }
 
-    private Tpdu decodeError(ByteBuf userData, List<Parameter> parameters) {
+    private Tpdu decodeErrorTpdu(ByteBuf userData, List<Parameter> parameters) 
{
         Tpdu tpdu;
         short destinationReference = userData.readShort();
         RejectCause rejectCause = RejectCause.valueOf(userData.readByte());
@@ -274,7 +283,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         return tpdu;
     }
 
-    private Tpdu decodeDisconnect(ByteBuf userData, TpduCode tpduCode, 
List<Parameter> parameters) {
+    private Tpdu decodeDisconnectTpdu(ByteBuf userData, TpduCode tpduCode, 
List<Parameter> parameters) {
         Tpdu tpdu;
         short destinationReference = userData.readShort();
         short sourceReference = userData.readShort();
@@ -289,7 +298,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         return tpdu;
     }
 
-    private Tpdu decodeData(ByteBuf userData, List<Parameter> parameters) {
+    private Tpdu decodeDataTpdu(ByteBuf userData, List<Parameter> parameters) {
         Tpdu tpdu;
         byte tmp = userData.readByte();
         boolean eot = (tmp & 0x80) == 0x80;
@@ -298,7 +307,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         return tpdu;
     }
 
-    private Tpdu decodeConnection(ChannelHandlerContext ctx, ByteBuf userData, 
TpduCode tpduCode, List<Parameter> parameters) {
+    private Tpdu decodeConnectTpdu(ChannelHandlerContext ctx, ByteBuf 
userData, TpduCode tpduCode, List<Parameter> parameters) {
         Tpdu tpdu;
         short destinationReference = userData.readShort();
         short sourceReference = userData.readShort();
@@ -324,7 +333,7 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         switch (parameterCode) {
             case CALLING_TSAP:
             case CALLED_TSAP:
-                return decodeCallParameter(out, parameterCode);
+                return decodeTsapParameter(out, parameterCode);
             case CHECKSUM:
                 byte checksum = out.readByte();
                 return new ChecksumParameter(checksum);
@@ -343,16 +352,13 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         }
     }
 
-    private Parameter decodeCallParameter(ByteBuf out, ParameterCode 
parameterCode) {
-        DeviceGroup deviceGroup = DeviceGroup.valueOf(out.readByte());
-        byte rackAndSlot = out.readByte();
-        byte rackId = (byte) ((rackAndSlot & 0xF0) >> 4);
-        byte slotId = (byte) (rackAndSlot & 0x0F);
+    private Parameter decodeTsapParameter(ByteBuf out, ParameterCode 
parameterCode) {
+        short tsapId = out.readShort();
         switch (parameterCode) {
             case CALLING_TSAP:
-                return new CallingTsapParameter(deviceGroup, rackId, slotId);
+                return new CallingTsapParameter(tsapId);
             case CALLED_TSAP:
-                return new CalledTsapParameter(deviceGroup, rackId, slotId);
+                return new CalledTsapParameter(tsapId);
             default:
                 if (logger.isErrorEnabled()) {
                     logger.error("Parameter not implemented yet {}", 
parameterCode.name());
@@ -361,6 +367,10 @@ public class IsoTPProtocol extends 
PlcMessageToMessageCodec<IsoOnTcpMessage, Tpd
         }
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Helpers
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     /**
      * Return the length of the entire header in bytes (including the size 
field itself)
      * This is a sum of the fixed size header defined for the given tpdu type 
and the
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java
index fbd8589..a9446f3 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CalledTsapParameter.java
@@ -18,13 +18,12 @@ under the License.
 */
 package org.apache.plc4x.java.isotp.netty.model.params;
 
-import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
 import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode;
 
 public class CalledTsapParameter extends TsapParameter {
 
-    public CalledTsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte 
slotNumber) {
-        super(deviceGroup, rackNumber, slotNumber);
+    public CalledTsapParameter(short tsapId) {
+        super(tsapId);
     }
 
     @Override
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java
index b3cb6e4..a4dd393 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/CallingTsapParameter.java
@@ -18,13 +18,12 @@ under the License.
 */
 package org.apache.plc4x.java.isotp.netty.model.params;
 
-import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
 import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode;
 
 public class CallingTsapParameter extends TsapParameter {
 
-    public CallingTsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte 
slotNumber) {
-        super(deviceGroup, rackNumber, slotNumber);
+    public CallingTsapParameter(short tsapId) {
+        super(tsapId);
     }
 
     @Override
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
index 2d7f2d2..6439008 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
@@ -18,31 +18,21 @@ under the License.
 */
 package org.apache.plc4x.java.isotp.netty.model.params;
 
-
-import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
-
+/**
+ * Base class for calling and called TSAPs
+ * TODO: I find it strange to have these parameters directly relate to S7 
specifics as they should not need to be known in the IsoTP protocol.
+ * Optionally it might be a good idea to have some mechanism
+ */
 public abstract class TsapParameter implements Parameter {
 
-    private final DeviceGroup deviceGroup;
-    private final byte rackNumber;
-    private final byte slotNumber;
-
-    public TsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte 
slotNumber) {
-        this.deviceGroup = deviceGroup;
-        this.rackNumber = rackNumber;
-        this.slotNumber = slotNumber;
-    }
-
-    public DeviceGroup getDeviceGroup() {
-        return deviceGroup;
-    }
+    private final short tsapId;
 
-    public byte getRackNumber() {
-        return rackNumber;
+    public TsapParameter(short tsapId) {
+        this.tsapId = tsapId;
     }
 
-    public byte getSlotNumber() {
-        return slotNumber;
+    public short getTsapId() {
+        return tsapId;
     }
 
 }
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
index e224544..396b4c6 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
@@ -34,6 +34,7 @@ import org.apache.plc4x.java.base.events.ConnectedEvent;
 import org.apache.plc4x.java.isoontcp.netty.IsoOnTcpProtocol;
 import org.apache.plc4x.java.isotp.netty.IsoTPProtocol;
 import org.apache.plc4x.java.isotp.netty.model.tpdus.DisconnectRequestTpdu;
+import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
 import org.apache.plc4x.java.isotp.netty.model.types.DisconnectReason;
 import org.apache.plc4x.java.isotp.netty.model.types.TpduSize;
 import org.apache.plc4x.java.s7.model.S7Address;
@@ -42,6 +43,7 @@ import org.apache.plc4x.java.s7.model.S7DataBlockAddress;
 import org.apache.plc4x.java.s7.netty.Plc4XS7Protocol;
 import org.apache.plc4x.java.s7.netty.S7Protocol;
 import org.apache.plc4x.java.s7.netty.model.types.MemoryArea;
+import org.apache.plc4x.java.s7.utils.S7TsapIdEncoder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -121,6 +123,9 @@ public class S7PlcConnection extends AbstractPlcConnection 
implements PlcReader,
 
     @Override
     protected ChannelHandler getChannelHandler(CompletableFuture<Void> 
sessionSetupCompleteFuture) {
+        short calledTsapId = 
S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.OTHERS, rack, slot);
+        short callingTsapId = 
S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC, 0, 0);
+
         return new ChannelInitializer() {
             @Override
             protected void initChannel(Channel channel) {
@@ -137,7 +142,7 @@ public class S7PlcConnection extends AbstractPlcConnection 
implements PlcReader,
                     }
                 });
                 pipeline.addLast(new IsoOnTcpProtocol());
-                pipeline.addLast(new IsoTPProtocol((byte) rack, (byte) slot, 
paramPduSize));
+                pipeline.addLast(new IsoTPProtocol(callingTsapId, 
calledTsapId, paramPduSize));
                 pipeline.addLast(new S7Protocol(paramMaxAmqCaller, 
paramMaxAmqCallee, (short) paramPduSize.getValue()));
                 pipeline.addLast(new Plc4XS7Protocol());
             }
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
index f5c12f9..1d41aea 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
@@ -65,6 +65,14 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         this.requests = new HashMap<>();
     }
 
+    /**
+     * If this protocol layer catches an {@link S7ConnectedEvent} from the 
protocol layer beneath,
+     * the connection establishment is finished.
+     *
+     * @param ctx the current protocol layers context
+     * @param evt the event
+     * @throws Exception throws an exception if something goes wrong internally
+     */
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) 
throws Exception {
         if (evt instanceof S7ConnectedEvent) {
@@ -74,6 +82,40 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         }
     }
 
+    /**
+     * When receiving an error inside the pipeline, we have to find out which 
{@link PlcRequestContainer}
+     * correlates needs to be notified about the problem. If a container is 
found, we can relay the
+     * exception to that by calling completeExceptionally and passing in the 
exception.
+     *
+     * @param ctx the current protocol layers context
+     * @param cause the exception that was caught
+     * @throws Exception throws an exception if something goes wrong internally
+     */
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
+        if(cause instanceof PlcProtocolPayloadTooBigException) {
+            PlcProtocolPayloadTooBigException pptbe = 
(PlcProtocolPayloadTooBigException) cause;
+            if(pptbe.getPayload() instanceof S7RequestMessage) {
+                S7RequestMessage request = (S7RequestMessage) 
pptbe.getPayload();
+                if(request.getParent() instanceof PlcRequestContainer) {
+                    PlcRequestContainer requestContainer = 
(PlcRequestContainer) request.getParent();
+
+                    // Remove the current request from the unconfirmed 
requests list.
+                    if(requests.containsKey(request.getTpduReference())) {
+                        requests.remove(request.getTpduReference());
+                    }
+
+                    
requestContainer.getResponseFuture().completeExceptionally(cause);
+                }
+            }
+        }
+        super.exceptionCaught(ctx, cause);
+    }
+
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Encoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, 
List<Object> out) throws Exception {
         PlcRequest request = msg.getRequest();
@@ -84,6 +126,23 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         }
     }
 
+    private void encodeReadRequest(PlcRequestContainer msg, List<Object> out) 
throws PlcException {
+        List<VarParameterItem> parameterItems = new LinkedList<>();
+
+        PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
+        encodeParameterItems(parameterItems, readRequest);
+        VarParameter readVarParameter = new 
VarParameter(ParameterType.READ_VAR, parameterItems);
+
+        // Assemble the request.
+        S7RequestMessage s7ReadRequest = new S7RequestMessage(MessageType.JOB,
+            (short) tpduGenerator.getAndIncrement(), 
Collections.singletonList(readVarParameter),
+            Collections.emptyList(), msg);
+
+        requests.put(s7ReadRequest.getTpduReference(), msg);
+
+        out.add(s7ReadRequest);
+    }
+
     private void encodeWriteRequest(PlcRequestContainer msg, List<Object> out) 
throws PlcException {
         List<VarParameterItem> parameterItems = new LinkedList<>();
         List<VarPayloadItem> payloadItems = new LinkedList<>();
@@ -125,23 +184,6 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         out.add(s7WriteRequest);
     }
 
-    private void encodeReadRequest(PlcRequestContainer msg, List<Object> out) 
throws PlcException {
-        List<VarParameterItem> parameterItems = new LinkedList<>();
-
-        PlcReadRequest readRequest = (PlcReadRequest) msg.getRequest();
-        encodeParameterItems(parameterItems, readRequest);
-        VarParameter readVarParameter = new 
VarParameter(ParameterType.READ_VAR, parameterItems);
-
-        // Assemble the request.
-        S7RequestMessage s7ReadRequest = new S7RequestMessage(MessageType.JOB,
-            (short) tpduGenerator.getAndIncrement(), 
Collections.singletonList(readVarParameter),
-            Collections.emptyList(), msg);
-
-        requests.put(s7ReadRequest.getTpduReference(), msg);
-
-        out.add(s7ReadRequest);
-    }
-
     private void encodeParameterItems(List<VarParameterItem> parameterItems, 
PlcReadRequest readRequest) throws PlcException {
         for (ReadRequestItem requestItem : readRequest.getRequestItems()) {
             // Try to get the correct S7 transport size for the given data 
type.
@@ -157,6 +199,75 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         }
     }
 
+    private VarParameterItem encodeVarParameterItem(Address address, 
TransportSize transportSize, int size) throws PlcProtocolException {
+        // Depending on the address type, generate the corresponding type of 
request item.
+        if (!(address instanceof S7Address)) {
+            throw new PlcProtocolException("Can only use S7Address types on S7 
connection");
+        }
+        S7Address s7Address = (S7Address) address;
+        if (s7Address instanceof S7DataBlockAddress) {
+            S7DataBlockAddress s7DataBlockAddress = (S7DataBlockAddress) 
s7Address;
+            return new S7AnyVarParameterItem(
+                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
+                transportSize, (short) size,
+                s7DataBlockAddress.getDataBlockNumber(), 
s7DataBlockAddress.getByteOffset(), (byte) 0);
+        } else if (s7Address instanceof S7BitAddress) {
+            S7BitAddress s7BitAddress = (S7BitAddress) s7Address;
+            return new S7AnyVarParameterItem(
+                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
+                transportSize, (short) size, (short) 0,
+                s7Address.getByteOffset(), s7BitAddress.getBitOffset());
+        } else {
+            return new S7AnyVarParameterItem(
+                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
+                transportSize, (short) size, (short) 0,
+                s7Address.getByteOffset(), (byte) 0);
+        }
+    }
+
+    private TransportSize encodeTransportSize(Class<?> datatype) {
+        if (datatype == Boolean.class) {
+            return TransportSize.BIT;
+        } else if (datatype == Byte.class) {
+            return TransportSize.BYTE;
+        } else if (datatype == Short.class) {
+            return TransportSize.WORD;
+        } else if (datatype == Calendar.class) {
+            return TransportSize.DATE_AND_TIME;
+        } else if (datatype == Float.class) {
+            return TransportSize.REAL;
+        } else if (datatype == Integer.class) {
+            return TransportSize.DWORD;
+        } else if (datatype == String.class) {
+            return TransportSize.CHAR;
+        }
+        return null;
+    }
+
+    private DataTransportSize encodeDataTransportSize(Class<?> datatype) {
+        if (datatype == Boolean.class) {
+            return DataTransportSize.BIT;
+        } else if (datatype == Byte.class) {
+            return DataTransportSize.BYTE_WORD_DWORD;
+        } else if (datatype == Short.class) {
+            return DataTransportSize.BYTE_WORD_DWORD;
+        } else if (datatype == Calendar.class) {
+            // TODO: Decide what to do here ...
+            return null;
+        } else if (datatype == Float.class) {
+            return DataTransportSize.REAL;
+        } else if (datatype == Integer.class) {
+            return DataTransportSize.BYTE_WORD_DWORD;
+        } else if (datatype == String.class) {
+            return DataTransportSize.OCTET_STRING;
+        }
+        return null;
+    }
+
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Decoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @SuppressWarnings("unchecked")
     @Override
     protected void decode(ChannelHandlerContext ctx, S7Message msg, 
List<Object> out) throws Exception {
@@ -172,9 +283,9 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
 
             // Handle the response to a read request.
             if (request instanceof PlcReadRequest) {
-                response = decodeReadRequest(responseMessage, 
requestContainer);
+                response = decodeReadResponse(responseMessage, 
requestContainer);
             } else if (request instanceof PlcWriteRequest) {
-                response = decodeWriteRequest(responseMessage, 
requestContainer);
+                response = decodeWriteResponse(responseMessage, 
requestContainer);
             }
 
             // Confirm the response being handled.
@@ -184,66 +295,8 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         }
     }
 
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
throws Exception {
-        if(cause instanceof PlcProtocolPayloadTooBigException) {
-            PlcProtocolPayloadTooBigException pptbe = 
(PlcProtocolPayloadTooBigException) cause;
-            if(pptbe.getPayload() instanceof S7RequestMessage) {
-                S7RequestMessage request = (S7RequestMessage) 
pptbe.getPayload();
-                if(request.getParent() instanceof PlcRequestContainer) {
-                    PlcRequestContainer requestContainer = 
(PlcRequestContainer) request.getParent();
-
-                    // Remove the current request from the unconfirmed 
requests list.
-                    if(requests.containsKey(request.getTpduReference())) {
-                        requests.remove(request.getTpduReference());
-                    }
-
-                    
requestContainer.getResponseFuture().completeExceptionally(cause);
-                }
-            }
-        }
-        super.exceptionCaught(ctx, cause);
-    }
-
     @SuppressWarnings("unchecked")
-    private PlcResponse decodeWriteRequest(S7ResponseMessage responseMessage, 
PlcRequestContainer requestContainer) throws PlcProtocolException {
-        PlcResponse response;
-        PlcWriteRequest plcWriteRequest = (PlcWriteRequest) 
requestContainer.getRequest();
-        List<WriteResponseItem<?>> responseItems = new LinkedList<>();
-        VarPayload payload = responseMessage.getPayload(VarPayload.class)
-            .orElseThrow(() -> new PlcProtocolException("No VarPayload 
supplied"));
-        // If the numbers of items don't match, we're in big trouble as the 
only
-        // way to know how to interpret the responses is by aligning them with 
the
-        // items from the request as this information is not returned by the 
PLC.
-        if (plcWriteRequest.getRequestItems().size() != 
payload.getPayloadItems().size()) {
-            throw new PlcProtocolException(
-                "The number of requested items doesn't match the number of 
returned items");
-        }
-        List<VarPayloadItem> payloadItems = payload.getPayloadItems();
-        final int noPayLoadItems = payloadItems.size();
-        for (int i = 0; i < noPayLoadItems; i++) {
-            VarPayloadItem payloadItem = payloadItems.get(i);
-
-            // Get the request item for this payload item
-            WriteRequestItem requestItem = 
plcWriteRequest.getRequestItems().get(i);
-
-            // A write response contains only the return code for every item.
-            ResponseCode responseCode = 
decodeResponseCode(payloadItem.getReturnCode());
-
-            WriteResponseItem responseItem = new 
WriteResponseItem(requestItem, responseCode);
-            responseItems.add(responseItem);
-        }
-
-        if (plcWriteRequest instanceof TypeSafePlcWriteRequest) {
-            response = new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) 
plcWriteRequest, responseItems);
-        } else {
-            response = new PlcWriteResponse(plcWriteRequest, responseItems);
-        }
-        return response;
-    }
-
-    @SuppressWarnings("unchecked")
-    private PlcResponse decodeReadRequest(S7ResponseMessage responseMessage, 
PlcRequestContainer requestContainer) throws PlcProtocolException {
+    private PlcResponse decodeReadResponse(S7ResponseMessage responseMessage, 
PlcRequestContainer requestContainer) throws PlcProtocolException {
         PlcResponse response;
         PlcReadRequest plcReadRequest = (PlcReadRequest) 
requestContainer.getRequest();
 
@@ -289,79 +342,43 @@ public class Plc4XS7Protocol extends 
PlcMessageToMessageCodec<S7Message, PlcRequ
         return response;
     }
 
-    
////////////////////////////////////////////////////////////////////////////////
-    // Encoding helpers.
-    
////////////////////////////////////////////////////////////////////////////////
-
-    private VarParameterItem encodeVarParameterItem(Address address, 
TransportSize transportSize, int size) throws PlcProtocolException {
-        // Depending on the address type, generate the corresponding type of 
request item.
-        if (!(address instanceof S7Address)) {
-            throw new PlcProtocolException("Can only use S7Address types on S7 
connection");
-        }
-        S7Address s7Address = (S7Address) address;
-        if (s7Address instanceof S7DataBlockAddress) {
-            S7DataBlockAddress s7DataBlockAddress = (S7DataBlockAddress) 
s7Address;
-            return new S7AnyVarParameterItem(
-                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
-                transportSize, (short) size,
-                s7DataBlockAddress.getDataBlockNumber(), 
s7DataBlockAddress.getByteOffset(), (byte) 0);
-        } else if (s7Address instanceof S7BitAddress) {
-            S7BitAddress s7BitAddress = (S7BitAddress) s7Address;
-            return new S7AnyVarParameterItem(
-                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
-                transportSize, (short) size, (short) 0,
-                s7Address.getByteOffset(), s7BitAddress.getBitOffset());
-        } else {
-            return new S7AnyVarParameterItem(
-                SpecificationType.VARIABLE_SPECIFICATION, 
s7Address.getMemoryArea(),
-                transportSize, (short) size, (short) 0,
-                s7Address.getByteOffset(), (byte) 0);
+    @SuppressWarnings("unchecked")
+    private PlcResponse decodeWriteResponse(S7ResponseMessage responseMessage, 
PlcRequestContainer requestContainer) throws PlcProtocolException {
+        PlcResponse response;
+        PlcWriteRequest plcWriteRequest = (PlcWriteRequest) 
requestContainer.getRequest();
+        List<WriteResponseItem<?>> responseItems = new LinkedList<>();
+        VarPayload payload = responseMessage.getPayload(VarPayload.class)
+            .orElseThrow(() -> new PlcProtocolException("No VarPayload 
supplied"));
+        // If the numbers of items don't match, we're in big trouble as the 
only
+        // way to know how to interpret the responses is by aligning them with 
the
+        // items from the request as this information is not returned by the 
PLC.
+        if (plcWriteRequest.getRequestItems().size() != 
payload.getPayloadItems().size()) {
+            throw new PlcProtocolException(
+                "The number of requested items doesn't match the number of 
returned items");
         }
-    }
+        List<VarPayloadItem> payloadItems = payload.getPayloadItems();
+        final int noPayLoadItems = payloadItems.size();
+        for (int i = 0; i < noPayLoadItems; i++) {
+            VarPayloadItem payloadItem = payloadItems.get(i);
 
-    private TransportSize encodeTransportSize(Class<?> datatype) {
-        if (datatype == Boolean.class) {
-            return TransportSize.BIT;
-        } else if (datatype == Byte.class) {
-            return TransportSize.BYTE;
-        } else if (datatype == Short.class) {
-            return TransportSize.WORD;
-        } else if (datatype == Calendar.class) {
-            return TransportSize.DATE_AND_TIME;
-        } else if (datatype == Float.class) {
-            return TransportSize.REAL;
-        } else if (datatype == Integer.class) {
-            return TransportSize.DWORD;
-        } else if (datatype == String.class) {
-            return TransportSize.CHAR;
+            // Get the request item for this payload item
+            WriteRequestItem requestItem = 
plcWriteRequest.getRequestItems().get(i);
+
+            // A write response contains only the return code for every item.
+            ResponseCode responseCode = 
decodeResponseCode(payloadItem.getReturnCode());
+
+            WriteResponseItem responseItem = new 
WriteResponseItem(requestItem, responseCode);
+            responseItems.add(responseItem);
         }
-        return null;
-    }
 
-    private DataTransportSize encodeDataTransportSize(Class<?> datatype) {
-        if (datatype == Boolean.class) {
-            return DataTransportSize.BIT;
-        } else if (datatype == Byte.class) {
-            return DataTransportSize.BYTE_WORD_DWORD;
-        } else if (datatype == Short.class) {
-            return DataTransportSize.BYTE_WORD_DWORD;
-        } else if (datatype == Calendar.class) {
-            // TODO: Decide what to do here ...
-            return null;
-        } else if (datatype == Float.class) {
-            return DataTransportSize.REAL;
-        } else if (datatype == Integer.class) {
-            return DataTransportSize.BYTE_WORD_DWORD;
-        } else if (datatype == String.class) {
-            return DataTransportSize.OCTET_STRING;
+        if (plcWriteRequest instanceof TypeSafePlcWriteRequest) {
+            response = new TypeSafePlcWriteResponse((TypeSafePlcWriteRequest) 
plcWriteRequest, responseItems);
+        } else {
+            response = new PlcWriteResponse(plcWriteRequest, responseItems);
         }
-        return null;
+        return response;
     }
 
-    
////////////////////////////////////////////////////////////////////////////////
-    // Decoding helpers.
-    
////////////////////////////////////////////////////////////////////////////////
-
     private ResponseCode decodeResponseCode(DataTransportErrorCode 
dataTransportErrorCode) {
         if (dataTransportErrorCode == null) {
             return ResponseCode.INTERNAL_ERROR;
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
index 923b820..943603c 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
@@ -64,6 +64,14 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         this.pduSize = requestedPduSize;
     }
 
+    /**
+     * If the S7 protocol layer is used over Iso TP, then after receiving a 
{@link IsoTPConnectedEvent} the
+     * corresponding S7 setup communication message has to be sent in order to 
negotiate the S7 protocol layer.
+     *
+     * @param ctx the current protocol layers context
+     * @param evt the event
+     * @throws Exception throws an exception if something goes wrong internally
+     */
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) 
throws Exception {
         ChannelHandler prevHandler = getPrevChannelHandler(ctx);
@@ -82,6 +90,10 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         }
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Encoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void encode(ChannelHandlerContext ctx, S7Message in, 
List<Object> out) {
         logger.debug("S7 RawMessage sent");
@@ -104,41 +116,6 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         }
     }
 
-    /**
-     * While a SetupCommunication message is no problem, when reading or 
writing data,
-     * situations could arise that have to be handled. The following 
situations have to
-     * be handled:
-     * - The number of request items is so big, that the resulting PDU would 
exceed the
-     *   agreed upon PDU size -> The request has to be split up into multiple 
requests.
-     * - If large blocks of data are requested by request items the result of 
a request
-     *   could exceed the PDU size -> The requests has to be split up into 
multiple requests
-     *   where each requests response doesn't exceed the PDU size.
-     *
-     * The following optimizations should be implemented:
-     * - If blocks are read which are in near proximity to each other it could 
be better
-     *   to replace multiple requests by one that includes multiple blocks.
-     * - Rearranging the order of request items could reduce the number of 
needed PDUs.
-     *
-     * @param message incoming message
-     * @return List of outgoing messages
-     */
-    private List<S7Message> optimizeMessage(S7Message message) {
-        // The following considerations have to be taken into account:
-        // - The size of all parameters and payloads of a message cannot 
exceed the negotiated PDU size
-        // - When reading data, the size of the returned data cannot exceed 
the negotiated PDU size
-        //
-        // Examples:
-        // - Size of the request exceeds the maximum
-        //  When having a negotiated max PDU size of 256, the maximum size of 
individual addresses can be at most 18
-        //  If more are sent, the S7 will respond with a frame error.
-        // - Size of the response exceeds the maximum
-        //  When reading two Strings of each 200 bytes length, the size of the 
request is ok, however the PLC would
-        //  have to send back 400 bytes of String data, which would exceed the 
PDU size. In this case the first String
-        //  is correctly returned, but for the second item the PLC will return 
a code of 0x03 = Access Denied
-
-        return Collections.singletonList(message);
-    }
-
     private void encodePayloads(S7Message in, ByteBuf buf) {
         for (S7Payload payload : in.getPayloads()) {
             ParameterType parameterType = payload.getType();
@@ -231,6 +208,10 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
                 | (s7AnyRequestItem.getBitOffset() & 0x07)));
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Decoding
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
     @Override
     protected void decode(ChannelHandlerContext ctx, IsoTPMessage in, 
List<Object> out) {
         if (logger.isTraceEnabled()) {
@@ -269,7 +250,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         int i = 0;
 
         while (i < headerParametersLength) {
-            S7Parameter parameter = parseParameter(userData, isResponse, 
headerParametersLength - i);
+            S7Parameter parameter = decodeParameter(userData, isResponse, 
headerParametersLength - i);
             s7Parameters.add(parameter);
             if (parameter instanceof SetupCommunicationParameter) {
                 setupCommunicationParameter = (SetupCommunicationParameter) 
parameter;
@@ -283,7 +264,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         List<S7Payload> s7Payloads = decodePayloads(userData, isResponse, 
userDataLength, readWriteVarParameter);
 
         if (isResponse) {
-            setupCommunications(ctx, setupCommunicationParameter);
+            decodeSetupCommunications(ctx, setupCommunicationParameter);
             out.add(new S7ResponseMessage(messageType, tpduReference, 
s7Parameters, s7Payloads, errorClass, errorCode));
         } else {
             // TODO: Find out if there is any situation in which a request is 
sent from the PLC
@@ -291,7 +272,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         }
     }
 
-    private void setupCommunications(ChannelHandlerContext ctx, 
SetupCommunicationParameter setupCommunicationParameter) {
+    private void decodeSetupCommunications(ChannelHandlerContext ctx, 
SetupCommunicationParameter setupCommunicationParameter) {
         // If we got a SetupCommunicationParameter as part of the response
         // we are currently in the process of establishing a connection with
         // the PLC, so save some of the information in the session and tell
@@ -353,7 +334,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         return s7Payloads;
     }
 
-    private S7Parameter parseParameter(ByteBuf in, boolean isResponse, int 
restLength) {
+    private S7Parameter decodeParameter(ByteBuf in, boolean isResponse, int 
restLength) {
         ParameterType parameterType = ParameterType.valueOf(in.readByte());
         if (parameterType == null) {
             logger.error("Could not find parameter type");
@@ -372,7 +353,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
                 List<VarParameterItem> varParamameter;
                 byte numItems = in.readByte();
                 if (!isResponse) {
-                    varParamameter = parseReadWriteVarParameter(in, numItems);
+                    varParamameter = decodeReadWriteVarParameter(in, numItems);
                 } else {
                     varParamameter = Collections.emptyList();
                 }
@@ -392,7 +373,7 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         return null;
     }
 
-    private List<VarParameterItem> parseReadWriteVarParameter(ByteBuf in, byte 
numItems) {
+    private List<VarParameterItem> decodeReadWriteVarParameter(ByteBuf in, 
byte numItems) {
         List<VarParameterItem> items = new LinkedList<>();
         for (int i = 0; i < numItems; i++) {
             SpecificationType specificationType = 
SpecificationType.valueOf(in.readByte());
@@ -427,6 +408,46 @@ public class S7Protocol extends 
PlcMessageToMessageCodec<IsoTPMessage, S7Message
         return items;
     }
 
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    // Helpers
+    
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * While a SetupCommunication message is no problem, when reading or 
writing data,
+     * situations could arise that have to be handled. The following 
situations have to
+     * be handled:
+     * - The number of request items is so big, that the resulting PDU would 
exceed the
+     *   agreed upon PDU size -> The request has to be split up into multiple 
requests.
+     * - If large blocks of data are requested by request items the result of 
a request
+     *   could exceed the PDU size -> The requests has to be split up into 
multiple requests
+     *   where each requests response doesn't exceed the PDU size.
+     *
+     * The following optimizations should be implemented:
+     * - If blocks are read which are in near proximity to each other it could 
be better
+     *   to replace multiple requests by one that includes multiple blocks.
+     * - Rearranging the order of request items could reduce the number of 
needed PDUs.
+     *
+     * @param message incoming message
+     * @return List of outgoing messages
+     */
+    private List<S7Message> optimizeMessage(S7Message message) {
+        // The following considerations have to be taken into account:
+        // - The size of all parameters and payloads of a message cannot 
exceed the negotiated PDU size
+        // - When reading data, the size of the returned data cannot exceed 
the negotiated PDU size
+        //
+        // Examples:
+        // - Size of the request exceeds the maximum
+        //  When having a negotiated max PDU size of 256, the maximum size of 
individual addresses can be at most 18
+        //  If more are sent, the S7 will respond with a frame error.
+        // - Size of the response exceeds the maximum
+        //  When reading two Strings of each 200 bytes length, the size of the 
request is ok, however the PLC would
+        //  have to send back 400 bytes of String data, which would exceed the 
PDU size. In this case the first String
+        //  is correctly returned, but for the second item the PLC will return 
a code of 0x03 = Access Denied
+
+        return Collections.singletonList(message);
+    }
+
     private short getParametersLength(List<S7Parameter> parameters) {
         short l = 0;
         if (parameters != null) {
diff --git 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java
similarity index 55%
copy from 
plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
copy to 
plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java
index 2d7f2d2..3980c4c 100644
--- 
a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameter.java
+++ 
b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoder.java
@@ -1,3 +1,4 @@
+package org.apache.plc4x.java.s7.utils;
 /*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
@@ -16,33 +17,28 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.java.isotp.netty.model.params;
-
 
 import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
 
-public abstract class TsapParameter implements Parameter {
-
-    private final DeviceGroup deviceGroup;
-    private final byte rackNumber;
-    private final byte slotNumber;
+public class S7TsapIdEncoder {
 
-    public TsapParameter(DeviceGroup deviceGroup, byte rackNumber, byte 
slotNumber) {
-        this.deviceGroup = deviceGroup;
-        this.rackNumber = rackNumber;
-        this.slotNumber = slotNumber;
+    public static short encodeS7TsapId(DeviceGroup deviceGroup, int rack, int 
slot) {
+        short firstByte = ((short) (deviceGroup.getCode() << 8));
+        short secondByte = ((short) ((rack << 4) | (slot & 0x0F)));
+        return (short) (firstByte | secondByte);
     }
 
-    public DeviceGroup getDeviceGroup() {
-        return deviceGroup;
+    public static DeviceGroup decodeDeviceGroup(short tsapId) {
+        byte deviceGroupCode = (byte) ((tsapId >> 8) & (0xFF));
+        return DeviceGroup.valueOf(deviceGroupCode);
     }
 
-    public byte getRackNumber() {
-        return rackNumber;
+    public static int decodeRack(short tsapId) {
+        return ((tsapId >> 4) & 0xF);
     }
 
-    public byte getSlotNumber() {
-        return slotNumber;
+    public static int decodeSlot(short tsapId) {
+        return (tsapId & 0xF);
     }
 
 }
diff --git 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java
 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java
index 886d63d..6f28908 100644
--- 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java
+++ 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/IsoTPProtocolTest.java
@@ -26,6 +26,7 @@ import org.apache.plc4x.java.isotp.netty.model.IsoTPMessage;
 import org.apache.plc4x.java.isotp.netty.model.params.*;
 import org.apache.plc4x.java.isotp.netty.model.tpdus.*;
 import org.apache.plc4x.java.isotp.netty.model.types.*;
+import org.apache.plc4x.java.s7.utils.S7TsapIdEncoder;
 import org.apache.plc4x.test.FastTests;
 import org.junit.After;
 import org.junit.Before;
@@ -69,7 +70,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeConnectionRequest() throws Exception {
+    public void encodeConnectionRequest() {
         ConnectionRequestTpdu tpdu = new ConnectionRequestTpdu((short) 0x1, 
(short) (0x2), ProtocolClass.CLASS_0, Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -88,7 +89,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeConnectionRequest() throws Exception {
+    public void decodeConnectionRequest() {
         buf.writeByte(0x6) // header length
             .writeByte(TpduCode.CONNECTION_REQUEST.getCode())
             .writeShort(0x01) // destination reference
@@ -111,7 +112,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeDisconnectionRequest() throws Exception {
+    public void encodeDisconnectionRequest() {
         DisconnectRequestTpdu tpdu = new DisconnectRequestTpdu((short) 0x1, 
(short) (0x2), DisconnectReason.NORMAL, Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -129,7 +130,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeDisconnectionRequest() throws Exception {
+    public void decodeDisconnectionRequest() {
         buf.writeByte(0x6) // header length
             .writeByte(TpduCode.DISCONNECT_REQUEST.getCode())
             .writeShort(0x01) // destination reference
@@ -152,7 +153,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeData() throws Exception {
+    public void encodeData() {
         DataTpdu tpdu = new DataTpdu(true, (byte) 0x7, 
Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -169,7 +170,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeDataEOT() throws Exception {
+    public void decodeDataEOT() {
         buf.writeByte(0x3) // header length
             .writeByte(TpduCode.DATA.getCode())
             .writeByte((byte) 0x81); // Tpdu code + EOT
@@ -189,7 +190,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeData() throws Exception {
+    public void decodeData() {
         buf.writeByte(0x3) // header length
             .writeByte(TpduCode.DATA.getCode())
             .writeByte((byte) 0x1); // Tpdu code
@@ -209,7 +210,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeConnectionConfirm() throws Exception {
+    public void encodeConnectionConfirm() {
         ConnectionConfirmTpdu tpdu = new ConnectionConfirmTpdu((short) 0x1, 
(short) (0x2), ProtocolClass.CLASS_1, Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -228,7 +229,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeConnectionConfirm() throws Exception {
+    public void decodeConnectionConfirm() {
         buf.writeByte(0x6) // header length
             .writeByte(TpduCode.CONNECTION_CONFIRM.getCode())
             .writeShort(0x01) // destination reference
@@ -251,7 +252,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeDisconnectionConfirm() throws Exception {
+    public void encodeDisconnectionConfirm() {
         DisconnectConfirmTpdu tpdu = new DisconnectConfirmTpdu((short) 0x1, 
(short) (0x2), Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -269,7 +270,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeDisconnectionConfirm() throws Exception {
+    public void decodeDisconnectionConfirm() {
         buf.writeByte(0x5) // header length
             .writeByte(TpduCode.DISCONNECT_CONFIRM.getCode())
             .writeShort(0x01) // destination reference
@@ -291,7 +292,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeError() throws Exception {
+    public void encodeError() {
         ErrorTpdu tpdu = new ErrorTpdu((short) 0x1, 
RejectCause.REASON_NOT_SPECIFIED, Collections.emptyList(), buf);
 
         isoTPProtocol.encode(ctx, tpdu, out);
@@ -309,9 +310,11 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeCallingParameter() throws Exception {
+    public void encodeCallingParameter() {
         ArrayList<Parameter> parmameters = new ArrayList<>();
-        CallingTsapParameter callingParameter = new 
CallingTsapParameter(DeviceGroup.PG_OR_PC, (byte) 0x7, (byte) 0xe1); // slot 
number too big and overflows into rack
+        CallingTsapParameter callingParameter = new CallingTsapParameter(
+            // slot number too big and overflows into rack
+            S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC, (byte) 0x7, 
(byte) 0xe1));
         parmameters.add(callingParameter);
         ErrorTpdu tpdu = new ErrorTpdu((short) 0x1, 
RejectCause.REASON_NOT_SPECIFIED, parmameters, buf);
 
@@ -336,7 +339,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeChecksumParameter() throws Exception {
+    public void encodeChecksumParameter() {
         ArrayList<Parameter> parmameters = new ArrayList<>();
         ChecksumParameter checksumParameter = new ChecksumParameter((byte) 
0x77);
         parmameters.add(checksumParameter);
@@ -360,7 +363,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeAditionalInformationParameter() throws Exception {
+    public void encodeAditionalInformationParameter() {
         ArrayList<Parameter> parmameters = new ArrayList<>();
         byte[] data = {'O', 'p', 'p', 's'};
         DisconnectAdditionalInformationParameter informationParameter = new 
DisconnectAdditionalInformationParameter(data);
@@ -388,7 +391,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeSizeParameter() throws Exception {
+    public void encodeSizeParameter() {
         ArrayList<Parameter> parmameters = new ArrayList<>();
         TpduSizeParameter sizeParameter = new 
TpduSizeParameter(TpduSize.SIZE_512);
         parmameters.add(sizeParameter);
@@ -412,7 +415,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeError() throws Exception {
+    public void decodeError() {
         buf.writeByte(0x4) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
@@ -433,10 +436,8 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeNullRequest() throws Exception {
-        ConnectionRequestTpdu tpdu = null;
-
-        isoTPProtocol.encode(ctx, tpdu, out);
+    public void encodeNullRequest() {
+        isoTPProtocol.encode(ctx, null, out);
         assertThat("RawMessage not decoded", out, empty());
 
         isoTPProtocol.encode(ctx, null, out);
@@ -446,7 +447,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeNull() throws Exception {
+    public void decodeNull() {
         IsoOnTcpMessage in = new IsoOnTcpMessage(buf);
 
         isoTPProtocol.decode(ctx, in, out);
@@ -458,7 +459,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void encodeUnsupported() throws Exception {
+    public void encodeUnsupported() {
         ArrayList<Parameter> parmameters = new ArrayList<>();
         CustomTpdu tpdu = new CustomTpdu((byte) 0x7F, parmameters, buf);
 
@@ -469,7 +470,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeUnsupported() throws Exception {
+    public void decodeUnsupported() {
         IsoOnTcpMessage in = new IsoOnTcpMessage(buf);
         buf.writeByte(0x3) // header length
             .writeByte(0x7F)
@@ -480,7 +481,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeCallingParameter() throws Exception {
+    public void decodeCallingParameter() {
         buf.writeByte(0x8) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
@@ -503,14 +504,14 @@ public class IsoTPProtocolTest {
         assertThat(errorTpdu.getParameters(), hasSize(1));
         CallingTsapParameter parameter = (CallingTsapParameter) 
errorTpdu.getParameters().get(0);
         assertThat(parameter.getType(), equalTo(ParameterCode.CALLING_TSAP));
-        assertThat(parameter.getDeviceGroup(), equalTo(DeviceGroup.PG_OR_PC));
-        assertThat(parameter.getRackNumber(), equalTo((byte) 0x1));
-        assertThat(parameter.getSlotNumber(), equalTo((byte) 0x7));
+        assertThat(S7TsapIdEncoder.decodeDeviceGroup(parameter.getTsapId()), 
equalTo(DeviceGroup.PG_OR_PC));
+        assertThat(S7TsapIdEncoder.decodeRack(parameter.getTsapId()), 
equalTo(0x1));
+        assertThat(S7TsapIdEncoder.decodeSlot(parameter.getTsapId()), 
equalTo(0x7));
     }
 
     @Test
     @Category(FastTests.class)
-    public void decodeCalledParameter() throws Exception {
+    public void decodeCalledParameter() {
         buf.writeByte(0x8) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
@@ -533,14 +534,14 @@ public class IsoTPProtocolTest {
         assertThat(errorTpdu.getParameters(), hasSize(1));
         CalledTsapParameter parameter = (CalledTsapParameter) 
errorTpdu.getParameters().get(0);
         assertThat(parameter.getType(), equalTo(ParameterCode.CALLED_TSAP));
-        assertThat(parameter.getDeviceGroup(), equalTo(DeviceGroup.PG_OR_PC));
-        assertThat(parameter.getRackNumber(), equalTo((byte) 0x2));
-        assertThat(parameter.getSlotNumber(), equalTo((byte) 0x3));
+        assertThat(S7TsapIdEncoder.decodeDeviceGroup(parameter.getTsapId()), 
equalTo(DeviceGroup.PG_OR_PC));
+        assertThat(S7TsapIdEncoder.decodeRack(parameter.getTsapId()), 
equalTo(0x2));
+        assertThat(S7TsapIdEncoder.decodeSlot(parameter.getTsapId()), 
equalTo(0x3));
     }
 
     @Test
     @Category(FastTests.class)
-    public void decodeChecksumParameter() throws Exception {
+    public void decodeChecksumParameter() {
         buf.writeByte(0x8) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
@@ -567,7 +568,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeSizeParameter() throws Exception {
+    public void decodeSizeParameter() {
         buf.writeByte(0x8) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
@@ -594,7 +595,7 @@ public class IsoTPProtocolTest {
 
     @Test
     @Category(FastTests.class)
-    public void decodeAdditionalInformationParameter() throws Exception {
+    public void decodeAdditionalInformationParameter() {
         buf.writeByte(0x8) // header length
             .writeByte(TpduCode.TPDU_ERROR.getCode())
             .writeShort(0x01) // destination reference
diff --git 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java
 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java
index 0fb651c..705010c 100644
--- 
a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java
+++ 
b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/isotp/netty/model/params/TsapParameterTests.java
@@ -19,7 +19,6 @@ under the License.
 
 package org.apache.plc4x.java.isotp.netty.model.params;
 
-import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
 import org.apache.plc4x.java.isotp.netty.model.types.ParameterCode;
 import org.apache.plc4x.test.FastTests;
 import org.junit.After;
@@ -41,24 +40,20 @@ public class TsapParameterTests {
     @Test
     @Category(FastTests.class)
     public void calledPartameter() {
-        DeviceGroup deviceGroup = DeviceGroup.valueOf((byte)0);
-        tsapParameter = new CalledTsapParameter(deviceGroup, (byte)1, (byte)4);
+        short calledTsapId = 0x1234;
+        tsapParameter = new CalledTsapParameter(calledTsapId);
 
-        assertThat("Device group incorrect", tsapParameter.getDeviceGroup(), 
equalTo(DeviceGroup.valueOf((byte)0)));
-        assertThat("Rack number not correct", tsapParameter.getRackNumber(), 
equalTo((byte)1));
-        assertThat("Slot number not coorect", tsapParameter.getSlotNumber(), 
equalTo((byte)4));
+        assertThat("TSAP Id incorrect", tsapParameter.getTsapId(), 
equalTo(calledTsapId));
         assertThat(tsapParameter.getType(), 
equalTo(ParameterCode.CALLED_TSAP));
     }
 
     @Test
     @Category(FastTests.class)
     public void callingPartameter() {
-        DeviceGroup deviceGroup = DeviceGroup.valueOf((byte)0);
-        tsapParameter = new CallingTsapParameter(deviceGroup, (byte)2, 
(byte)5);
+        short callingTsapId = 0x4321;
+        tsapParameter = new CallingTsapParameter(callingTsapId);
 
-        assertThat("Device group incorrect", tsapParameter.getDeviceGroup(), 
equalTo(DeviceGroup.valueOf((byte)0)));
-        assertThat("Rack number not correct", tsapParameter.getRackNumber(), 
equalTo((byte)2));
-        assertThat("Slot number not coorect", tsapParameter.getSlotNumber(), 
equalTo((byte)5));
+        assertThat("TSAP Id incorrect", tsapParameter.getTsapId(), 
equalTo(callingTsapId));
         assertThat(tsapParameter.getType(), 
equalTo(ParameterCode.CALLING_TSAP));
     }
 

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

Reply via email to