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 14:53:41 UTC
[plc4x] 02/02: [SIMULATED PLC] Many improvements.
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 53d36ee4bf6d3badea248fbb02cc2cbd86455e62
Author: julian <j....@pragmaticminds.de>
AuthorDate: Fri May 22 16:53:32 2020 +0200
[SIMULATED PLC] Many improvements.
---
.../plc4x/java/spi/optimizer/BaseOptimizer.java | 3 +-
.../org/apache/plc4x/simulator/PlcSimulator.java | 31 +++-----
.../simulator/server/s7/FieldReadException.java | 29 ++++++++
.../server/s7/InvalidAddressException.java | 30 ++++++++
.../apache/plc4x/simulator/server/s7/S7Int.java | 84 ++++++++++++++++++++++
.../plc4x/simulator/server/s7/S7PlcHandler.java | 63 ++--------------
.../simulator/server/s7/S7PlcHandlerBase.java | 51 +++++++++++++
.../apache/plc4x/simulator/server/s7/S7Value.java | 34 +++++++++
.../plc4x/simulator/server/s7/S7ValueFactory.java | 73 +++++++++++++++++++
.../server/s7/protocol/S7Step7ServerAdapter.java | 22 +++++-
10 files changed, 339 insertions(+), 81 deletions(-)
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
index 3c252f4..d352e4e 100644
--- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/optimizer/BaseOptimizer.java
@@ -51,7 +51,8 @@ public abstract class BaseOptimizer {
PlcReadResponse subReadResponse = (PlcReadResponse) readResponse.getLeft();
fields.put(fieldName,
new ResponseItem<>(subReadResponse.getResponseCode(fieldName),
- subReadResponse.getAsPlcValue().getValue(fieldName)));
+ // We cannot safely access the response value if response code != OK
+ subReadResponse.getResponseCode(fieldName) == PlcResponseCode.OK ? subReadResponse.getAsPlcValue().getValue(fieldName) : null));
} else {
fields.put(fieldName, new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, null));
}
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 360097f..bc7865d 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
@@ -20,8 +20,7 @@ package org.apache.plc4x.simulator;
import org.apache.plc4x.simulator.model.Context;
import org.apache.plc4x.simulator.server.ServerModule;
-import org.apache.plc4x.simulator.server.s7.S7PlcHandler;
-import org.apache.plc4x.simulator.server.s7.S7ServerModule;
+import org.apache.plc4x.simulator.server.s7.*;
import org.apache.plc4x.simulator.simulation.SimulationModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -31,6 +30,9 @@ 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;
+
public class PlcSimulator {
private static final Logger LOGGER = LoggerFactory.getLogger(PlcSimulator.class);
@@ -90,30 +92,19 @@ public class PlcSimulator {
LOGGER.info("Starting Server Modules:");
for (ServerModule serverModule : serverModules.values()) {
LOGGER.info(String.format("Starting server module: %s ...", serverModule.getName()));
- ((S7ServerModule) serverModule).setHandler(new S7PlcHandler() {
- @Override
- public void onConnectionInitiated() {
-
- }
+ ((S7ServerModule) serverModule).setHandler(new S7PlcHandlerBase() {
@Override
- public void onConnectionEstablished() {
-
- }
-
- @Override
- public void onConnectionClosed() {
-
- }
-
- @Override
- public S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress) {
+ public S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress) throws FieldReadException {
if (byteAddress == 0) {
- return S7Int._int((short) -42);
+ return INT((short) -42);
+ } else if (byteAddress == 2) {
+ return UINT(42);
} else {
- return S7Int._uint(42);
+ throw new InvalidAddressException();
}
}
+
});
serverModule.start();
LOGGER.info("Started");
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/FieldReadException.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/FieldReadException.java
new file mode 100644
index 0000000..cb860b6
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/FieldReadException.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Base class for Exceptions that can occur when a Filed is read.
+ *
+ * @author julian
+ * Created by julian on 22.05.20
+ */
+public abstract class FieldReadException extends Exception {
+}
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/InvalidAddressException.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/InvalidAddressException.java
new file mode 100644
index 0000000..078f57b
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/InvalidAddressException.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Exception that indicates that the Field is not known.
+ * This results in {@link org.apache.plc4x.java.api.types.PlcResponseCode}s INVALID_ADDRESS.
+ *
+ * @author julian
+ * Created by julian on 22.05.20
+ */
+public class InvalidAddressException extends FieldReadException {
+}
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Int.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Int.java
new file mode 100644
index 0000000..f5303c9
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Int.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+/**
+ * TODO write comment
+ *
+ * @author julian
+ * Created by julian on 22.05.20
+ */
+public class S7Int {
+
+ private final Short signed;
+ private final Integer unsigned;
+
+ public S7Int(short signed) {
+ this.signed = signed;
+ this.unsigned = null;
+ }
+
+ public S7Int(int unsigned) {
+ if (unsigned < 0) {
+ throw new IllegalArgumentException("Signed value cannot be negative!");
+ }
+ this.unsigned = unsigned;
+ this.signed = null;
+ }
+
+ public static S7Int INT(short signed) {
+ return new S7Int(signed);
+ }
+
+ public static S7Int UINT(int unsigned) {
+ return new S7Int(unsigned);
+ }
+
+ public boolean isSigned() {
+ return signed != null;
+ }
+
+ public boolean isUnsigned() {
+ return unsigned != null;
+ }
+
+ public short getSigned() {
+ if (!isSigned()) {
+ throw new UnsupportedOperationException("Cannot get signed on unsigned!");
+ }
+ return signed;
+ }
+
+ public Integer getUnsigned() {
+ if (!isUnsigned()) {
+ throw new UnsupportedOperationException("Cannot get unsigned on signed!");
+ }
+ return unsigned;
+ }
+
+ @Override
+ public String toString() {
+ if (isSigned()) {
+ return "Signed(" + signed + ")";
+ } else {
+ return "Unsigned(" + unsigned + ")";
+ }
+ }
+}
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 d5b8efb..a672998 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
@@ -19,6 +19,8 @@
package org.apache.plc4x.simulator.server.s7;
+import java.net.InetSocketAddress;
+
/**
* Handler for PLC Server.
*
@@ -27,69 +29,12 @@ package org.apache.plc4x.simulator.server.s7;
*/
public interface S7PlcHandler {
- void onConnectionInitiated();
+ void onConnectionInitiated(InetSocketAddress remoteAddress);
void onConnectionEstablished();
void onConnectionClosed();
- S7Int readIntFromDataBlock(int dbNumber, int byteAddress, byte bitAddress);
-
- class S7Int {
- private final Short signed;
- private final Integer unsigned;
-
- public S7Int(short signed) {
- this.signed = signed;
- this.unsigned = null;
- }
-
- public S7Int(int unsigned) {
- if (unsigned < 0) {
- throw new IllegalArgumentException("Signed value cannot be negative!");
- }
- this.unsigned = unsigned;
- this.signed = null;
- }
-
- public static S7Int _int(short signed) {
- return new S7Int(signed);
- }
-
- public static S7Int _uint(int unsigned) {
- return new S7Int(unsigned);
- }
-
- public boolean isSigned() {
- return signed != null;
- }
-
- public boolean isUnsigned() {
- return unsigned != null;
- }
-
- public short getSigned() {
- if (!isSigned()) {
- throw new UnsupportedOperationException("Cannot get signed on unsigned!");
- }
- return signed;
- }
-
- public Integer getUnsigned() {
- if (!isUnsigned()) {
- throw new UnsupportedOperationException("Cannot get unsigned on signed!");
- }
- return unsigned;
- }
-
- @Override
- public String toString() {
- if (isSigned()) {
- return "Signed(" + signed + ")";
- } else {
- return "Unsigned(" + unsigned + ")";
- }
- }
- }
+ S7Int readIntFromDataBlock(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
new file mode 100644
index 0000000..ada966b
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7PlcHandlerBase.java
@@ -0,0 +1,51 @@
+/*
+ * 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 java.net.InetSocketAddress;
+
+/**
+ * Base Implementation.
+ */
+public abstract class S7PlcHandlerBase implements S7PlcHandler {
+
+ @Override
+ public void onConnectionInitiated(InetSocketAddress remoteAddress) {
+ // Intentionally do nothing
+ }
+
+ @Override
+ public void onConnectionEstablished() {
+ // Intentionally do nothing
+ }
+
+ @Override
+ public void onConnectionClosed() {
+ // Intentionally do nothing
+ }
+
+ /**
+ * Will always return invalid address.
+ */
+ @Override
+ public S7Int readIntFromDataBlock(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/S7Value.java
new file mode 100644
index 0000000..28a4ca9
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7Value.java
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * TODO write comment
+ *
+ * @author julian
+ * Created by julian on 22.05.20
+ */
+public interface S7Value {
+
+ void _int();
+ void _uint();
+ void _real();
+
+}
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
new file mode 100644
index 0000000..1f88e5c
--- /dev/null
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/s7/S7ValueFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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 org.apache.commons.lang3.NotImplementedException;
+
+import java.math.BigInteger;
+
+/**
+ * TODO write comment
+ *
+ * @author julian
+ * Created by julian on 22.05.20
+ */
+public class S7ValueFactory {
+
+ // Signed 2 Byte INT
+ public static S7Int INT(short s) {
+ return S7Int.INT(s);
+ }
+
+ // Unsigned 2 Byte INT
+ public static S7Int UINT(int i) {
+ return S7Int.UINT(i);
+ }
+
+ // Signed 4 Byte INT
+ public static S7Int DINT(int l) {
+ throw new NotImplementedException("");
+ }
+
+ // Signed 8 Byte Int
+ public static S7Int LINT(long l) {
+ throw new NotImplementedException("");
+ }
+
+ // Unsigned 4 Byte INT
+ public static S7Int UDINT(long l) {
+ throw new NotImplementedException("");
+ }
+
+ // Unsigned 8 Byte INT
+ public static S7Int ULINT(BigInteger bi) {
+ throw new NotImplementedException("");
+ }
+
+ // 4 Byte floating point
+ public static Object REAL(float f) {
+ throw new NotImplementedException("");
+ }
+
+ // 8 Byte floating point
+ public static Object LREAL(double d) {
+ throw new NotImplementedException("");
+ }
+}
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 74bd580..8391d61 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
@@ -22,10 +22,13 @@ import io.netty.channel.*;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
@@ -73,6 +76,9 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
return;
}
+ // Callback
+ handler.onConnectionInitiated((InetSocketAddress) ctx.pipeline().channel().remoteAddress());
+
COTPTpduSize proposedTpduSize = null;
COTPPacketConnectionRequest cotpConnectionRequest = (COTPPacketConnectionRequest) cotpPacket;
for (COTPParameter parameter : cotpConnectionRequest.getParameters()) {
@@ -146,6 +152,9 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
s7TpduReference, s7ParameterSetupCommunicationResponse, null, (short) 0, (short) 0);
ctx.writeAndFlush(new TPKTPacket(new COTPPacketData(null, s7MessageResponse, true, cotpTpduRef)));
+ // Now we should be connected
+ handler.onConnectionEstablished();
+
state = State.S7_CONNECTED;
break;
}
@@ -260,7 +269,18 @@ public class S7Step7ServerAdapter extends ChannelInboundHandlerAdapter {
case INT: // These case should never happen. UINT will always be picked
case UINT: {
// The value should be represented as Short
- S7PlcHandler.S7Int s7Int = handler.readIntFromDataBlock(addressAny.getDbNumber(), addressAny.getByteAddress(), addressAny.getBitAddress());
+ S7Int s7Int;
+ 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;
+ } catch (Exception e) {
+ // We have no idea, so just send INVALID_ADDRESS ?
+ payloadItems[i] = new S7VarPayloadDataItem(DataTransportErrorCode.INVALID_ADDRESS, DataTransportSize.NULL, 0, new byte[0]);
+ break;
+ }
WriteBuffer writeBuffer = new WriteBuffer(2, false);
if (s7Int.isSigned()) {