You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2018/03/11 10:09:30 UTC
[incubator-plc4x] 01/05: - Renamed the S7 encoders and decoders
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
commit ad387967f4aa8cfbd034a78637ecf120e746b4c5
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Mar 11 11:05:41 2018 +0100
- Renamed the S7 encoders and decoders
---
.../plc4x/java/s7/netty/Plc4XS7Protocol.java | 4 +-
.../org/apache/plc4x/java/s7/netty/S7Protocol.java | 50 ++++++++++++++++++----
.../{BigEndianDecoder.java => S7TypeDecoder.java} | 24 +++++++----
.../{BigEndianEncoder.java => S7TypeEncoder.java} | 4 +-
4 files changed, 61 insertions(+), 21 deletions(-)
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
index 9fcec13..750ed62 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java
@@ -49,8 +49,8 @@ import org.apache.plc4x.java.s7.netty.model.types.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
-import static org.apache.plc4x.java.s7.netty.util.BigEndianDecoder.decodeData;
-import static org.apache.plc4x.java.s7.netty.util.BigEndianEncoder.encodeData;
+import static org.apache.plc4x.java.s7.netty.util.S7TypeDecoder.decodeData;
+import static org.apache.plc4x.java.s7.netty.util.S7TypeEncoder.encodeData;
public class Plc4XS7Protocol extends MessageToMessageCodec<S7Message, PlcRequestContainer> {
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
index 2aa4a75..40398d0 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/S7Protocol.java
@@ -43,16 +43,16 @@ import org.apache.plc4x.java.s7.netty.model.types.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
public class S7Protocol extends MessageToMessageCodec<IsoTPMessage, S7Message> {
- public static final byte S7_PROTOCOL_MAGIC_NUMBER = 0x32;
+ private static final byte S7_PROTOCOL_MAGIC_NUMBER = 0x32;
private static final Logger logger = LoggerFactory.getLogger(S7Protocol.class);
+ private Map<Short, List<S7Message>> messageFragments = new HashMap<>();
+
private short maxAmqCaller;
private short maxAmqCallee;
private short pduSize;
@@ -81,13 +81,45 @@ public class S7Protocol extends MessageToMessageCodec<IsoTPMessage, S7Message> {
protected void encode(ChannelHandlerContext ctx, S7Message in, List<Object> out) {
logger.debug("S7 Message sent");
- ByteBuf buf = Unpooled.buffer();
+ List<S7Message> messages = splitMessage(in);
+ messageFragments.put(in.getTpduReference(), messages);
+
+ for (S7Message message : messages) {
+ ByteBuf buf = Unpooled.buffer();
+
+ encodeHeader(message, buf);
+ encodeParameters(message, buf);
+ encodePayloads(message, buf);
- encodeHeader(in, buf);
- encodeParameters(in, buf);
- encodePayloads(in, buf);
+ out.add(new DataTpdu(true, (byte) 1, Collections.emptyList(), buf));
+ }
+ }
- out.add(new DataTpdu(true, (byte) 1, Collections.emptyList(), buf));
+ /**
+ * While a SetupCommunication message is no problem, when reading multiple
+ * addresses in one request, the size of the PDU could be exceeded, therefore we need
+ * to split up one incoming message. When writing, the S7 PLCs only seem to accept
+ * writing of single elements, so we have to break up writing of multiple values into
+ * multiple single-value write operations.
+ *
+ * @param message incoming message
+ * @return List of outgoing messages
+ */
+ private List<S7Message> splitMessage(S7Message message) {
+ // The following considerations have to be taken into account:
+ // - The size of all parameters and payloads of a message cannot exceed the negotiated PDU size
+ // - When reading data, the size of the returned data cannot exceed the negotiated PDU size
+ //
+ // Examples:
+ // - Size of the request exceeds the maximum
+ // When having a negotiated max PDU size of 256, the maximum size of individual addresses can be at most 18
+ // If more are sent, the S7 will respond with a frame error.
+ // - Size of the response exceeds the maximum
+ // When reading two Strings of each 200 bytes length, the size of the request is ok, however the PLC would
+ // have to send back 400 bytes of String data, which would exceed the PDU size. In this case the first String
+ // is correctly returned, but for the second item the PLC will return a code of 0x03 = Access Denied
+
+ return Collections.singletonList(message);
}
private void encodePayloads(S7Message in, ByteBuf buf) {
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianDecoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java
similarity index 76%
rename from plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianDecoder.java
rename to plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java
index 6e22bcd..ac67863 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianDecoder.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java
@@ -20,12 +20,13 @@ package org.apache.plc4x.java.s7.netty.util;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
+import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
-public class BigEndianDecoder {
+public class S7TypeDecoder {
- private BigEndianDecoder() {
+ private S7TypeDecoder() {
// Utility class
}
@@ -58,13 +59,20 @@ public class BigEndianDecoder {
result.add(Float.intBitsToFloat(intValue));
i += 4;
} else if (datatype == String.class) {
- StringBuilder builder = new StringBuilder();
- while (s7Data[i] != (byte) 0x0 && i < length) {
- builder.append((char) s7Data[i]);
- i++;
+ // Every string value had a prefix of two bytes for which I have no idea, what the meaning is.
+ // This code assumes the string values doesn't contain UTF-8 values with a code of 0x00 as it
+ // uses this as termination char.
+ try {
+ int j = 0;
+ for(; j < s7Data.length; j++) {
+ if(s7Data[j] == 0) {
+ break;
+ }
+ }
+ result.add(new String(s7Data, 2, j - 2, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new PlcProtocolException("Error decoding String value");
}
- i++; // skip terminating character
- result.add(builder.toString());
} else {
throw new PlcProtocolException("Unsupported datatype " + datatype.getSimpleName());
}
diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianEncoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java
similarity index 98%
rename from plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianEncoder.java
rename to plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java
index f9d1159..5c50e50 100644
--- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/BigEndianEncoder.java
+++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java
@@ -20,9 +20,9 @@ package org.apache.plc4x.java.s7.netty.util;
import java.util.Calendar;
-public class BigEndianEncoder {
+public class S7TypeEncoder {
- private BigEndianEncoder() {
+ private S7TypeEncoder() {
// Utility class
}
--
To stop receiving notification emails like this one, please contact
cdutz@apache.org.