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 2018/10/31 14:30:39 UTC

[incubator-plc4x] branch master updated: - Added some Integration-Tests to the S7 driver that actually test the full stack.

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 f0123ef  - Added some Integration-Tests to the S7 driver that actually test the full stack.
f0123ef is described below

commit f0123ef97137c5f0832e1fd5fe121566a72f4a80
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Oct 31 15:30:35 2018 +0100

    - Added some Integration-Tests to the S7 driver that actually test the full stack.
---
 plc4j/protocols/s7/pom.xml                         |  24 ++++
 .../java/s7/connection/S7PlcConnectionIT.java      |  92 ++++++++-----
 .../java/s7/connection/S7PlcConnectionTests.java   |  89 +++----------
 .../java/s7/connection/S7PlcTestConnection.java    | 148 ++++++++-------------
 .../apache/plc4x/java/s7/netty/S7ProtocolTest.java |  22 ++-
 .../plc4x/java/s7/utils/S7TsapIdEncoderTest.java   |  68 ++++++++++
 .../java/s7/connection/s7-read-var-request.pcapng  | Bin 0 -> 400 bytes
 .../java/s7/connection/s7-read-var-response.pcapng | Bin 0 -> 392 bytes
 .../java/s7/connection/s7-write-var-request.pcapng | Bin 0 -> 404 bytes
 .../s7/connection/s7-write-var-response.pcapng     | Bin 0 -> 388 bytes
 10 files changed, 241 insertions(+), 202 deletions(-)

diff --git a/plc4j/protocols/s7/pom.xml b/plc4j/protocols/s7/pom.xml
index ce0b9bf..af9ac3f 100644
--- a/plc4j/protocols/s7/pom.xml
+++ b/plc4j/protocols/s7/pom.xml
@@ -96,6 +96,16 @@
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.pcap4j</groupId>
+      <artifactId>pcap4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.pcap4j</groupId>
+      <artifactId>pcap4j-packetfactory-static</artifactId>
+      <scope>test</scope>
+    </dependency>
 
     <dependency>
       <groupId>org.apache.plc4x</groupId>
@@ -111,4 +121,18 @@
     </dependency>
   </dependencies>
 
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <configuration>
+          <usedDependencies combine.children="append">
+            <usedDependency>org.pcap4j:pcap4j-packetfactory-static</usedDependency>
+          </usedDependencies>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
 </project>
\ No newline at end of file
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionIT.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionIT.java
index cdbcea0..4cef96e 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionIT.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionIT.java
@@ -18,67 +18,99 @@ under the License.
 */
 package org.apache.plc4x.java.s7.connection;
 
-import io.netty.channel.Channel;
+import io.netty.channel.embedded.EmbeddedChannel;
 import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteResponse;
 import org.apache.plc4x.java.s7.types.S7ControllerType;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.Timeout;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import static org.hamcrest.core.Is.is;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsNull.notNullValue;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
 
 public class S7PlcConnectionIT {
 
-    private static final Logger logger = LoggerFactory.getLogger(S7PlcConnectionIT.class);
-
     @Rule
     public Timeout globalTimeout = Timeout.seconds(4); // 4 seconds max per method tested
 
-    private S7PlcTestConnection  s7PlcConnection;
-    private Channel channel;
+    private S7PlcTestConnection SUT;
 
     @Before
     public void setUp() {
-        try {
-            s7PlcConnection = new S7PlcTestConnection(1, 2, "", S7ControllerType.S7_1500);
-            s7PlcConnection.connect();
-            channel = s7PlcConnection.getChannel();
-        } catch (PlcConnectionException e) {
-            logger.error("Error initializing connection", e);
-            fail("Error initializing connection");
-        }
+        SUT = new S7PlcTestConnection(1, 2,
+            "pdu-size=1&max-amq-caller=2&max-amq-callee=3&unknown=parameter&unknown-flag", S7ControllerType.S7_1500);
     }
 
     @After
     public void tearDown() throws PlcConnectionException{
-        if(s7PlcConnection.isConnected()) {
-            s7PlcConnection.close();
+        if(SUT.isConnected()) {
+            SUT.close();
         }
-        s7PlcConnection = null;
-        channel = null;
+        SUT = null;
     }
 
     @Test
-    public void testConnect() {
-        assertThat(s7PlcConnection, notNullValue());
-        assertThat("The connection should be 'connected'", s7PlcConnection.isConnected(), is( true) );
+    public void connectAndClose() throws Exception {
+        SUT.connect();
+        SUT.close();
     }
 
     @Test
-    public void testDisconnect() throws PlcConnectionException {
-        assertThat(s7PlcConnection, notNullValue());
-        assertThat("The connection should be 'connected'", s7PlcConnection.isConnected(), is( true) );
-        s7PlcConnection.close();
-        assertThat("The connection should be 'connected'", s7PlcConnection.isConnected(), is( false) );
+    public void read() throws Exception {
+        SUT.connect();
+        EmbeddedChannel channel = (EmbeddedChannel) SUT.getChannel();
+        assertThat("No outbound messages should exist.", channel.outboundMessages().size(), equalTo(0));
+
+        PlcReadRequest request = SUT.readRequestBuilder().addItem("test", "%Q0.4:BOOL").build();
+        CompletableFuture<PlcReadResponse> responseFuture = SUT.read(request);
+        // Check that one message has been sent.
+        assertThat("Exactly one outbound message should exist after sending.",
+            channel.outboundMessages().size(), equalTo(1));
+        SUT.verifyPcapFile("org/apache/plc4x/java/s7/connection/s7-read-var-request.pcapng");
+
+        // Manually feed a packet response into the channel.
+        SUT.sendPcapFile("org/apache/plc4x/java/s7/connection/s7-read-var-response.pcapng");
+
+        // Now get the response as it was processed by the connection.
+        PlcReadResponse response = responseFuture.get(200, TimeUnit.MILLISECONDS);
+
+        assertThat(response, notNullValue());
+
+        SUT.close();
     }
 
-    // TODO more tests for connect, close, read and write
+    @Test
+    public void write() throws Exception {
+        SUT.connect();
+        EmbeddedChannel channel = (EmbeddedChannel) SUT.getChannel();
+        assertThat("No outbound messages should exist.", channel.outboundMessages().size(), equalTo(0));
+
+        PlcWriteRequest request = SUT.writeRequestBuilder().addItem("test", "%Q0.4:BOOL", true).build();
+        CompletableFuture<PlcWriteResponse> responseFuture = SUT.write(request);
+        // Check that one message has been sent.
+        assertThat("Exactly one outbound message should exist after sending.",
+            channel.outboundMessages().size(), equalTo(1));
+        SUT.verifyPcapFile("org/apache/plc4x/java/s7/connection/s7-write-var-request.pcapng");
+
+        // Manually feed a packet response into the channel.
+        SUT.sendPcapFile("org/apache/plc4x/java/s7/connection/s7-write-var-response.pcapng");
+
+        // Now get the response as it was processed by the connection.
+        PlcWriteResponse response = responseFuture.get(200, TimeUnit.MILLISECONDS);
+
+        assertThat(response, notNullValue());
+
+        SUT.close();
+    }
 
 }
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionTests.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionTests.java
index 23bff02..78ced2e 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionTests.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcConnectionTests.java
@@ -19,98 +19,53 @@ under the License.
 
 package org.apache.plc4x.java.s7.connection;
 
-import org.apache.plc4x.java.api.exceptions.PlcException;
-import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.exceptions.PlcUnsupportedOperationException;
 import org.apache.plc4x.java.isotp.netty.model.types.TpduSize;
-import org.apache.plc4x.java.s7.model.S7Field;
-import org.apache.plc4x.java.s7.netty.model.types.MemoryArea;
+import org.apache.plc4x.java.s7.types.S7ControllerType;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.net.InetAddress;
-
+import static org.apache.plc4x.java.base.util.Junit5Backport.assertThrows;
 import static org.hamcrest.core.IsEqual.equalTo;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.core.IsNull.notNullValue;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
 
 public class S7PlcConnectionTests {
 
-    private S7PlcConnection  s7PlcConnection;
+    private S7PlcTestConnection SUT;
 
     @Before
-    public void setUp() throws Exception {
-        InetAddress address = InetAddress.getByName("localhost");
-        s7PlcConnection = new S7PlcConnection(address, 1, 2,
-            "pdu-size=1&max-amq-caller=2&max-amq-callee=3&unknown=parameter&unknown-flag");
+    public void setUp() {
+        SUT = new S7PlcTestConnection(1, 2,
+            "pdu-size=1&max-amq-caller=2&max-amq-callee=3&unknown=parameter&unknown-flag", S7ControllerType.S7_1200);
     }
 
     @After
     public void tearDown() {
-        s7PlcConnection = null;
+        SUT = null;
     }
 
     @Test
     public void initialState() {
-        assertThat("Rack is incorrect", s7PlcConnection.getRack(), equalTo(1) );
-        assertThat("Slot is incorrect", s7PlcConnection.getSlot(), equalTo(2) );
-        assertThat("Pdu size is incorrect", s7PlcConnection.getParamPduSize(), equalTo(TpduSize.SIZE_128));
-        assertThat("Max AMQ Caller size is incorrect", s7PlcConnection.getParamMaxAmqCaller(), equalTo(2) );
-        assertThat("Max AMQ Callee size is incorrect", s7PlcConnection.getParamMaxAmqCallee(), equalTo(3) );
-    }
-
-/*    @Test
-    public void prepareEmptyField() {
-        try {
-            s7PlcConnection.prepareField("");
-        }
-        catch (PlcException exception) {
-            assertThat(exception, instanceOf(PlcInvalidFieldException.class));
-            assertThat(exception.getMessage(), containsString("invalid") );
-        }
+        assertThat("Rack is incorrect", SUT.getRack(), equalTo(1) );
+        assertThat("Slot is incorrect", SUT.getSlot(), equalTo(2) );
+        assertThat("Pdu size is incorrect", SUT.getParamPduSize(), equalTo(TpduSize.SIZE_128));
+        assertThat("Max AMQ Caller size is incorrect", SUT.getParamMaxAmqCaller(), equalTo(2) );
+        assertThat("Max AMQ Callee size is incorrect", SUT.getParamMaxAmqCallee(), equalTo(3) );
     }
 
     @Test
-    public void prepareDatablockField() {
-        try {
-            S7DataBlockField field = (S7DataBlockField)
-                s7PlcConnection.prepareField("DATA_BLOCKS/20/100");
+    public void capabilities() {
+        assertThat(SUT.canRead(), equalTo(true));
+        assertThat(SUT.readRequestBuilder(), notNullValue());
 
-            assertThat("unexpected data block", field.getDataBlockNumber(), equalTo((short) 20) );
-            assertThat("unexpected byte offset", field.getByteOffset(), equalTo((short) 100) );
-        }
-        catch (PlcException exception) {
-            fail("valid data block field");
-        }
-    }
+        assertThat(SUT.canWrite(), equalTo(true));
+        assertThat(SUT.writeRequestBuilder(), notNullValue());
 
-    @Test
-    public void prepareField() {
-        try {
-            S7Field field = (S7Field) s7PlcConnection.prepareField("TIMERS/10");
-
-            assertThat("unexpected memory area", field.getMemoryArea(), equalTo(MemoryArea.TIMERS) );
-            assertThat("unexpected byte offset", field.getByteOffset(), equalTo((short) 10) );
-        }
-        catch (PlcException exception) {
-            fail("valid timer block field");
-        }
+        assertThat(SUT.canSubscribe(), equalTo(false));
+        assertThrows(PlcUnsupportedOperationException.class, () -> SUT.subscriptionRequestBuilder());
+        assertThrows(PlcUnsupportedOperationException.class, () -> SUT.unsubscriptionRequestBuilder());
     }
 
-    @Test
-    public void prepareBitField() {
-        try {
-            S7BitField field = (S7BitField) s7PlcConnection.prepareField("TIMERS/10/4");
-
-            assertThat("unexpected memory area", field.getMemoryArea(), equalTo(MemoryArea.TIMERS) );
-            assertThat("unexpected byte offset", field.getByteOffset(), equalTo((short) 10) );
-            assertThat("unexpected but offset", field.getBitOffset(), equalTo((byte) 4) );
-        }
-        catch (PlcException exception) {
-            fail("valid timer block bit field");
-        }
-    }*/
-
 }
\ No newline at end of file
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcTestConnection.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcTestConnection.java
index 44cff0a..8a69334 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcTestConnection.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/connection/S7PlcTestConnection.java
@@ -21,15 +21,25 @@ package org.apache.plc4x.java.s7.connection;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.embedded.EmbeddedChannel;
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.plc4x.java.base.connection.TestChannelFactory;
-import org.apache.plc4x.java.base.events.ConnectEvent;
 import org.apache.plc4x.java.s7.types.S7ControllerType;
+import org.pcap4j.core.NotOpenException;
+import org.pcap4j.core.PcapHandle;
+import org.pcap4j.core.PcapNativeException;
+import org.pcap4j.core.Pcaps;
+import org.pcap4j.packet.Packet;
 
+import java.io.EOFException;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.concurrent.TimeoutException;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
 
 public class S7PlcTestConnection extends S7PlcConnection {
 
@@ -70,7 +80,7 @@ public class S7PlcTestConnection extends S7PlcConnection {
         EmbeddedChannel channel = (EmbeddedChannel) getChannel();
 
         // Send an event to the pipeline telling the Protocol filters what's going on.
-        channel.pipeline().fireUserEventTriggered(new ConnectEvent());
+        super.sendChannelCreatedEvent();
 
         ByteBuf writtenData = channel.readOutbound();
         byte[] connectionRequest = new byte[writtenData.readableBytes()];
@@ -78,8 +88,7 @@ public class S7PlcTestConnection extends S7PlcConnection {
         // TODO: Check the content of the Iso TP connection request.
 
         // Send an Iso TP connection response back to the pipeline.
-        byte[] connectionConfirm = readPcapFile(
-            "org/apache/plc4x/java/s7/connection/iso-tp-connect-response.pcap");
+        byte[] connectionConfirm = readPcapFile("org/apache/plc4x/java/s7/connection/iso-tp-connect-response.pcap");
         channel.writeInbound(Unpooled.wrappedBuffer(connectionConfirm));
 
         // Read a S7 Setup Communication request.
@@ -123,100 +132,57 @@ public class S7PlcTestConnection extends S7PlcConnection {
         channel.writeInbound(Unpooled.wrappedBuffer(cpuFunctionsResponse));
     }
 
-    public static byte[] toByteArray(int[] in) {
-        byte[] out = new byte[in.length];
-        for(int i = 0; i < in.length; i++) {
-            out[i] = (byte) in[i];
+    public static byte[] readPcapFile(String filename) {
+        try {
+            InputStream in = S7PlcTestConnection.class.getClassLoader().getResourceAsStream(filename);
+            byte[] pcap = IOUtils.toByteArray(in);
+            byte[] data = new byte[pcap.length - 94];
+            System.arraycopy(pcap, 94, data, 0, pcap.length - 94);
+            return data;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
         }
-        return out;
     }
 
-    public static void dumpArrayToPcapFile(String filename, byte[] data) {
-        byte[] pcapHeader = toByteArray(
-            new int[]{
-                // Magic Bytes (Big Endian)
-                0xa1, 0xb2, 0xc3, 0xd4,
-                // Version (2.4)
-                0x00, 0x02, 0x00, 0x04,
-                // Timestamp
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                // Max Length
-                0x00, 0x00, 0xFF, 0xFF,
-                // Link Layer: Ethernet
-                0x00, 0x00, 0x00, 0x01,
-                // Timestamp (Seconds)
-                0x00, 0x00, 0x00, 0x00,
-                // Timestamp (Microseconds)
-                0x00, 0x00, 0x00, 0x00,
-                // Packet Length
-                0x00, 0x00, 0x00, 0x00,
-                // Packet Length (duplicate)
-                0x00, 0x00, 0x00, 0x00, // 40
-                /////////////////////////////////////
-                // Ethernet Header
-                // Destination Address (Mac Address)
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                // Source Address (Mac Address)
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                // IPv4
-                0x08, 0x00,
-                /////////////////////////////////////
-                // IPv4 Header (type + 20 byte length)
-                0x45, 0x00,
-                // Length
-                0x00, 0x00, // 40 + payload
-                0x00, 0x00,
-                0x00, 0x00,
-                0x1e,
-                // Protocol (TCP)
-                0x06,
-                // Header Checksum
-                0x00, 0x00,
-                // Source IP
-                0x00, 0x00, 0x00, 0x00,
-                // Dest IP
-                0x00, 0x00, 0x00, 0x00, // 34
-                /////////////////////////////////////
-                // TCP Header
-                // Source Port
-                0x00, 0x66,
-                // Dest Port
-                0x10, 0xd1,
-                0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00,
-                // Header Length
-                0x50, 0x18,
-                0xFA, 0xDA,
-                0x00, 0x00,
-                0x00, 0x00 // 54
-            });
-
-        byte[] total = new byte[pcapHeader.length + data.length];
-        System.arraycopy(pcapHeader, 0, total, 0, pcapHeader.length);
-        System.arraycopy(data, 0, total, pcapHeader.length, data.length);
-        total[35] = (byte) (data.length + 54);
-        total[39] = (byte) (data.length + 54);
-        total[39+18] = (byte) (data.length + 40);
-
+    public void sendPcapFile(String filename) {
         try {
-            File file = new File(filename);
-            System.out.println("Dumping to file: "  + file.getAbsolutePath());
-            FileUtils.writeByteArrayToFile(file, total);
-        } catch (IOException e) {
-            e.printStackTrace();
+            ClassLoader classLoader = getClass().getClassLoader();
+            File file = new File(Objects.requireNonNull(classLoader.getResource(filename)).getFile());
+            PcapHandle responsePcap = Pcaps.openOffline(file.getAbsolutePath());
+            Packet packet = responsePcap.getNextPacketEx();
+            byte[] data = packet.getPayload().getPayload().getPayload().getRawData();
+
+            EmbeddedChannel channel = (EmbeddedChannel) getChannel();
+            channel.writeInbound(Unpooled.wrappedBuffer(data));
+        } catch (PcapNativeException | EOFException | TimeoutException | NotOpenException e) {
+            throw new RuntimeException("Error sending pacap file " + filename, e);
         }
     }
 
-    public byte[] readPcapFile(String filename) {
+    public void verifyPcapFile(String filename) {
         try {
-            InputStream in = getClass().getClassLoader().getResourceAsStream(filename);
-            byte[] pcap = IOUtils.toByteArray(in);
-            byte[] data = new byte[pcap.length - 94];
-            System.arraycopy(pcap, 94, data, 0, pcap.length - 94);
-            return data;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
+            ClassLoader classLoader = getClass().getClassLoader();
+            File file = new File(Objects.requireNonNull(classLoader.getResource(filename)).getFile());
+            PcapHandle responsePcap = Pcaps.openOffline(file.getAbsolutePath());
+            Packet packet = responsePcap.getNextPacketEx();
+            byte[] actData = packet.getPayload().getPayload().getPayload().getRawData();
+
+            // Get the systems output.
+            EmbeddedChannel channel = (EmbeddedChannel) getChannel();
+            ByteBuf request = channel.readOutbound();
+
+            // Check the sizes are equal.
+            assertThat(actData.length, equalTo(request.readableBytes()));
+
+            // Read the raw data sent to the output.
+            byte[] refData = new byte[request.readableBytes()];
+            request.readBytes(refData);
+
+            // Compare the actual output to the reference output.
+            assertThat(Arrays.equals(actData, refData), equalTo(true));
+        } catch (PcapNativeException | EOFException | TimeoutException | NotOpenException e) {
+            throw new RuntimeException("Error sending pacap file " + filename, e);
         }
     }
 
-}
+}
\ No newline at end of file
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/S7ProtocolTest.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/S7ProtocolTest.java
index d84dd42..868b67b 100644
--- a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/S7ProtocolTest.java
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/netty/S7ProtocolTest.java
@@ -23,12 +23,7 @@ import io.netty.buffer.Unpooled;
 import org.apache.plc4x.java.isotp.netty.model.IsoTPMessage;
 import org.apache.plc4x.java.isotp.netty.model.tpdus.Tpdu;
 import org.apache.plc4x.java.netty.NettyTestBase;
-import org.apache.plc4x.java.s7.netty.model.messages.S7RequestMessage;
-import org.apache.plc4x.java.s7.netty.model.params.VarParameter;
-import org.apache.plc4x.java.s7.netty.model.params.items.S7AnyVarParameterItem;
-import org.apache.plc4x.java.s7.netty.model.payloads.VarPayload;
-import org.apache.plc4x.java.s7.netty.model.payloads.items.VarPayloadItem;
-import org.apache.plc4x.java.s7.netty.model.types.*;
+import org.apache.plc4x.java.s7.netty.model.types.MessageType;
 import org.apache.plc4x.test.FastTests;
 import org.junit.Before;
 import org.junit.Test;
@@ -36,7 +31,6 @@ import org.junit.experimental.categories.Category;
 
 import java.util.LinkedList;
 
-import static java.util.Collections.singletonList;
 import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
@@ -50,17 +44,17 @@ public class S7ProtocolTest extends NettyTestBase {
         SUT = new S7Protocol((short) 1, (short) 1, (short) 256);
     }
 
-    @Test
+   /* @Test
     @Category(FastTests.class)
     public void encode() throws Exception {
         //TODO: finish me
         LinkedList<Object> out = new LinkedList<>();
         // TODO: Disabled for now ... have to reactivate it when I'm finished with PLC4X-29
-        /*SUT.encode(null, new S7RequestMessage(
+        SUT.write(null, new S7RequestMessage(
             MessageType.ACK,
             (short) 1,
             singletonList(new VarParameter(ParameterType.WRITE_VAR, singletonList(new S7AnyVarParameterItem(
-                SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BIT, (short) 1, (short) 1, (short) 1, (byte) 1
+                SpecificationType.VARIABLE_SPECIFICATION, MemoryArea.DATA_BLOCKS, TransportSize.BOOL, (short) 1, (short) 1, (short) 1, (byte) 1
             )))),
             singletonList(new VarPayload(
                 ParameterType.WRITE_VAR,
@@ -68,13 +62,13 @@ public class S7ProtocolTest extends NettyTestBase {
                     DataTransportErrorCode.OK,
                     DataTransportSize.BYTE_WORD_DWORD, new byte[]{0})
                 ))
-            ), null), out);
-        assertThat(out, hasSize(1));*/
-    }
+            ), null), new DefaultChannelPromise(new EmbeddedChannel()));
+        assertThat(out, hasSize(1));
+    }*/
 
     @Test
     @Category(FastTests.class)
-    public void decode() throws Exception {
+    public void decode() {
         //TODO: finish me
         LinkedList<Object> out = new LinkedList<>();
         ByteBuf buffer = Unpooled.buffer();
diff --git a/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoderTest.java b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoderTest.java
new file mode 100644
index 0000000..e0851ee
--- /dev/null
+++ b/plc4j/protocols/s7/src/test/java/org/apache/plc4x/java/s7/utils/S7TsapIdEncoderTest.java
@@ -0,0 +1,68 @@
+/*
+ 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.utils;
+
+import org.apache.plc4x.java.isotp.netty.model.types.DeviceGroup;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Constructor;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+class S7TsapIdEncoderTest {
+
+    @Test
+    void testConstructorPrivacy() {
+        // Check that every declared constructor is inaccessible.
+        for (Constructor<?> declaredConstructor : S7TsapIdEncoder.class.getDeclaredConstructors()) {
+            assertThat(declaredConstructor.isAccessible(), equalTo(false));
+        }
+    }
+
+    @Test
+    void encodeS7TsapId() {
+        short tsapId = S7TsapIdEncoder.encodeS7TsapId(DeviceGroup.PG_OR_PC, 1, 2);
+
+        assertThat(tsapId, equalTo((short) 0x112));
+    }
+
+    @Test
+    void decodeDeviceGroup() {
+        DeviceGroup deviceGroup = S7TsapIdEncoder.decodeDeviceGroup((short) 0x112);
+
+        assertThat(deviceGroup, equalTo(DeviceGroup.PG_OR_PC));
+    }
+
+    @Test
+    void decodeRack() {
+        int rack = S7TsapIdEncoder.decodeRack((short) 0x112);
+
+        assertThat(rack, equalTo(1));
+    }
+
+    @Test
+    void decodeSlot() {
+        int slot = S7TsapIdEncoder.decodeSlot((short) 0x112);
+
+        assertThat(slot, equalTo(2));
+    }
+
+}
\ No newline at end of file
diff --git a/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-request.pcapng b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-request.pcapng
new file mode 100644
index 0000000..ee0481b
Binary files /dev/null and b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-request.pcapng differ
diff --git a/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-response.pcapng b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-response.pcapng
new file mode 100644
index 0000000..b6a5c50
Binary files /dev/null and b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-read-var-response.pcapng differ
diff --git a/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-request.pcapng b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-request.pcapng
new file mode 100644
index 0000000..183b130
Binary files /dev/null and b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-request.pcapng differ
diff --git a/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-response.pcapng b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-response.pcapng
new file mode 100644
index 0000000..acd088f
Binary files /dev/null and b/plc4j/protocols/s7/src/test/resources/org/apache/plc4x/java/s7/connection/s7-write-var-response.pcapng differ