You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by jf...@apache.org on 2020/05/22 11:58:29 UTC

[plc4x] branch feature/plc-simulator updated (c035a33 -> d9c4d11)

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

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


 discard c035a33  Rebased on current develop + fixed some issues to get a running version again.
 discard 5638602  - Continued implemting the functionality to read DBs in the simulator
 discard 8c3c13e  - Made data be transported in "byte" instead of "short" arrays. - Changed the PLCSimulator to only run with one selected simulation (Due to the problem of how to map I/O to the different simulations)
 discard 97239f5  - Added inputs and outputs to the context - Refactored the Simulator and Server APIs - Made the WaterTankSimulationModule do something a little more complicated
 discard 4d06a7a  - 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
     add e5d95cf  - Fixed the parent version of the pom
     new 92352ee  - 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
     new 1379478  - Added inputs and outputs to the context - Refactored the Simulator and Server APIs - Made the WaterTankSimulationModule do something a little more complicated
     new f27cef0  - Made data be transported in "byte" instead of "short" arrays. - Changed the PLCSimulator to only run with one selected simulation (Due to the problem of how to map I/O to the different simulations)
     new b756712  - Continued implemting the functionality to read DBs in the simulator
     new d9c4d11  Rebased on current develop + fixed some issues to get a running version again.

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (c035a33)
            \
             N -- N -- N   refs/heads/feature/plc-simulator (d9c4d11)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

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


Summary of changes:


[plc4x] 04/05: - Continued implemting the functionality to read DBs in the simulator

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

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

commit b75671247bf0a8f5a830d02777f8f1be5a5b777c
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Fri Oct 18 13:17:59 2019 +0200

    - Continued implemting the functionality to read DBs in the simulator
---
 .../server/s7/protocol/S7Step7ServerAdapter.java   | 34 ++++++++++++++++++++--
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index 9f7a34d..f4f6ddb 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -25,6 +25,7 @@ import org.apache.plc4x.simulator.model.Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.nio.ByteOrder;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.List;
@@ -241,13 +242,40 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                             S7AddressAny addressAny = (S7AddressAny) address1;
                                             switch (addressAny.getArea()) {
                                                 case DATA_BLOCKS: {
-
+                                                    final int dataBlockNumber = addressAny.getDbNumber();
+                                                    if(dataBlockNumber != 1) {
+                                                        // TODO: Return unknown object.
+                                                    }
+                                                    final int numberOfElements = addressAny.getNumberOfElements();
+                                                    if(numberOfElements != 1) {
+                                                        // TODO: Return invalid address.
+                                                    }
+                                                    final int byteAddress = addressAny.getByteAddress();
+                                                    if(byteAddress != 0) {
+                                                        // TODO: Return invalid address.
+                                                    }
+                                                    final byte bitAddress = addressAny.getBitAddress();
+                                                    switch (addressAny.getTransportSize()) {
+                                                        case INT: {
+                                                            String firstKey = context.getMemory().keySet().iterator().next();
+                                                            Object value = context.getMemory().get(firstKey);
+                                                            short shortValue = ((Number) value).shortValue();
+                                                            byte[] data = new byte[2];
+                                                            data[0] = (byte) (shortValue & 0xff);
+                                                            data[1] = (byte) ((shortValue >> 8) & 0xff);
+                                                            payloadItems[i] = new S7VarPayloadDataItem((short) 0xFF, PayloadSize.BYTE_WORD_DWORD, data.length, data);
+                                                            break;
+                                                        }
+                                                        default: {
+                                                            // TODO: Return invalid address.
+                                                        }
+                                                    }
                                                     break;
                                                 }
                                                 case INPUTS:
                                                 case OUTPUTS: {
-                                                    int ioNumber = (addressAny.getByteAddress() * 8) + addressAny.getBitAddress();
-                                                    int numElements = (addressAny.getTransportSize() == ParameterSize.BOOL) ?
+                                                    final int ioNumber = (addressAny.getByteAddress() * 8) + addressAny.getBitAddress();
+                                                    final int numElements = (addressAny.getTransportSize() == ParameterSize.BOOL) ?
                                                         addressAny.getNumberOfElements() : addressAny.getTransportSize().getSizeInBytes() * 8;
                                                     final BitSet bitSet = toBitSet(context.getDigitalInputs(), ioNumber, numElements);
                                                     final byte[] data = Arrays.copyOf(bitSet.toByteArray(), (numElements + 7) / 8);


[plc4x] 05/05: Rebased on current develop + fixed some issues to get a running version again.

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

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

commit d9c4d1170e07ee579bfd4c969238c39b3729e5f2
Author: julian <j....@pragmaticminds.de>
AuthorDate: Fri May 22 13:55:56 2020 +0200

    Rebased on current develop + fixed some issues to get a running version again.
---
 .../spi/connection/GeneratedProtocolMessageCodec.java  |  2 +-
 sandbox/plc-simulator/pom.xml                          | 11 +++--------
 .../plc4x/simulator/server/s7/S7ServerModule.java      | 14 ++++++++++++--
 .../server/s7/protocol/S7Step7ServerAdapter.java       | 18 ++++++++++--------
 4 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
index 1b8e757..9b06e2c 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/GeneratedProtocolMessageCodec.java
@@ -26,7 +26,7 @@ import org.apache.plc4x.java.spi.generation.*;
 import java.util.function.Consumer;
 import java.util.function.ToIntFunction;
 
-class GeneratedProtocolMessageCodec<BASE_PACKET_CLASS extends Message> extends GeneratedDriverByteToMessageCodec<BASE_PACKET_CLASS> {
+public class GeneratedProtocolMessageCodec<BASE_PACKET_CLASS extends Message> extends GeneratedDriverByteToMessageCodec<BASE_PACKET_CLASS> {
 
     private final ToIntFunction<ByteBuf> packetSizeEstimator;
     private final Consumer<ByteBuf> corruptPackageRemover;
diff --git a/sandbox/plc-simulator/pom.xml b/sandbox/plc-simulator/pom.xml
index 559322f..32a4146 100644
--- a/sandbox/plc-simulator/pom.xml
+++ b/sandbox/plc-simulator/pom.xml
@@ -78,19 +78,14 @@
   <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.8.0-SNAPSHOT</version>
-    </dependency>
-
-    <dependency>
       <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-utils-driver-base-java</artifactId>
+      <artifactId>plc4j-driver-s7</artifactId>
       <version>0.8.0-SNAPSHOT</version>
     </dependency>
+
     <dependency>
       <groupId>org.apache.plc4x</groupId>
-      <artifactId>plc4j-protocol-driver-base</artifactId>
+      <artifactId>plc4j-spi</artifactId>
       <version>0.8.0-SNAPSHOT</version>
     </dependency>
 
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 5a63fc9..5be811c 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
@@ -26,12 +26,19 @@ 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.java.s7.readwrite.S7Driver;
+import org.apache.plc4x.java.s7.readwrite.TPKTPacket;
+import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO;
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.connection.GeneratedProtocolMessageCodec;
+import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
 import org.apache.plc4x.simulator.exceptions.SimulatorExcepiton;
 import org.apache.plc4x.simulator.model.Context;
 import org.apache.plc4x.simulator.server.ServerModule;
 import org.apache.plc4x.simulator.server.s7.protocol.S7Step7ServerAdapter;
 
+import static org.apache.plc4x.java.spi.configuration.ConfigurationFactory.configure;
+
 public class S7ServerModule implements ServerModule {
 
     private static final int ISO_ON_TCP_PORT = 102;
@@ -52,6 +59,7 @@ public class S7ServerModule implements ServerModule {
 
     @Override
     public void start() throws SimulatorExcepiton {
+        S7Driver driver = new S7Driver();
         if(loopGroup != null) {
             return;
         }
@@ -67,7 +75,9 @@ public class S7ServerModule implements ServerModule {
                     @Override
                     public void initChannel(SocketChannel channel) {
                         ChannelPipeline pipeline = channel.pipeline();
-                        pipeline.addLast(new S7Step7Protocol());
+                        pipeline.addLast(new GeneratedProtocolMessageCodec<>(TPKTPacket.class, new TPKTPacketIO(), true, null,
+                            new S7Driver.ByteLengthEstimator(),
+                            new S7Driver.CorruptPackageCleaner()));
                         pipeline.addLast(new S7Step7ServerAdapter(context));
                     }
                 }).option(ChannelOption.SO_BACKLOG, 128)
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index f4f6ddb..9c60514 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -141,7 +141,8 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
 
                     S7ParameterSetupCommunication s7ParameterSetupCommunicationResponse =
                         new S7ParameterSetupCommunication(amqCaller, amqCallee, pduLength);
-                    S7MessageResponse s7MessageResponse = new S7MessageResponse(
+                    // TODO should send S7MessageResponseData
+                    S7MessageResponseData s7MessageResponse = new S7MessageResponseData(
                         s7TpduReference, s7ParameterSetupCommunicationResponse, null, (short) 0, (short) 0);
                     ctx.writeAndFlush(new TPKTPacket(new COTPPacketData(null, s7MessageResponse, true, cotpTpduRef)));
 
@@ -193,7 +194,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
 
                                                 S7PayloadUserDataItemCpuFunctionReadSzlResponse readSzlResponsePayload =
                                                     new S7PayloadUserDataItemCpuFunctionReadSzlResponse(
-                                                        DataTransportErrorCode.OK, PayloadSize.OCTET_STRING, szlId,
+                                                        DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, szlId,
                                                         readSzlRequestPayload.getSzlIndex(), items);
 
                                                 S7ParameterUserDataItem[] responseParameterItems =
@@ -256,14 +257,15 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                     }
                                                     final byte bitAddress = addressAny.getBitAddress();
                                                     switch (addressAny.getTransportSize()) {
-                                                        case INT: {
+                                                        case INT:
+                                                        case UINT: {
                                                             String firstKey = context.getMemory().keySet().iterator().next();
                                                             Object value = context.getMemory().get(firstKey);
-                                                            short shortValue = ((Number) value).shortValue();
+                                                            short shortValue = 42; // ((Number) value).shortValue();
                                                             byte[] data = new byte[2];
                                                             data[0] = (byte) (shortValue & 0xff);
                                                             data[1] = (byte) ((shortValue >> 8) & 0xff);
-                                                            payloadItems[i] = new S7VarPayloadDataItem((short) 0xFF, PayloadSize.BYTE_WORD_DWORD, data.length, data);
+                                                            payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, 8 * data.length, data);
                                                             break;
                                                         }
                                                         default: {
@@ -275,11 +277,11 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                 case INPUTS:
                                                 case OUTPUTS: {
                                                     final int ioNumber = (addressAny.getByteAddress() * 8) + addressAny.getBitAddress();
-                                                    final int numElements = (addressAny.getTransportSize() == ParameterSize.BOOL) ?
+                                                    final int numElements = (addressAny.getTransportSize() == TransportSize.BOOL) ?
                                                         addressAny.getNumberOfElements() : addressAny.getTransportSize().getSizeInBytes() * 8;
                                                     final BitSet bitSet = toBitSet(context.getDigitalInputs(), ioNumber, numElements);
                                                     final byte[] data = Arrays.copyOf(bitSet.toByteArray(), (numElements + 7) / 8);
-                                                    payloadItems[i] = new S7VarPayloadDataItem((short) 0xFF, PayloadSize.BYTE_WORD_DWORD, data.length, data);
+                                                    payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, 8 * data.length, data);
                                                     break;
                                                 }
                                             }
@@ -288,7 +290,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                 }
                                 S7ParameterReadVarResponse readVarResponseParameter = new S7ParameterReadVarResponse((short) items.length);
                                 S7PayloadReadVarResponse readVarResponsePayload = new S7PayloadReadVarResponse(payloadItems);
-                                S7MessageResponse response = new S7MessageResponse(request.getTpduReference(),
+                                S7MessageResponseData response = new S7MessageResponseData(request.getTpduReference(),
                                     readVarResponseParameter, readVarResponsePayload, (short) 0x00, (short) 0x00);
                                 ctx.writeAndFlush(new TPKTPacket(new COTPPacketData(null, response, true, cotpTpduRef)));
                             }


[plc4x] 01/05: - 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

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

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

commit 92352ee07c1f490b251529e8819bb02806c4df24
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                      |  19 ++++
 .../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 ++++++++---
 .../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 ++++
 12 files changed, 332 insertions(+), 154 deletions(-)

diff --git a/sandbox/plc-simulator/pom.xml b/sandbox/plc-simulator/pom.xml
index 16c23d7..0cb6de6 100644
--- a/sandbox/plc-simulator/pom.xml
+++ b/sandbox/plc-simulator/pom.xml
@@ -76,6 +76,25 @@
   </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.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-utils-driver-base-java</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4j-protocol-driver-base</artifactId>
+      <version>0.8.0-SNAPSHOT</version>
+    </dependency>
+
+    <!-- Explicitly override the scope to compile to include these -->
 
     <dependency>
       <groupId>io.netty</groupId>
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 c33d5b8..43c02bc 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,8 +72,8 @@ 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;
                         }
                     }
@@ -84,6 +84,7 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
 
                     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.
@@ -99,7 +100,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;
@@ -136,7 +136,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;
@@ -180,7 +179,7 @@ public class S7Step7ServerProtocol extends ChannelInboundHandlerAdapter {
 
                                                 S7PayloadUserDataItemCpuFunctionReadSzlResponse readSzlResponsePayload =
                                                     new S7PayloadUserDataItemCpuFunctionReadSzlResponse(
-                                                        DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, szlId,
+                                                        DataTransportErrorCode.OK, PayloadSize.OCTET_STRING, szlId,
                                                         readSzlRequestPayload.getSzlIndex(), items);
 
                                                 S7ParameterUserDataItem[] responseParameterItems =
@@ -210,14 +209,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/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 0df0d41..eab772e 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.spi.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


[plc4x] 03/05: - Made data be transported in "byte" instead of "short" arrays. - Changed the PLCSimulator to only run with one selected simulation (Due to the problem of how to map I/O to the different simulations)

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

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

commit f27cef04c41446cdad2322c7d5550c251ef7b797
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Thu Oct 17 09:57:08 2019 +0200

    - Made data be transported in "byte" instead of "short" arrays.
    - Changed the PLCSimulator to only run with one selected simulation (Due to the problem of how to map I/O to the different simulations)
---
 .../org/apache/plc4x/simulator/PlcSimulator.java   | 48 ++++++++++++----------
 .../plc4x/simulator/server/ServerModule.java       |  4 +-
 .../plc4x/simulator/server/s7/S7ServerModule.java  | 12 ++----
 .../server/s7/protocol/S7Step7ServerAdapter.java   | 46 +++++++++++++++++----
 .../watertank/WaterTankSimulationModule.java       |  2 +-
 5 files changed, 71 insertions(+), 41 deletions(-)

diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
index 26aab3a..d9bdab5 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
@@ -35,25 +35,32 @@ public class PlcSimulator {
 
     private boolean running;
     private final Map<String, ServerModule> serverModules;
-    private final Map<String, SimulationModule> simulationModules;
+    private final SimulationModule simulationModule;
 
-    private PlcSimulator() {
-        this(Thread.currentThread().getContextClassLoader());
+    private PlcSimulator(String simulationName) {
+        this(simulationName, Thread.currentThread().getContextClassLoader());
     }
 
-    private PlcSimulator(ClassLoader classLoader) {
-        Map<String, Context> contexts = new TreeMap<>();
-
+    private PlcSimulator(String simulationName, ClassLoader classLoader) {
+        Context context = null;
         // Initialize all the simulation modules.
         LOGGER.info("Initializing Simulation Modules:");
-        simulationModules = new TreeMap<>();
+        SimulationModule foundSimulationModule = null;
         ServiceLoader<SimulationModule> simulationModuleLoader = ServiceLoader.load(SimulationModule.class, classLoader);
-        for (SimulationModule simulationModule : simulationModuleLoader) {
-            LOGGER.info(String.format("Initializing simulation module: %s ...", simulationModule.getName()));
-            simulationModules.put(simulationModule.getName(), simulationModule);
-            contexts.put(simulationModule.getName(), simulationModule.getContext());
-            LOGGER.info("Initialized");
+        for (SimulationModule curSimulationModule : simulationModuleLoader) {
+            if(curSimulationModule.getName().equals(simulationName)) {
+                LOGGER.info(String.format("Initializing simulation module: %s ...", simulationName));
+                foundSimulationModule = curSimulationModule;
+                context = curSimulationModule.getContext();
+                LOGGER.info("Initialized");
+            }
+        }
+        // If we couldn't find the simulation module provided, report an error and exit.
+        if(foundSimulationModule == null) {
+            LOGGER.info(String.format("Couldn't find simulation module %s", simulationName));
+            System.exit(1);
         }
+        simulationModule = foundSimulationModule;
         LOGGER.info("Finished Initializing Simulation Modules\n");
 
         // Initialize all the server modules.
@@ -64,7 +71,7 @@ public class PlcSimulator {
             LOGGER.info(String.format("Initializing server module: %s ...", serverModule.getName()));
             serverModules.put(serverModule.getName(), serverModule);
             // Inject the contexts.
-            serverModule.setContexts(contexts);
+            serverModule.setContext(context);
             LOGGER.info("Initialized");
         }
         LOGGER.info("Finished Initializing Server Modules\n");
@@ -89,14 +96,11 @@ public class PlcSimulator {
         try {
             LOGGER.info("Starting simulations ...");
             while (running) {
-                // Give all the simulation modules the chance to do something.
-                for (SimulationModule simulationModule : simulationModules.values()) {
-                    try {
-                        simulationModule.loop();
-                    } catch(Exception e) {
-                        LOGGER.error("Caught error while executing loop() method of " + simulationModule.getName() +
-                            " simulation.", e);
-                    }
+                try {
+                    simulationModule.loop();
+                } catch(Exception e) {
+                    LOGGER.error("Caught error while executing loop() method of " + simulationModule.getName() +
+                        " simulation.", e);
                 }
                 // Sleep 100 ms to not run the simulation too eagerly.
                 TimeUnit.MILLISECONDS.sleep(100);
@@ -113,7 +117,7 @@ public class PlcSimulator {
     }
 
     public static void main(String[] args) throws Exception {
-        final PlcSimulator simulator = new PlcSimulator();
+        final PlcSimulator simulator = new PlcSimulator("Water Tank");
         // Make sure we stop everything correctly.
         Runtime.getRuntime().addShutdownHook(new Thread(simulator::stop));
         // Start the simulator.
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 97bf1c0..61a1ac9 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
@@ -21,8 +21,6 @@ package org.apache.plc4x.simulator.server;
 import org.apache.plc4x.simulator.exceptions.SimulatorExcepiton;
 import org.apache.plc4x.simulator.model.Context;
 
-import java.util.Map;
-
 public interface ServerModule {
 
     /**
@@ -30,7 +28,7 @@ public interface ServerModule {
      */
     String getName();
 
-    void setContexts(Map<String, Context> contexts);
+    void setContext(Context contexts);
 
     void start() throws SimulatorExcepiton;
 
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 483acc6..5a63fc9 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
@@ -32,17 +32,13 @@ import org.apache.plc4x.simulator.model.Context;
 import org.apache.plc4x.simulator.server.ServerModule;
 import org.apache.plc4x.simulator.server.s7.protocol.S7Step7ServerAdapter;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 public class S7ServerModule implements ServerModule {
 
     private static final int ISO_ON_TCP_PORT = 102;
 
     private EventLoopGroup loopGroup;
     private EventLoopGroup workerGroup;
-    private List<Context> contexts;
+    private Context context;
 
     @Override
     public String getName() {
@@ -50,8 +46,8 @@ public class S7ServerModule implements ServerModule {
     }
 
     @Override
-    public void setContexts(Map<String, Context> contexts) {
-        this.contexts = new ArrayList<>(contexts.values());
+    public void setContext(Context context) {
+        this.context = context;
     }
 
     @Override
@@ -72,7 +68,7 @@ public class S7ServerModule implements ServerModule {
                     public void initChannel(SocketChannel channel) {
                         ChannelPipeline pipeline = channel.pipeline();
                         pipeline.addLast(new S7Step7Protocol());
-                        pipeline.addLast(new S7Step7ServerAdapter(contexts));
+                        pipeline.addLast(new S7Step7ServerAdapter(context));
                     }
                 }).option(ChannelOption.SO_BACKLOG, 128)
                 .childOption(ChannelOption.SO_KEEPALIVE, true);
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index 6a7e95b..9f7a34d 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -25,14 +25,15 @@ import org.apache.plc4x.simulator.model.Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Arrays;
+import java.util.BitSet;
 import java.util.List;
-import java.util.Map;
 
 public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(S7Step7ServerAdapter.class);
 
-    private List<Context> contexts;
+    private Context context;
 
     private State state;
 
@@ -54,8 +55,8 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
     private static final int maxPduLength = 240;
     private int pduLength;
 
-    public S7Step7ServerAdapter(List<Context> contexts) {
-        this.contexts = contexts;
+    public S7Step7ServerAdapter(Context context) {
+        this.context = context;
         state = State.INITIAL;
     }
 
@@ -184,6 +185,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                         function.getCpuSubfunction(), (short) 1,
                                                         (short) 0, (short) 0, 0);
 
+                                                // This is the product number of a S7-1200
                                                 SzlDataTreeItem[] items = new SzlDataTreeItem[1];
                                                 items[0] = new SzlDataTreeItem((short) 0x0001,
                                                     "6ES7 212-1BD30-0XB0 ".getBytes(), 0x2020, 0x0001, 0x2020);
@@ -210,7 +212,7 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                 ctx.writeAndFlush(new TPKTPacket(new COTPPacketData(null, s7ResponseMessage, true, cotpTpduRef)));
                                             } else {
                                                 LOGGER.error("Not able to respond to the given request Read SZL with SZL type class " +
-                                                    szlId.getTypeClass().name() + " and SZL sublise " + szlId.getSublistList().name());
+                                                    szlId.getTypeClass().name() + " and SZL sublist " + szlId.getSublistList().name());
                                             }
 
                                         }
@@ -228,17 +230,39 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                 S7ParameterReadVarRequest readVarRequestParameter =
                                     (S7ParameterReadVarRequest) request.getParameter();
                                 final S7VarRequestParameterItem[] items = readVarRequestParameter.getItems();
-                                for (S7VarRequestParameterItem item : items) {
+                                S7VarPayloadDataItem[] payloadItems = new S7VarPayloadDataItem[items.length];
+                                for (int i = 0; i < items.length; i++) {
+                                    S7VarRequestParameterItem item = items[i];
                                     if(item instanceof S7VarRequestParameterItemAddress) {
                                         S7VarRequestParameterItemAddress address =
                                             (S7VarRequestParameterItemAddress) item;
                                         final S7Address address1 = address.getAddress();
                                         if(address1 instanceof S7AddressAny) {
                                             S7AddressAny addressAny = (S7AddressAny) address1;
-
+                                            switch (addressAny.getArea()) {
+                                                case DATA_BLOCKS: {
+
+                                                    break;
+                                                }
+                                                case INPUTS:
+                                                case OUTPUTS: {
+                                                    int ioNumber = (addressAny.getByteAddress() * 8) + addressAny.getBitAddress();
+                                                    int numElements = (addressAny.getTransportSize() == ParameterSize.BOOL) ?
+                                                        addressAny.getNumberOfElements() : addressAny.getTransportSize().getSizeInBytes() * 8;
+                                                    final BitSet bitSet = toBitSet(context.getDigitalInputs(), ioNumber, numElements);
+                                                    final byte[] data = Arrays.copyOf(bitSet.toByteArray(), (numElements + 7) / 8);
+                                                    payloadItems[i] = new S7VarPayloadDataItem((short) 0xFF, PayloadSize.BYTE_WORD_DWORD, data.length, data);
+                                                    break;
+                                                }
+                                            }
                                         }
                                     }
                                 }
+                                S7ParameterReadVarResponse readVarResponseParameter = new S7ParameterReadVarResponse((short) items.length);
+                                S7PayloadReadVarResponse readVarResponsePayload = new S7PayloadReadVarResponse(payloadItems);
+                                S7MessageResponse response = new S7MessageResponse(request.getTpduReference(),
+                                    readVarResponseParameter, readVarResponsePayload, (short) 0x00, (short) 0x00);
+                                ctx.writeAndFlush(new TPKTPacket(new COTPPacketData(null, response, true, cotpTpduRef)));
                             }
                             else if(request.getParameter() instanceof S7ParameterWriteVarRequest) {
                                 S7ParameterWriteVarRequest writeVarRequestParameter =
@@ -266,4 +290,12 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
         S7_CONNECTED
     }
 
+    private BitSet toBitSet(List<Boolean> booleans, int startIndex, int numElements) {
+        BitSet bitSet = new BitSet(booleans.size());
+        for(int i = 0; i < Math.min(booleans.size() - startIndex, numElements); i++) {
+            bitSet.set(i, booleans.get(i + startIndex));
+        }
+        return bitSet;
+    }
+
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
index dafd394..7000fb3 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
@@ -54,7 +54,7 @@ public class WaterTankSimulationModule implements SimulationModule {
             // The input valve
             .addDigitalInput(false)
             // The output valve
-            .addDigitalInput(false)
+            .addDigitalInput(true)
             // The emergency valve
             .addDigitalOutput(false)
             // The water level


[plc4x] 02/05: - Added inputs and outputs to the context - Refactored the Simulator and Server APIs - Made the WaterTankSimulationModule do something a little more complicated

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

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

commit 13794781b34477110685b6320c912a50983f8f42
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Oct 16 09:44:32 2019 +0200

    - Added inputs and outputs to the context
    - Refactored the Simulator and Server APIs
    - Made the WaterTankSimulationModule do something a little more complicated
---
 sandbox/plc-simulator/pom.xml                      |   5 +
 .../org/apache/plc4x/simulator/PlcSimulator.java   |  27 +++--
 .../org/apache/plc4x/simulator/model/Context.java  | 112 +++++++++++++++++++++
 .../plc4x/simulator/server/ServerModule.java       |   5 +
 .../plc4x/simulator/server/s7/S7ServerModule.java  |  13 ++-
 .../server/s7/protocol/S7Step7ServerAdapter.java   |  13 ++-
 .../simulator/simulation/SimulationModule.java     |   5 +-
 .../watertank/WaterTankSimulationModule.java       |  65 ++++++++++--
 8 files changed, 221 insertions(+), 24 deletions(-)

diff --git a/sandbox/plc-simulator/pom.xml b/sandbox/plc-simulator/pom.xml
index 0cb6de6..559322f 100644
--- a/sandbox/plc-simulator/pom.xml
+++ b/sandbox/plc-simulator/pom.xml
@@ -94,6 +94,11 @@
       <version>0.8.0-SNAPSHOT</version>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-collections4</artifactId>
+    </dependency>
+
     <!-- Explicitly override the scope to compile to include these -->
 
     <dependency>
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
index aa55608..26aab3a 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
@@ -18,6 +18,7 @@ under the License.
 */
 package org.apache.plc4x.simulator;
 
+import org.apache.plc4x.simulator.model.Context;
 import org.apache.plc4x.simulator.server.ServerModule;
 import org.apache.plc4x.simulator.simulation.SimulationModule;
 import org.slf4j.Logger;
@@ -41,17 +42,7 @@ public class PlcSimulator {
     }
 
     private PlcSimulator(ClassLoader classLoader) {
-
-        // Initialize all the server modules.
-        LOGGER.info("Initializing Server Modules:");
-        serverModules = new TreeMap<>();
-        ServiceLoader<ServerModule> serverModuleLoader = ServiceLoader.load(ServerModule.class, classLoader);
-        for (ServerModule serverModule : serverModuleLoader) {
-            LOGGER.info(String.format("Initializing server module: %s ...", serverModule.getName()));
-            serverModules.put(serverModule.getName(), serverModule);
-            LOGGER.info("Initialized");
-        }
-        LOGGER.info("Finished Initializing Server Modules\n");
+        Map<String, Context> contexts = new TreeMap<>();
 
         // Initialize all the simulation modules.
         LOGGER.info("Initializing Simulation Modules:");
@@ -60,10 +51,24 @@ public class PlcSimulator {
         for (SimulationModule simulationModule : simulationModuleLoader) {
             LOGGER.info(String.format("Initializing simulation module: %s ...", simulationModule.getName()));
             simulationModules.put(simulationModule.getName(), simulationModule);
+            contexts.put(simulationModule.getName(), simulationModule.getContext());
             LOGGER.info("Initialized");
         }
         LOGGER.info("Finished Initializing Simulation Modules\n");
 
+        // Initialize all the server modules.
+        LOGGER.info("Initializing Server Modules:");
+        serverModules = new TreeMap<>();
+        ServiceLoader<ServerModule> serverModuleLoader = ServiceLoader.load(ServerModule.class, classLoader);
+        for (ServerModule serverModule : serverModuleLoader) {
+            LOGGER.info(String.format("Initializing server module: %s ...", serverModule.getName()));
+            serverModules.put(serverModule.getName(), serverModule);
+            // Inject the contexts.
+            serverModule.setContexts(contexts);
+            LOGGER.info("Initialized");
+        }
+        LOGGER.info("Finished Initializing Server Modules\n");
+
         running = true;
     }
 
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/model/Context.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/model/Context.java
new file mode 100644
index 0000000..be8faad
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/model/Context.java
@@ -0,0 +1,112 @@
+/*
+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.model;
+
+import org.apache.commons.collections4.list.FixedSizeList;
+import org.apache.commons.collections4.map.FixedSizeMap;
+
+import java.util.*;
+
+public class Context {
+
+    private final FixedSizeMap<String, Object> memory;
+    private final FixedSizeList<Boolean> digitalInputs;
+    private final FixedSizeList<Long> analogInputs;
+    private final FixedSizeList<Boolean> digitalOutputs;
+    private final FixedSizeList<Long> analogOutputs;
+
+    public Context(FixedSizeMap<String, Object> memory,
+                   FixedSizeList<Boolean> digitalInputs, FixedSizeList<Long> analogInputs,
+                   FixedSizeList<Boolean> digitalOutputs, FixedSizeList<Long> analogOutputs) {
+        this.memory = memory;
+        this.digitalInputs = digitalInputs;
+        this.analogInputs = analogInputs;
+        this.digitalOutputs = digitalOutputs;
+        this.analogOutputs = analogOutputs;
+    }
+
+    public Map<String, Object> getMemory() {
+        return memory;
+    }
+
+    public List<Boolean> getDigitalInputs() {
+        return digitalInputs;
+    }
+
+    public List<Long> getAnalogInputs() {
+        return analogInputs;
+    }
+
+    public List<Boolean> getDigitalOutputs() {
+        return digitalOutputs;
+    }
+
+    public List<Long> getAnalogOutputs() {
+        return analogOutputs;
+    }
+
+    public static class ContextBuilder {
+        private final Map<String, Object> memory;
+        private final List<Boolean> digitalInputs;
+        private final List<Long> analogInputs;
+        private final List<Boolean> digitalOutputs;
+        private final List<Long> analogOutputs;
+
+        public ContextBuilder() {
+            memory = new TreeMap<>();
+            digitalInputs = new LinkedList<>();
+            analogInputs = new LinkedList<>();
+            digitalOutputs = new LinkedList<>();
+            analogOutputs = new LinkedList<>();
+        }
+
+        public ContextBuilder addMemoryVariable(String name, Object defaultValue) {
+            memory.put(name, defaultValue);
+            return this;
+        }
+
+        public ContextBuilder addDigitalInput(Boolean defaultValue) {
+            digitalInputs.add(defaultValue);
+            return this;
+        }
+
+        public ContextBuilder addAnalogInput(Long defaultValue) {
+            analogInputs.add(defaultValue);
+            return this;
+        }
+
+        public ContextBuilder addDigitalOutput(Boolean defaultValue) {
+            digitalOutputs.add(defaultValue);
+            return this;
+        }
+
+        public ContextBuilder addAnalogOutput(Long defaultValue) {
+            analogOutputs.add(defaultValue);
+            return this;
+        }
+
+        public Context build() {
+            return new Context(FixedSizeMap.fixedSizeMap(memory),
+                FixedSizeList.fixedSizeList(digitalInputs), FixedSizeList.fixedSizeList(analogInputs),
+                FixedSizeList.fixedSizeList(digitalOutputs), FixedSizeList.fixedSizeList(analogOutputs));
+        }
+
+    }
+
+}
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 da67ef6..97bf1c0 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
@@ -19,6 +19,9 @@ under the License.
 package org.apache.plc4x.simulator.server;
 
 import org.apache.plc4x.simulator.exceptions.SimulatorExcepiton;
+import org.apache.plc4x.simulator.model.Context;
+
+import java.util.Map;
 
 public interface ServerModule {
 
@@ -27,6 +30,8 @@ public interface ServerModule {
      */
     String getName();
 
+    void setContexts(Map<String, Context> contexts);
+
     void start() throws SimulatorExcepiton;
 
     void stop() throws SimulatorExcepiton;
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 ed1b160..483acc6 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
@@ -28,15 +28,21 @@ 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.model.Context;
 import org.apache.plc4x.simulator.server.ServerModule;
 import org.apache.plc4x.simulator.server.s7.protocol.S7Step7ServerAdapter;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 public class S7ServerModule implements ServerModule {
 
     private static final int ISO_ON_TCP_PORT = 102;
 
     private EventLoopGroup loopGroup;
     private EventLoopGroup workerGroup;
+    private List<Context> contexts;
 
     @Override
     public String getName() {
@@ -44,6 +50,11 @@ public class S7ServerModule implements ServerModule {
     }
 
     @Override
+    public void setContexts(Map<String, Context> contexts) {
+        this.contexts = new ArrayList<>(contexts.values());
+    }
+
+    @Override
     public void start() throws SimulatorExcepiton {
         if(loopGroup != null) {
             return;
@@ -61,7 +72,7 @@ public class S7ServerModule implements ServerModule {
                     public void initChannel(SocketChannel channel) {
                         ChannelPipeline pipeline = channel.pipeline();
                         pipeline.addLast(new S7Step7Protocol());
-                        pipeline.addLast(new S7Step7ServerAdapter());
+                        pipeline.addLast(new S7Step7ServerAdapter(contexts));
                     }
                 }).option(ChannelOption.SO_BACKLOG, 128)
                 .childOption(ChannelOption.SO_KEEPALIVE, true);
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
index 43c02bc..6a7e95b 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/protocol/S7Step7ServerAdapter.java
@@ -21,14 +21,20 @@ package org.apache.plc4x.simulator.server.s7.protocol;
 import io.netty.channel.*;
 import org.apache.plc4x.java.s7.readwrite.*;
 import org.apache.plc4x.java.s7.readwrite.types.*;
+import org.apache.plc4x.simulator.model.Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+import java.util.Map;
+
 public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(S7Step7ServerAdapter.class);
 
-    private State state = State.INITIAL;
+    private List<Context> contexts;
+
+    private State state;
 
     // COTP parameters
     private static final int localReference = 42;
@@ -48,6 +54,11 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
     private static final int maxPduLength = 240;
     private int pduLength;
 
+    public S7Step7ServerAdapter(List<Context> contexts) {
+        this.contexts = contexts;
+        state = State.INITIAL;
+    }
+
     @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
         if(msg instanceof TPKTPacket) {
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/SimulationModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/SimulationModule.java
index f08b082..c79ee22 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/SimulationModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/SimulationModule.java
@@ -18,7 +18,7 @@ under the License.
 */
 package org.apache.plc4x.simulator.simulation;
 
-import java.util.Map;
+import org.apache.plc4x.simulator.model.Context;
 
 public interface SimulationModule {
 
@@ -29,10 +29,9 @@ public interface SimulationModule {
 
     /**
      * Gives access to the internal simulations context.
-     * This is an immutable map of named properties that should contain only simple data-types.
      * @return reference to the simulations context
      */
-    Map<String, Object> getContext();
+    Context getContext();
 
     /**
      * Method for doing the actual processing inside the simulation.
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
index b41e5dd..dafd394 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/simulation/watertank/WaterTankSimulationModule.java
@@ -18,21 +18,47 @@ under the License.
 */
 package org.apache.plc4x.simulator.simulation.watertank;
 
+import org.apache.plc4x.simulator.model.Context;
 import org.apache.plc4x.simulator.simulation.SimulationModule;
 
-import java.util.Map;
-import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
+/**
+ * This is a little simulation that simulates a Water tank.
+ * This tank has a capacity who's "waterLevel" is represented as a Long value.
+ * Water can flow into the tank if the input valve is opened and it can flow
+ * out of the tank if the output valve is open.
+ *
+ * The capacity of the output is slightly smaller than that of the input, so
+ * opening both valves will result in the tank filling.
+ *
+ * To prevent the tank from bursting, there's an emergency valve which is opened
+ * as soon as the water-level reaches a critical maximum.
+ */
 public class WaterTankSimulationModule implements SimulationModule {
 
+    private static final long MAX_WATER_LEVEL = 27648L;
+    private static final long EMERGENCY_VALVE_WATER_LEVEL = 27500L;
+
+    private static final int NUM_INPUT_VALVE_INPUT = 0;
+    private static final int NUM_OUTPUT_VALVE_INPUT = 1;
+
+    private static final int EMERGENCY_VALVE_OUTPUT = 0;
+
     private static final String PROP_WATER_LEVEL = "waterLevel";
 
-    private final Map<String, Object> context;
+    private final Context context;
 
     public WaterTankSimulationModule() {
-        context = new TreeMap<>();
-        context.put(PROP_WATER_LEVEL, 0);
+        context = new Context.ContextBuilder()
+            // The input valve
+            .addDigitalInput(false)
+            // The output valve
+            .addDigitalInput(false)
+            // The emergency valve
+            .addDigitalOutput(false)
+            // The water level
+            .addMemoryVariable(PROP_WATER_LEVEL, 0L).build();
     }
 
     @Override
@@ -41,16 +67,39 @@ public class WaterTankSimulationModule implements SimulationModule {
     }
 
     @Override
-    public Map<String, Object> getContext() {
+    public Context getContext() {
         return context;
     }
 
     @Override
     public void loop() {
         // TODO: Do something sensible ;-)
+        // Just a POC for now ... to be replaced by a "real" simulation ...
         try {
-            // Just increase the level by 1 (Whatever this means ...
-            context.put(PROP_WATER_LEVEL, ((Integer) context.get(PROP_WATER_LEVEL)) + 1);
+            // Get the current value for the water tank level.
+            Long value = (Long) context.getMemory().get(PROP_WATER_LEVEL);
+
+            // If the input valve is open, add 10.
+            if(context.getDigitalInputs().get(NUM_INPUT_VALVE_INPUT)) {
+                value += 10;
+                value = Math.min(MAX_WATER_LEVEL, value);
+            }
+
+            // If the output valve is open, subtract 8 (It's slightly less throughput than the input)
+            if(context.getDigitalInputs().get(NUM_OUTPUT_VALVE_INPUT)) {
+                value -= 8;
+                value = Math.max(0, value);
+            }
+
+            // Calculate if the emergency valve should be open
+            boolean emergencyValveOpen = value > EMERGENCY_VALVE_WATER_LEVEL;
+
+            // Update the memory.
+            context.getMemory().put(PROP_WATER_LEVEL, value);
+            // Update the state of the emergency valve.
+            context.getDigitalOutputs().set(EMERGENCY_VALVE_OUTPUT, emergencyValveOpen);
+
+            // Sleep for a little while (Should probably be handled by the simulator)
             TimeUnit.MILLISECONDS.sleep(100);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();