Skip to content

Commit 6c2e43e

Browse files
committed
Types are matched to S7-definitions
1 parent 9d5c3b8 commit 6c2e43e

File tree

8 files changed

+94
-107
lines changed

8 files changed

+94
-107
lines changed

modules/hivemq-edge-module-s7/src/main/java/com/hivemq/edge/adapters/s7/S7Client.java

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.hivemq.edge.adapters.s7;
22

33
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
4+
import com.github.xingshuangs.iot.protocol.s7.service.MultiAddressRead;
45
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
6+
import com.github.xingshuangs.iot.protocol.s7.utils.AddressUtil;
57
import com.hivemq.adapter.sdk.api.data.DataPoint;
68
import com.hivemq.adapter.sdk.api.factories.DataPointFactory;
79
import com.hivemq.edge.adapters.s7.config.S7AdapterConfig;
@@ -33,55 +35,61 @@ public S7Client(final @NotNull EPlcType elpcType, final @NotNull String hostname
3335
this.dataPointFactory = dataPointFactory;
3436
}
3537

36-
37-
public DataPoint readByte(final String address) {
38-
if(log.isTraceEnabled()) {
39-
log.trace("Reading bytes from address {} with count {}", address, 1);
40-
}
41-
return dataPointFactory.create(address, s7PLC.readByte(address, 1)[0]);
42-
}
43-
44-
45-
public DataPoint readBytes(final String address, final int count) {
46-
if(log.isTraceEnabled()) {
47-
log.trace("Reading bytes from address {} with count {}", address, count);
48-
}
49-
return dataPointFactory.create(address, s7PLC.readByte(address, count));
50-
}
51-
5238
public List<DataPoint> read(final @NotNull S7DataType type, final @NotNull List<String> addresses) {
5339
if(log.isTraceEnabled()) {
5440
log.trace("Reading data from addresses {} with type {}", addresses, type);
5541
}
5642
switch (type) {
5743
case BOOL: return combine(dataPointFactory, addresses, s7PLC.readBoolean(addresses));
58-
case BYTE: throw new IllegalArgumentException("Byte data type not supported by this method, use readBytes");
59-
case WORD: return null;
60-
case DWORD: return null;
61-
case LWORD: return null;
62-
case USINT: return combine(dataPointFactory, addresses, s7PLC.readUInt16(addresses));
63-
case UINT: return null;
44+
case BYTE: return addresses.stream().map(address -> dataPointFactory
45+
.create(address, s7PLC.readByte(address)))
46+
.collect(Collectors.toList());
47+
case WORD: return combine(dataPointFactory, addresses, s7PLC.readInt16(addresses));
48+
case DWORD: return combine(dataPointFactory, addresses, s7PLC.readInt32(addresses));
49+
case LWORD: return combine(dataPointFactory, addresses, s7PLC.readInt64(addresses));
50+
case USINT: return addresses.stream().map(address -> dataPointFactory
51+
.create(address, Byte.toUnsignedInt(s7PLC.readByte(address))))
52+
.collect(Collectors.toList());
53+
case UINT: return combine(dataPointFactory, addresses, s7PLC.readUInt16(addresses));
6454
case UDINT: return combine(dataPointFactory, addresses, s7PLC.readUInt32(addresses));
65-
case ULINT: return null;
66-
case SINT: return null;
55+
case ULINT: return addresses.stream()
56+
.map(address -> dataPointFactory.create(address, new BigInteger(Long.toUnsignedString(s7PLC.readInt64(address)))))
57+
.collect(Collectors.toList());
58+
case SINT: return addresses.stream().map(address -> dataPointFactory
59+
.create(address, ((Byte)s7PLC.readByte(address)).shortValue()))
60+
.collect(Collectors.toList());
6761
case INT: return combine(dataPointFactory, addresses, s7PLC.readInt16(addresses));
6862
case DINT: return combine(dataPointFactory, addresses, s7PLC.readInt32(addresses));
6963
case LINT: return combine(dataPointFactory, addresses, s7PLC.readInt64(addresses));
7064
case REAL: return combine(dataPointFactory, addresses, s7PLC.readFloat32(addresses));
7165
case LREAL: return combine(dataPointFactory, addresses, s7PLC.readFloat64(addresses));
72-
case CHAR: return null;
73-
case WCHAR: return null;
74-
case STRING: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readString).collect(Collectors.toList()));
75-
case WSTRING: return null;
66+
case CHAR: return addresses.stream().map(address -> dataPointFactory
67+
.create(address, s7PLC.readByte(address)))
68+
.collect(Collectors.toList());
69+
case WCHAR: return addresses.stream()
70+
.map(address -> {
71+
final byte[] bytes = s7PLC.readByte(address, 2);
72+
final char charValue = (char) ((bytes[0] & 0xff) << 8 | (bytes[1] & 0xff));
73+
return dataPointFactory.create(address, charValue);
74+
})
75+
.collect(Collectors.toList());
76+
case STRING:
77+
case WSTRING: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readString).collect(Collectors.toList()));
7678
case TIME: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readTime).collect(Collectors.toList()));
77-
case LTIME: return null;
79+
case LTIME: return combine(dataPointFactory, addresses, s7PLC.readInt64(addresses));
7880
case DATE: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readDate).collect(Collectors.toList()));
7981
case TOD: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readTimeOfDay).collect(Collectors.toList()));
80-
case LTOD: return null;
81-
case DT: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readDTL).collect(Collectors.toList()));
82-
case LDT: return null;
83-
case DTL: return null;
84-
case ARRAY: return null;
82+
case LTOD: return addresses.stream()
83+
.map(address -> dataPointFactory.create(address, new BigInteger(Long.toUnsignedString(s7PLC.readInt64(address)))))
84+
.collect(Collectors.toList());
85+
case DT: return addresses.stream()
86+
.map(address -> dataPointFactory.create(address, s7PLC.readDate(address)))
87+
.collect(Collectors.toList());
88+
case LDT:return addresses.stream()
89+
.map(address -> dataPointFactory.create(address, new BigInteger(Long.toUnsignedString(s7PLC.readInt64(address)))))
90+
.collect(Collectors.toList());
91+
case DTL: return combine(dataPointFactory, addresses, addresses.stream().map(s7PLC::readDTL).collect(Collectors.toList()));
92+
case ARRAY: throw new IllegalArgumentException("Arrays not supported");
8593
default: {
8694
log.error("Unspported tag-type {} at address {}", type, addresses);
8795
throw new IllegalArgumentException("Unspported tag-type " + type + " at address " + addresses);

modules/hivemq-edge-module-s7/src/main/java/com/hivemq/edge/adapters/s7/S7ProtocolAdapter.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,7 @@ public void poll(@NotNull final PollingInput pollingInput, @NotNull final Pollin
129129
S7TagDefinition tagDefinition = tagToRead.getDefinition();
130130
//Every S7 address starts with a % but the iot-communications lib doesn't like it, so we are stripping it.
131131
final String tagAddress = tagDefinition.getAddress().replace("%","");
132-
final DataPoint dataPoint;
133-
if(tagDefinition.getDataType() == S7DataType.BYTE) {
134-
dataPoint = s7Client.readByte(tagAddress);
135-
} else {
136-
dataPoint = s7Client.read(tagDefinition.getDataType(), List.of(tagAddress)).get(0);
137-
}
132+
final DataPoint dataPoint = s7Client.read(tagDefinition.getDataType(), List.of(tagAddress)).get(0);
138133

139134
if(adapterConfig.getS7ToMqttConfig().getPublishChangedDataOnly()) {
140135
if(dataPoints.containsKey(tagAddress)) {

modules/hivemq-edge-module-s7/src/main/java/com/hivemq/edge/adapters/s7/config/S7AdapterConfig.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@
2222
import org.jetbrains.annotations.NotNull;
2323
import org.jetbrains.annotations.Nullable;
2424

25-
public class S7AdapterConfig implements ProtocolSpecificAdapterConfig {
25+
import java.util.Objects;
2626

27-
private static final @NotNull String ID_REGEX = "^([a-zA-Z_0-9-_])*$";
27+
public class S7AdapterConfig implements ProtocolSpecificAdapterConfig {
2828

2929
private static final int PORT_MIN = 1;
3030
private static final int PORT_MAX = 65535;
3131

32-
public static final String DEFAULT_S7_PORT = "102";
32+
public static final int DEFAULT_S7_PORT = 102;
3333
public static final String DEFAULT_CONTROLER_TYPE = "S7_300";
3434

35-
public static final String PROPERTY_ID = "id";
3635
public static final String PROPERTY_PORT = "port";
3736
public static final String PROPERTY_HOST = "host";
3837
public static final String PROPERTY_CONTROLLER_TYPE = "controllerType";
@@ -51,14 +50,14 @@ public enum ControllerType {
5150
SINUMERIK_828D
5251
}
5352

54-
@JsonProperty(value = PROPERTY_PORT, required = true)
53+
@JsonProperty(value = PROPERTY_PORT)
5554
@ModuleConfigField(title = "Port",
5655
description = "The port number on the device to connect to",
5756
required = true,
58-
defaultValue = DEFAULT_S7_PORT,
57+
defaultValue = "" + DEFAULT_S7_PORT,
5958
numberMin = PORT_MIN,
6059
numberMax = PORT_MAX)
61-
private final int port;
60+
private final @NotNull Integer port;
6261

6362
@JsonProperty(value = PROPERTY_HOST, required = true)
6463
@ModuleConfigField(title = "Host",
@@ -91,27 +90,30 @@ public enum ControllerType {
9190

9291
@JsonProperty(value = PROPERTY_S_7_TO_MQTT, required = true)
9392
@ModuleConfigField(title = "S7 To MQTT Config",
94-
description = "The configuration for a data stream from S7 to MQTT",
95-
required = true)
93+
description = "The configuration for a data stream from S7 to MQTT")
9694
private final @NotNull S7ToMqttConfig s7ToMqttConfig;
9795

9896
@JsonCreator
9997
public S7AdapterConfig(
100-
@JsonProperty(value = PROPERTY_ID, required = true) final @NotNull String id,
101-
@JsonProperty(value = PROPERTY_PORT, required = true) final Integer port,
98+
@JsonProperty(value = PROPERTY_PORT) final Integer port,
10299
@JsonProperty(value = PROPERTY_HOST, required = true) final @NotNull String host,
103100
@JsonProperty(value = PROPERTY_CONTROLLER_TYPE, required = true) final @NotNull ControllerType controllerType,
104101
@JsonProperty(value = PROPERTY_REMOTE_RACK) final @Nullable Integer remoteRack,
105102
@JsonProperty(value = PROPERTY_REMOTE_SLOT) final @Nullable Integer remoteSlot,
106103
@JsonProperty(value = PROPERTY_PDU_LENGTH) final @Nullable Integer pduLength,
107-
@JsonProperty(value = PROPERTY_S_7_TO_MQTT, required = true) final @NotNull S7ToMqttConfig s7ToMqttConfig) {
104+
@JsonProperty(value = PROPERTY_S_7_TO_MQTT) final @Nullable S7ToMqttConfig s7ToMqttConfig) {
108105
this.host = host;
109106
this.controllerType = controllerType;
110-
this.port = port;
107+
this.port = Objects.requireNonNullElse(port, DEFAULT_S7_PORT);
111108
this.remoteRack = remoteRack;
112109
this.remoteSlot = remoteSlot;
113110
this.pduLength = pduLength;
114-
this.s7ToMqttConfig = s7ToMqttConfig;
111+
112+
if (s7ToMqttConfig == null) {
113+
this.s7ToMqttConfig = new S7ToMqttConfig(null, null, null);
114+
} else {
115+
this.s7ToMqttConfig = s7ToMqttConfig;
116+
}
115117
}
116118

117119
public int getPort() {

modules/hivemq-edge-module-s7/src/main/java/com/hivemq/edge/adapters/s7/config/S7DataType.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,35 @@
3636
public enum S7DataType {
3737
BOOL(Boolean.class, 1, List.of(S7_300, S7_400, S7_1200, S7_1500), "Boolean", "https://support.industry.siemens.com/cs/mdm/109054417?c=46422035979&lc=en-GE"),
3838
BYTE(Byte.class, 8, List.of(S7_300, S7_400, S7_1200, S7_1500), "Byte", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595553163&lc=en-GE"),
39-
WORD(Byte[].class, 16, List.of(S7_300, S7_400, S7_1200, S7_1500), "Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595472523&lc=en-GE"),
40-
DWORD(Byte[].class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "Double Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595322763&lc=en-GE"),
41-
LWORD(Byte[].class, 64, List.of(S7_1500), "Long Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595507211&lc=en-GE"),
42-
USINT(Short.class, 8, List.of(S7_1200, S7_1500), "Unsigned Short Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=46521647883&lc=en-GE"),
39+
WORD(Short.class, 16, List.of(S7_300, S7_400, S7_1200, S7_1500), "Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595472523&lc=en-GE"),
40+
DWORD(Integer.class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "Double Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595322763&lc=en-GE"),
41+
LWORD(Long.class, 64, List.of(S7_1500), "Long Word", "https://support.industry.siemens.com/cs/mdm/109054417?c=56595507211&lc=en-GE"),
42+
USINT(Integer.class, 8, List.of(S7_1200, S7_1500), "Unsigned Short Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=46521647883&lc=en-GE"),
4343
UINT(Integer.class, 16, List.of(S7_1200, S7_1500), "Unsigned Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=46521834123&lc=en-GE"),
4444
UDINT(Long.class, 32, List.of(S7_1200, S7_1500), "Unsigned Double Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=46521930763&lc=en-GE"),
4545
ULINT(BigInteger.class, 64, List.of(S7_1500), "Unsigned Long Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=59653945739&lc=en-GE"),
46-
SINT(Byte.class, 8, List.of(S7_1200, S7_1500), "Short Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=68894861835&lc=en-GE"),
46+
SINT(Short.class, 8, List.of(S7_1200, S7_1500), "Short Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=68894861835&lc=en-GE"),
4747
INT(Short.class, 16, List.of(S7_300, S7_400, S7_1200, S7_1500),"Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=63679745547&lc=en-GE"),
4848
DINT(Integer.class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "Double Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=46521869963&lc=en-GE"),
4949
LINT(Long.class, 64, List.of(S7_1500), "Long Integer", "https://support.industry.siemens.com/cs/mdm/109054417?c=66825552267&lc=en-GE"),
5050
REAL(Float.class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "Real", "https://support.industry.siemens.com/cs/mdm/109054417?c=68826794251&lc=en-GE"),
51-
LREAL(Float.class, 64, List.of(S7_1200, S7_1500), "Long Real", "https://support.industry.siemens.com/cs/mdm/109054417?c=68826903691&lc=en-GE"),
51+
LREAL(Double.class, 64, List.of(S7_1200, S7_1500), "Long Real", "https://support.industry.siemens.com/cs/mdm/109054417?c=68826903691&lc=en-GE"),
5252

53-
CHAR(Character.class, 8, List.of(S7_300, S7_400, S7_1200, S7_1500), "Character", "https://support.industry.siemens.com/cs/mdm/109054417?c=57152595083&lc=en-GE"),
54-
WCHAR(Short.class, 16, List.of(S7_1200, S7_1500), "Wide Character", "https://support.industry.siemens.com/cs/mdm/109054417?c=10488733835&lc=en-GE"),
53+
CHAR(Byte.class, 8, List.of(S7_300, S7_400, S7_1200, S7_1500), "Character", "https://support.industry.siemens.com/cs/mdm/109054417?c=57152595083&lc=en-GE"),
54+
WCHAR(Character.class, 16, List.of(S7_1200, S7_1500), "Wide Character", "https://support.industry.siemens.com/cs/mdm/109054417?c=10488733835&lc=en-GE"),
5555
STRING(String.class, -1, List.of(S7_300, S7_400, S7_1200, S7_1500), "String, 0 to 254 characters only ASCII", "https://support.industry.siemens.com/cs/mdm/109054417?c=63689840011&lc=en-GE"),
5656
WSTRING(String.class, -1, List.of(S7_1200, S7_1500), "Wide String, 0 to 254 characters only Unicode", "https://support.industry.siemens.com/cs/mdm/109054417?c=61472021771&lc=en-GE"), //
5757

5858
TIME(Long.class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "IEC Time (ms)", "https://support.industry.siemens.com/cs/mdm/109054417?c=61085966091&lc=en-GE"),
59-
LTIME(BigInteger.class, 64, List.of(S7_1500), "IEC Time (ns)", "https://support.industry.siemens.com/cs/mdm/109054417?c=61410814475&lc=en-GE"),
59+
LTIME(Long.class, 64, List.of(S7_1500), "IEC Time (ns)", "https://support.industry.siemens.com/cs/mdm/109054417?c=61410814475&lc=en-GE"),
6060
//TODO S5TIME https://support.industry.siemens.com/cs/mdm/109054417?c=63689295627&lc=en-GE
6161

6262
DATE(Short.class, 8, List.of(S7_300, S7_400, S7_1200, S7_1500), "IEC Date, since 01-01-1990 (Year-Month-Day)", "https://support.industry.siemens.com/cs/mdm/109054417?c=46522046859&lc=en-GE"),
6363
TOD(Long.class, 32, List.of(S7_300, S7_400, S7_1200, S7_1500), "Time Of Day (hours:minutes:seconds.milliseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=64869849355&lc=en-GE"),
6464
LTOD(BigInteger.class, 64, List.of(S7_1500), "Time-of-day (hours:minutes:seconds.nanoseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=64869390987&lc=en-GE"),
65-
DT(BigInteger.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:millisecond)", "https://support.industry.siemens.com/cs/mdm/109054417?c=61473284875&lc=en-GE"),
66-
LDT(BigInteger.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:nanoseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=71834521483&lc=en-GE"),
67-
DTL(BigInteger.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:nanoseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=64682916235&lc=en-GE"),
65+
DT(LocalDate.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:millisecond)", "https://support.industry.siemens.com/cs/mdm/109054417?c=61473284875&lc=en-GE"),
66+
LDT(LocalDateTime.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:nanoseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=71834521483&lc=en-GE"),
67+
DTL(LocalDateTime.class, 64, List.of(S7_1500), "Date and time (year-month-day-hour:minute:second:nanoseconds)", "https://support.industry.siemens.com/cs/mdm/109054417?c=64682916235&lc=en-GE"),
6868
ARRAY(Byte[].class, -1, List.of(S7_300, S7_400, S7_1200, S7_1500), "Array of type", "https://support.industry.siemens.com/cs/mdm/109054417?c=52352205963&lc=en-GE");
6969
//RAW_BYTE_ARRAY TODO: it's not an actual type but is there in the old implementation
7070

modules/hivemq-edge-module-s7/src/test/java/com/hivemq/edge/adapters/s7/MainTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public static void s7_300() {
2222
S7Client s7Client = new S7Client(eplcType, "172.16.10.53", 102,
2323
eplcType.getRack(), eplcType.getSlot(), eplcType.getPduLength(), DataPointImpl::new);
2424
s7Client.connect();
25-
final DataPoint dataPoint = s7Client.readBytes("IB1", 1);
26-
System.out.println(((byte[])dataPoint.getTagValue())[0]); // => 122
25+
final List<DataPoint> dataPoint = s7Client.read(S7DataType.BYTE, List.of("IB1"));
26+
System.out.println(dataPoint.get(0).getTagValue()); // => 122
2727
s7Client.disconnect();
2828
}
2929

0 commit comments

Comments
 (0)