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

[plc4x] branch feature/plc-simulator updated: [SIMULATED PLC] Improved hadler to support nearly all INTEGER types.

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


The following commit(s) were added to refs/heads/feature/plc-simulator by this push:
     new 5410825  [SIMULATED PLC] Improved hadler to support nearly all INTEGER types.
5410825 is described below

commit 54108250e5ba4b27b50c5e965118072decac60e5
Author: julian <j....@pragmaticminds.de>
AuthorDate: Fri May 22 17:41:45 2020 +0200

    [SIMULATED PLC] Improved hadler to support nearly all INTEGER types.
---
 .../org/apache/plc4x/simulator/PlcSimulator.java   |  9 ++-
 .../plc4x/simulator/server/s7/S7PlcHandler.java    |  2 +-
 .../simulator/server/s7/S7PlcHandlerBase.java      |  2 +-
 .../server/s7/{S7Value.java => S7Type.java}        | 14 +++--
 .../apache/plc4x/simulator/server/s7/S7Value.java  | 71 +++++++++++++++++++---
 .../plc4x/simulator/server/s7/S7ValueFactory.java  | 39 +++++++-----
 .../server/s7/protocol/S7Step7ServerAdapter.java   | 29 +++++----
 7 files changed, 117 insertions(+), 49 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 bc7865d..a7273b4 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
@@ -30,8 +30,7 @@ import java.util.ServiceLoader;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 
-import static org.apache.plc4x.simulator.server.s7.S7ValueFactory.INT;
-import static org.apache.plc4x.simulator.server.s7.S7ValueFactory.UINT;
+import static org.apache.plc4x.simulator.server.s7.S7ValueFactory.*;
 
 public class PlcSimulator {
 
@@ -95,11 +94,15 @@ public class PlcSimulator {
             ((S7ServerModule) serverModule).setHandler(new S7PlcHandlerBase() {
 
                 @Override
-                public S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException {
+                public S7Value readDB(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException {
                     if (byteAddress == 0) {
                         return INT((short) -42);
                     } else if (byteAddress == 2) {
                         return UINT(42);
+                    } else if (byteAddress == 4) {
+                        return LINT(-42);
+                    } else if (byteAddress == 12) {
+                        return DINT(-42);
                     } else {
                         throw new InvalidAddressException();
                     }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandler.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandler.java
index a672998..56d7a80 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandler.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandler.java
@@ -35,6 +35,6 @@ public interface S7PlcHandler {
 
     void onConnectionClosed();
 
-    S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException;
+    S7Value readDB(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException;
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandlerBase.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandlerBase.java
index ada966b..ab90272 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandlerBase.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandlerBase.java
@@ -45,7 +45,7 @@ public abstract class S7PlcHandlerBase implements S7PlcHandler {
      * Will always return invalid address.
      */
     @Override
-    public S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException {
+    public S7Value readDB(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException {
         throw new InvalidAddressException();
     }
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Type.java
similarity index 80%
copy from sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
copy to sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Type.java
index 28a4ca9..09460d7 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Type.java
@@ -25,10 +25,16 @@ package org.apache.plc4x.simulator.server.s7;
  * @author julian
  * Created by julian on 22.05.20
  */
-public interface S7Value {
+public enum S7Type {
+    INT(short.class),
+    UINT(int.class),
+    DINT(int.class),
+    LINT(long.class),
+    REAL(float.class);
 
-    void _int();
-    void _uint();
-    void _real();
+    private Class<?> javaType;
 
+    S7Type(Class<?> javaType) {
+        this.javaType = javaType;
+    }
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
index 28a4ca9..6df01d7 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
@@ -19,16 +19,67 @@
 
 package org.apache.plc4x.simulator.server.s7;
 
-/**
- * TODO write comment
- *
- * @author julian
- * Created by julian on 22.05.20
- */
-public interface S7Value {
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+public class S7Value {
+
+    private final S7Type type;
+    private final Object value;
+
+    S7Value(S7Type type, Object value) {
+        this.type = type;
+        this.value = value;
+    }
+
+    public S7Type getType() {
+        return type;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public byte[] getData() {
+        try {
+            WriteBuffer writeBuffer;
+            switch (type) {
+                case INT:
+                    writeBuffer = new WriteBuffer(2, false);
+                    writeBuffer.writeShort(16, ((short) value));
+                    break;
+                case UINT:
+                    writeBuffer = new WriteBuffer(2, false);
+                    writeBuffer.writeUnsignedInt(16, ((int) value));
+                    break;
+                case DINT:
+                    writeBuffer = new WriteBuffer(4, false);
+                    writeBuffer.writeInt(32, ((int) value));
+                    break;
+                case LINT:
+                    writeBuffer = new WriteBuffer(8, false);
+                    writeBuffer.writeLong(64, ((long) value));
+                    break;
+                case REAL:
+                    writeBuffer = new WriteBuffer(4, false);
+                    writeBuffer.writeFloat(32, ((float) value));
+                    break;
+                default:
+                    throw new NotImplementedException("Currently the type " + type + " is not implemented!");
+            }
+            return writeBuffer.getData();
+        } catch (ParseException e) {
+            throw new IllegalStateException("This should not happen!", e);
+        }
+    }
 
-    void _int();
-    void _uint();
-    void _real();
+    @Override
+    public String toString() {
+        return "S7Value{" +
+            "type=" + type +
+            ", value=" + value +
+            '}';
+    }
 
 }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ValueFactory.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ValueFactory.java
index 1f88e5c..d0d69b7 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ValueFactory.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ValueFactory.java
@@ -32,42 +32,51 @@ import java.math.BigInteger;
 public class S7ValueFactory {
 
     // Signed 2 Byte INT
-    public static S7Int INT(short s) {
-        return S7Int.INT(s);
+    public static S7Value INT(short s) {
+        return new S7Value(S7Type.INT, s);
     }
 
     // Unsigned 2 Byte INT
-    public static S7Int UINT(int i) {
-        return S7Int.UINT(i);
+    public static S7Value UINT(int i) {
+        checkUnsigned(i);
+        return new S7Value(S7Type.UINT, i);
     }
 
     // Signed 4 Byte INT
-    public static S7Int DINT(int l) {
-        throw new NotImplementedException("");
+    public static S7Value DINT(int i) {
+        return new S7Value(S7Type.DINT, i);
     }
 
-    // Signed 8 Byte Int
-    public static S7Int LINT(long l) {
+    // Unsigned 4 Byte INT
+    public static S7Value UDINT(long l) {
+        checkUnsigned(l);
         throw new NotImplementedException("");
     }
 
-    // Unsigned 4 Byte INT
-    public static S7Int UDINT(long l) {
-        throw new NotImplementedException("");
+    // Signed 8 Byte Int
+    public static S7Value LINT(long l) {
+        return new S7Value(S7Type.LINT, l);
     }
 
     // Unsigned 8 Byte INT
-    public static S7Int ULINT(BigInteger bi) {
+    public static S7Value ULINT(BigInteger bi) {
+        checkUnsigned(bi.doubleValue());
         throw new NotImplementedException("");
     }
 
     // 4 Byte floating point
-    public static Object REAL(float f) {
-        throw new NotImplementedException("");
+    public static S7Value REAL(float f) {
+        return new S7Value(S7Type.REAL, f);
     }
 
     // 8 Byte floating point
-    public static Object LREAL(double d) {
+    public static S7Value LREAL(double d) {
         throw new NotImplementedException("");
     }
+
+    private static void checkUnsigned(double v) {
+        if (v < 0) {
+            throw new IllegalArgumentException("Unsigned Value cannot have negative value");
+        }
+    }
 }
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 8391d61..00f72f3 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
@@ -19,12 +19,14 @@ under the License.
 package org.apache.plc4x.simulator.server.s7.protocol;
 
 import io.netty.channel.*;
+import org.apache.commons.lang3.NotImplementedException;
 import org.apache.plc4x.java.s7.readwrite.*;
 import org.apache.plc4x.java.s7.readwrite.types.*;
 import org.apache.plc4x.java.spi.generation.WriteBuffer;
 import org.apache.plc4x.simulator.server.s7.InvalidAddressException;
 import org.apache.plc4x.simulator.server.s7.S7Int;
 import org.apache.plc4x.simulator.server.s7.S7PlcHandler;
+import org.apache.plc4x.simulator.server.s7.S7Value;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -267,34 +269,31 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
                                                     final byte bitAddress = addressAny.getBitAddress();
                                                     switch (addressAny.getTransportSize()) {
                                                         case INT: // These case should never happen. UINT will always be picked
+                                                        case DINT:
+                                                        case LINT:
+                                                        case LTIME: // Is given for some transports LINT
+                                                        case UDINT: // Is given for DINT
                                                         case UINT: {
                                                             // The value should be represented as Short
-                                                            S7Int s7Int;
+                                                            S7Value value;
                                                             try {
-                                                                s7Int = handler.readIntFromDataBlock(addressAny.getDbNumber(), addressAny.getByteAddress(), addressAny.getBitAddress());
-                                                            } catch (InvalidAddressException e) {
-                                                                // Send a INVALID_ADDRESS response
-                                                                payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.INVALID_ADDRESS, DataTransportSize.NULL, 0, new byte[0]);
-                                                                break;
+                                                                value = handler.readDB(addressAny.getDbNumber(), addressAny.getByteAddress(), addressAny.getBitAddress());
                                                             } catch (Exception e) {
-                                                                // We have no idea, so just send INVALID_ADDRESS ?
+                                                                // Send a INVALID_ADDRESS response
                                                                 payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.INVALID_ADDRESS, DataTransportSize.NULL, 0, new byte[0]);
                                                                 break;
                                                             }
 
-                                                            WriteBuffer writeBuffer = new WriteBuffer(2, false);
-                                                            if (s7Int.isSigned()) {
-                                                                writeBuffer.writeShort(16, s7Int.getSigned());
-                                                            } else {
-                                                                writeBuffer.writeUnsignedInt(16, s7Int.getUnsigned());
-                                                            }
-                                                            byte[] data = writeBuffer.getData();
+
+                                                            byte[] data = value.getData();
 
                                                             payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, 8 * data.length, data);
                                                             break;
                                                         }
                                                         default: {
-                                                            // TODO: Return invalid address.
+                                                            LOGGER.warn("Got a request with unhandled type {}, returning INVALID_ADDRESS", addressAny.getTransportSize());
+                                                            payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.INVALID_ADDRESS, DataTransportSize.NULL, 0, new byte[0]);
+                                                            break;
                                                         }
                                                     }
                                                     break;