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 2019/10/14 16:08:39 UTC

[plc4x] 03/03: - Moved some of the code from the simulator to the S7 driver - Added a skeleton for the S7 driver to the new generated s7 driver - Removed the code-generation from the plc-simulator module - Refactored the S7Server to use the code of the driver instead

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

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

commit 0d7c768c5d14307be288dba14ea03b072b583f55
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon Oct 14 18:01:55 2019 +0200

    - Moved some of the code from the simulator to the S7 driver
    - Added a skeleton for the S7 driver to the new generated s7 driver
    - Removed the code-generation from the plc-simulator module
    - Refactored the S7Server to use the code of the driver instead
---
 sandbox/plc-simulator/pom.xml                      |  38 ++------
 .../SimulatorExcepiton.java}                       |  19 ++--
 .../plc4x/simulator/server/ServerModule.java       |   6 +-
 .../apache/plc4x/simulator/server/s7/S7Server.java |  69 --------------
 .../plc4x/simulator/server/s7/S7ServerModule.java  |  55 ++++++++---
 ...rverProtocol.java => S7Step7ServerAdapter.java} |  51 ++++++++---
 sandbox/test-java-s7-driver/pom.xml                |  10 ++
 .../java/org/apache/plc4x/java/s7/S7PlcDriver.java |  75 +++++++++++++++
 .../plc4x/java/s7/connection/S7PlcConnection.java  | 101 +++++++++++++++++++++
 .../java/s7/protocol/S7Step7ClientAdapter.java}    |  35 ++-----
 .../java/s7/protocol/S7Step7Plc4xAdapter.java}     |  35 ++-----
 .../plc4x/java}/s7/protocol/S7Step7Protocol.java   |   2 +-
 .../services/org.apache.plc4x.java.spi.PlcDriver   |  19 ++++
 13 files changed, 332 insertions(+), 183 deletions(-)

diff --git a/sandbox/plc-simulator/pom.xml b/sandbox/plc-simulator/pom.xml
index e853987..fcb7a7a 100644
--- a/sandbox/plc-simulator/pom.xml
+++ b/sandbox/plc-simulator/pom.xml
@@ -34,30 +34,10 @@
 
   <build>
     <plugins>
-      <!-- Generate the code for parsing and serializing S7 packets -->
-      <plugin>
-        <groupId>org.apache.plc4x.plugins</groupId>
-        <artifactId>plc4x-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>test</id>
-            <phase>generate-sources</phase>
-            <goals>
-              <goal>generate-driver</goal>
-            </goals>
-            <configuration>
-              <protocolName>s7</protocolName>
-              <languageName>java</languageName>
-              <outputFlavor>read-write</outputFlavor>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
       <!-- Build a fat jar containing all dependencies -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
-        <version>3.2.1</version>
         <executions>
           <execution>
             <id>generate-uber-jar</id>
@@ -79,6 +59,13 @@
   </build>
 
   <dependencies>
+    <!-- The Server is based on the same generated code as the client -->
+    <dependency>
+      <groupId>org.apache.plc4x.sandbox</groupId>
+      <artifactId>test-java-s7-driver</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+
     <dependency>
       <groupId>org.apache.plc4x</groupId>
       <artifactId>plc4j-utils-driver-base-java</artifactId>
@@ -89,15 +76,8 @@
       <artifactId>plc4j-protocol-driver-base</artifactId>
       <version>0.5.0-SNAPSHOT</version>
     </dependency>
-    <dependency>
-      <groupId>io.netty</groupId>
-      <artifactId>netty-all</artifactId>
-      <version>${netty.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.fasterxml.jackson.core</groupId>
-      <artifactId>jackson-annotations</artifactId>
-    </dependency>
+
+    <!-- Explicitly override the scope to compile to include these -->
     <dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/exceptions/SimulatorExcepiton.java
similarity index 68%
copy from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java
copy to sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/exceptions/SimulatorExcepiton.java
index 41aecac..1557e32 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/exceptions/SimulatorExcepiton.java
@@ -16,17 +16,20 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.simulator.server;
+package org.apache.plc4x.simulator.exceptions;
 
-public interface ServerModule {
+public class SimulatorExcepiton extends Exception {
 
-    /**
-     * @return the name of the server module
-     */
-    String getName();
+    public SimulatorExcepiton(String message) {
+        super(message);
+    }
 
-    void start();
+    public SimulatorExcepiton(String message, Throwable cause) {
+        super(message, cause);
+    }
 
-    void stop();
+    public SimulatorExcepiton(Throwable cause) {
+        super(cause);
+    }
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java
index 41aecac..da67ef6 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/ServerModule.java
@@ -18,6 +18,8 @@ under the License.
 */
 package org.apache.plc4x.simulator.server;
 
+import org.apache.plc4x.simulator.exceptions.SimulatorExcepiton;
+
 public interface ServerModule {
 
     /**
@@ -25,8 +27,8 @@ public interface ServerModule {
      */
     String getName();
 
-    void start();
+    void start() throws SimulatorExcepiton;
 
-    void stop();
+    void stop() throws SimulatorExcepiton;
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Server.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Server.java
deleted file mode 100644
index ca7d8e4..0000000
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Server.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-package org.apache.plc4x.simulator.server.s7;
-
-import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.*;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.channel.socket.nio.NioServerSocketChannel;
-import org.apache.plc4x.simulator.server.s7.protocol.S7Step7Protocol;
-import org.apache.plc4x.simulator.server.s7.protocol.S7Step7ServerProtocol;
-
-public class S7Server {
-
-    private static final int ISO_ON_TCP_PORT = 102;
-
-    private EventLoopGroup loopGroup;
-    private EventLoopGroup workerGroup;
-
-    public void start() throws Exception {
-        if(loopGroup != null) {
-            return;
-        }
-
-        loopGroup = new NioEventLoopGroup();
-        workerGroup = new NioEventLoopGroup();
-
-        ServerBootstrap bootstrap = new ServerBootstrap();
-        bootstrap.group(loopGroup, workerGroup)
-            .channel(NioServerSocketChannel.class)
-            .childHandler(new ChannelInitializer<SocketChannel>() {
-                @Override
-                public void initChannel(SocketChannel channel) {
-                    ChannelPipeline pipeline = channel.pipeline();
-                    pipeline.addLast(new S7Step7Protocol());
-                    pipeline.addLast(new S7Step7ServerProtocol());
-                }
-            }).option(ChannelOption.SO_BACKLOG, 128)
-            .childOption(ChannelOption.SO_KEEPALIVE, true);
-
-        bootstrap.bind(ISO_ON_TCP_PORT).sync();
-    }
-
-    public void stop() {
-        if(workerGroup == null) {
-            return;
-        }
-
-        workerGroup.shutdownGracefully();
-        loopGroup.shutdownGracefully();
-    }
-
-}
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
index b067305..ed1b160 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
@@ -18,15 +18,25 @@ under the License.
 */
 package org.apache.plc4x.simulator.server.s7;
 
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import org.apache.plc4x.java.s7.protocol.S7Step7Protocol;
+import org.apache.plc4x.simulator.exceptions.SimulatorExcepiton;
 import org.apache.plc4x.simulator.server.ServerModule;
+import org.apache.plc4x.simulator.server.s7.protocol.S7Step7ServerAdapter;
 
 public class S7ServerModule implements ServerModule {
 
-    private S7Server server;
+    private static final int ISO_ON_TCP_PORT = 102;
 
-    public S7ServerModule() {
-        this.server = new S7Server();
-    }
+    private EventLoopGroup loopGroup;
+    private EventLoopGroup workerGroup;
 
     @Override
     public String getName() {
@@ -34,22 +44,43 @@ public class S7ServerModule implements ServerModule {
     }
 
     @Override
-    public void start() {
+    public void start() throws SimulatorExcepiton {
+        if(loopGroup != null) {
+            return;
+        }
 
         try {
-            server.start();
-        } catch(Exception e) {
-            e.printStackTrace();
+            loopGroup = new NioEventLoopGroup();
+            workerGroup = new NioEventLoopGroup();
+
+            ServerBootstrap bootstrap = new ServerBootstrap();
+            bootstrap.group(loopGroup, workerGroup)
+                .channel(NioServerSocketChannel.class)
+                .childHandler(new ChannelInitializer<SocketChannel>() {
+                    @Override
+                    public void initChannel(SocketChannel channel) {
+                        ChannelPipeline pipeline = channel.pipeline();
+                        pipeline.addLast(new S7Step7Protocol());
+                        pipeline.addLast(new S7Step7ServerAdapter());
+                    }
+                }).option(ChannelOption.SO_BACKLOG, 128)
+                .childOption(ChannelOption.SO_KEEPALIVE, true);
+
+            bootstrap.bind(ISO_ON_TCP_PORT).sync();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new SimulatorExcepiton(e);
         }
     }
 
     @Override
     public void stop() {
-        try {
-            server.stop();
-        } catch(Exception e) {
-            e.printStackTrace();
+        if(workerGroup == null) {
+            return;
         }
+
+        workerGroup.shutdownGracefully();
+        loopGroup.shutdownGracefully();
     }
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerProtocol.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
similarity index 82%
rename from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerProtocol.java
rename to sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index a166538..46a4191 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerProtocol.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -24,9 +24,9 @@ import org.apache.plc4x.java.s7.readwrite.types.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
+public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(S7Step7ServerProtocol.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(S7Step7ServerAdapter.class);
 
     private State state = State.INITIAL;
 
@@ -52,9 +52,9 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
         if(msg instanceof TPKTPacket) {
             TPKTPacket packet = (TPKTPacket) msg;
+            final COTPPacket cotpPacket = packet.getPayload();
             switch (state) {
                 case INITIAL: {
-                    final COTPPacket cotpPacket = packet.getPayload();
                     if (!(cotpPacket instanceof COTPPacketConnectionRequest)) {
                         LOGGER.error("Expecting COTP Connection-Request");
                         return;
@@ -64,7 +64,7 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
                     COTPPacketConnectionRequest cotpConnectionRequest = (COTPPacketConnectionRequest) cotpPacket;
                     for (COTPParameter parameter : cotpConnectionRequest.getParameters()) {
                         if (parameter instanceof COTPParameterCalledTsap) {
-                            COTPParameterCalledTsap calledTsapParameter = (COTPParameterCalledTsap) parameter;
+                            // this is actually ignored as it doesn't contain any information.
                         } else if (parameter instanceof COTPParameterCallingTsap) {
                             COTPParameterCallingTsap callingTsapParameter = (COTPParameterCallingTsap) parameter;
                             remoteTsapId = callingTsapParameter.getTsapId();
@@ -72,14 +72,15 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
                             COTPParameterTpduSize tpduSizeParameter = (COTPParameterTpduSize) parameter;
                             proposedTpduSize = tpduSizeParameter.getTpduSize();
                         } else {
-                            LOGGER.error(
-                                "Unexpected COTP Connection-Request Parameter " + parameter.getClass().getName());
+                            LOGGER.error(String.format("Unexpected COTP Connection-Request Parameter %s",
+                                parameter.getClass().getName()));
                             return;
                         }
                     }
 
                     remoteReference = cotpConnectionRequest.getSourceReference();
                     protocolClass = cotpConnectionRequest.getProtocolClass();
+                    assert proposedTpduSize != null;
                     tpduSize = (proposedTpduSize.getSizeInBytes() > maxTpduSize.getSizeInBytes()) ? maxTpduSize : proposedTpduSize;
 
                     // Prepare a response and send it back to the remote.
@@ -95,7 +96,6 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
                     break;
                 }
                 case COTP_CONNECTED: {
-                    final COTPPacket cotpPacket = packet.getPayload();
                     if (!(cotpPacket instanceof COTPPacketData)) {
                         LOGGER.error("Expecting COTP Data packet");
                         return;
@@ -133,7 +133,6 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
                     break;
                 }
                 case S7_CONNECTED: {
-                    final COTPPacket cotpPacket = packet.getPayload();
                     if (!(cotpPacket instanceof COTPPacketData)) {
                         LOGGER.error("Expecting COTP Data packet");
                         return;
@@ -177,7 +176,7 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
 
                                                 S7PayloadUserDataItemCpuFunctionReadSzlResponse readSzlResponsePayload =
                                                     new S7PayloadUserDataItemCpuFunctionReadSzlResponse(
-                                                        (short) 0xFF, DataTransportSize.OCTET_STRING, szlId,
+                                                        (short) 0xFF, PayloadSize.OCTET_STRING, szlId,
                                                         readSzlRequestPayload.getSzlIndex(), items);
 
                                                 S7ParameterUserDataItem[] responseParameterItems =
@@ -207,14 +206,42 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
                         } else {
                             LOGGER.error("Unsupported type of S7MessageUserData parameter " +
                                 s7Parameter.getClass().getName());
-                            return;
                         }
                     } else {
-                        LOGGER.error("Unsupported type of message " + payload.getClass().getName());
-                        return;
+                        if(cotpPacket.getPayload() instanceof S7MessageRequest) {
+                            S7MessageRequest request = (S7MessageRequest) cotpPacket.getPayload();
+                            if(request.getParameter() instanceof S7ParameterReadVarRequest) {
+                                S7ParameterReadVarRequest readVarRequestParameter =
+                                    (S7ParameterReadVarRequest) request.getParameter();
+                                final S7VarRequestParameterItem[] items = readVarRequestParameter.getItems();
+                                for (S7VarRequestParameterItem item : items) {
+                                    if(item instanceof S7VarRequestParameterItemAddress) {
+                                        S7VarRequestParameterItemAddress address =
+                                            (S7VarRequestParameterItemAddress) item;
+                                        final S7Address address1 = address.getAddress();
+                                        if(address1 instanceof S7AddressAny) {
+                                            S7AddressAny addressAny = (S7AddressAny) address1;
+
+                                        }
+                                    }
+                                }
+                            }
+                            else if(request.getParameter() instanceof S7ParameterWriteVarRequest) {
+                                S7ParameterWriteVarRequest writeVarRequestParameter =
+                                    (S7ParameterWriteVarRequest) request.getParameter();
+
+                            } else {
+                                LOGGER.error("Unsupported type of S7MessageRequest parameter " +
+                                    request.getParameter().getClass().getName());
+                            }
+                        } else {
+                            LOGGER.error("Unsupported type of message " + payload.getClass().getName());
+                        }
                     }
                     break;
                 }
+                default:
+                    throw new IllegalStateException("Unexpected value: " + state);
             }
         }
     }
diff --git a/sandbox/test-java-s7-driver/pom.xml b/sandbox/test-java-s7-driver/pom.xml
index f5985b6..98bca1d 100644
--- a/sandbox/test-java-s7-driver/pom.xml
+++ b/sandbox/test-java-s7-driver/pom.xml
@@ -62,6 +62,16 @@
       <version>0.5.0-SNAPSHOT</version>
     </dependency>
     <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base-tcp</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-annotations</artifactId>
     </dependency>
diff --git a/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/S7PlcDriver.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/S7PlcDriver.java
new file mode 100644
index 0000000..d967959
--- /dev/null
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/S7PlcDriver.java
@@ -0,0 +1,75 @@
+/*
+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;
+
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.authentication.PlcAuthentication;
+import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.s7.connection.S7PlcConnection;
+import org.apache.plc4x.java.spi.PlcDriver;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class S7PlcDriver implements PlcDriver {
+
+    private static final Pattern S7_URI_PATTERN = Pattern.compile("^s7://(?<host>.*)/(?<rack>\\d{1,4})/(?<slot>\\d{1,4})(?<params>\\?.*)?");
+
+    @Override
+    public String getProtocolCode() {
+        return "s7";
+    }
+
+    @Override
+    public String getProtocolName() {
+        return "Siemens S7 (Basic)";
+    }
+
+    @Override
+    public PlcConnection connect(String url) throws PlcConnectionException {
+        Matcher matcher = S7_URI_PATTERN.matcher(url);
+        if (!matcher.matches()) {
+            throw new PlcConnectionException(
+                "Connection url doesn't match the format 's7://{host|ip}/{rack}/{slot}'");
+        }
+        String host = matcher.group("host");
+
+        int rack = Integer.parseInt(matcher.group("rack"));
+        int slot = Integer.parseInt(matcher.group("slot"));
+        String params = matcher.group("params") != null ? matcher.group("params").substring(1) : null;
+
+        try {
+            InetAddress serverInetAddress = InetAddress.getByName(host);
+            return new S7PlcConnection(serverInetAddress, rack, slot, params);
+        } catch (UnknownHostException e) {
+            throw new PlcConnectionException("Error parsing address", e);
+        } catch (Exception e) {
+            throw new PlcConnectionException("Error connecting to host", e);
+        }
+    }
+
+    @Override
+    public PlcConnection connect(String url, PlcAuthentication authentication) throws PlcConnectionException {
+        throw new PlcConnectionException("Basic S7 connections don't support authentication.");
+    }
+
+}
diff --git a/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
new file mode 100644
index 0000000..aa02626
--- /dev/null
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/connection/S7PlcConnection.java
@@ -0,0 +1,101 @@
+/*
+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.connection;
+
+import io.netty.channel.*;
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.base.connection.ChannelFactory;
+import org.apache.plc4x.java.base.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.base.connection.NettyPlcConnection;
+import org.apache.plc4x.java.base.connection.TcpSocketChannelFactory;
+import org.apache.plc4x.java.base.events.ConnectedEvent;
+import org.apache.plc4x.java.base.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.base.messages.PlcReader;
+import org.apache.plc4x.java.s7.protocol.S7Step7ClientAdapter;
+import org.apache.plc4x.java.s7.protocol.S7Step7Plc4xAdapter;
+import org.apache.plc4x.java.s7.protocol.S7Step7Protocol;
+
+import java.net.InetAddress;
+import java.util.concurrent.CompletableFuture;
+
+public class S7PlcConnection extends NettyPlcConnection implements PlcReader {
+
+    private static final int ISO_ON_TCP_PORT = 102;
+
+    public S7PlcConnection(InetAddress address, int rack, int slot, String params) {
+        this(new TcpSocketChannelFactory(address, ISO_ON_TCP_PORT), rack, slot, params);
+    }
+
+    public S7PlcConnection(ChannelFactory channelFactory, int rack, int slot, String param) {
+        super(channelFactory, false);
+    }
+
+    @Override
+    protected ChannelHandler getChannelHandler(CompletableFuture<Void> sessionSetupCompleteFuture) {
+        return new ChannelInitializer() {
+            @Override
+            protected void initChannel(Channel channel) {
+                // Build the protocol stack for communicating with the s7 protocol.
+                ChannelPipeline pipeline = channel.pipeline();
+                pipeline.addLast(new ChannelInboundHandlerAdapter() {
+                    @Override
+                    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+                        if (evt instanceof ConnectedEvent) {
+                            sessionSetupCompleteFuture.complete(null);
+                        } else {
+                            super.userEventTriggered(ctx, evt);
+                        }
+                    }
+                });
+                pipeline.addLast(new S7Step7Protocol());
+                pipeline.addLast(new S7Step7ClientAdapter());
+                pipeline.addLast(new S7Step7Plc4xAdapter());
+            }
+        };
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public PlcReadRequest.Builder readRequestBuilder() {
+        return new DefaultPlcReadRequest.Builder(this, new DefaultPlcFieldHandler() {
+            @Override
+            public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+                return new PlcField() {
+                    @Override
+                    public Class<?> getDefaultJavaType() {
+                        return String.class;
+                    }
+                };
+            }
+        });
+    }
+
+    @Override
+    public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) {
+        return new CompletableFuture<>();
+    }
+
+}
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7ClientAdapter.java
similarity index 56%
copy from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
copy to sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7ClientAdapter.java
index b067305..1904beb 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7ClientAdapter.java
@@ -16,40 +16,25 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.simulator.server.s7;
+package org.apache.plc4x.java.s7.protocol;
 
-import org.apache.plc4x.simulator.server.ServerModule;
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
+import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.s7.readwrite.S7Message;
 
-public class S7ServerModule implements ServerModule {
+import java.util.List;
 
-    private S7Server server;
-
-    public S7ServerModule() {
-        this.server = new S7Server();
-    }
-
-    @Override
-    public String getName() {
-        return "S7-STEP7";
-    }
+public class S7Step7ClientAdapter extends PlcMessageToMessageCodec<S7Message, PlcRequestContainer> {
 
     @Override
-    public void start() {
+    protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
 
-        try {
-            server.start();
-        } catch(Exception e) {
-            e.printStackTrace();
-        }
     }
 
     @Override
-    public void stop() {
-        try {
-            server.stop();
-        } catch(Exception e) {
-            e.printStackTrace();
-        }
+    protected void decode(ChannelHandlerContext ctx, S7Message msg, List<Object> out) throws Exception {
+
     }
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Plc4xAdapter.java
similarity index 56%
copy from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
copy to sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Plc4xAdapter.java
index b067305..5bd694f 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ServerModule.java
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Plc4xAdapter.java
@@ -16,40 +16,25 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.simulator.server.s7;
+package org.apache.plc4x.java.s7.protocol;
 
-import org.apache.plc4x.simulator.server.ServerModule;
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
+import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.s7.readwrite.S7Message;
 
-public class S7ServerModule implements ServerModule {
+import java.util.List;
 
-    private S7Server server;
-
-    public S7ServerModule() {
-        this.server = new S7Server();
-    }
-
-    @Override
-    public String getName() {
-        return "S7-STEP7";
-    }
+public class S7Step7Plc4xAdapter extends PlcMessageToMessageCodec<S7Message, PlcRequestContainer> {
 
     @Override
-    public void start() {
+    protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
 
-        try {
-            server.start();
-        } catch(Exception e) {
-            e.printStackTrace();
-        }
     }
 
     @Override
-    public void stop() {
-        try {
-            server.stop();
-        } catch(Exception e) {
-            e.printStackTrace();
-        }
+    protected void decode(ChannelHandlerContext ctx, S7Message msg, List<Object> out) throws Exception {
+
     }
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7Protocol.java b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Protocol.java
similarity index 98%
rename from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7Protocol.java
rename to sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Protocol.java
index f79b3bd..239f02e 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7Protocol.java
+++ b/sandbox/test-java-s7-driver/src/main/java/org/apache/plc4x/java/s7/protocol/S7Step7Protocol.java
@@ -16,7 +16,7 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-package org.apache.plc4x.simulator.server.s7.protocol;
+package org.apache.plc4x.java.s7.protocol;
 
 import io.netty.buffer.ByteBuf;
 import org.apache.plc4x.java.base.GeneratedDriverByteToMessageCodec;
diff --git a/sandbox/test-java-s7-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver b/sandbox/test-java-s7-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
new file mode 100644
index 0000000..0998600
--- /dev/null
+++ b/sandbox/test-java-s7-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+org.apache.plc4x.java.s7.S7PlcDriver