Skip to content

Commit ae5a5a2

Browse files
committed
fix: Fixed a small issue in serializing STRING and WSTRING values.
fixes: #2328
1 parent d169722 commit ae5a5a2

3 files changed

Lines changed: 26 additions & 13 deletions

File tree

plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,6 +2055,9 @@ private PlcResponse decodeWriteResponse(S7Message responseMessage, PlcWriteReque
20552055
private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
20562056
try {
20572057
DataTransportSize transportSize = tag.getDataType().getDataTransportSize();
2058+
// In the case of STRING, the default and the max stringLength are both 254. With WSTRING the default
2059+
// is also 254. For WSTRING, the max stringLength is 16382. Here we're only handling the default, the
2060+
// max is handled in the StaticHelper.
20582061
int stringLength = (tag instanceof S7StringFixedLengthTag) ? ((S7StringFixedLengthTag) tag).getStringLength() : 254;
20592062
ByteBuffer byteBuffer = null;
20602063
if((tag.getDataType() == TransportSize.BYTE) && (tag.getNumberOfElements() > 1)) {

plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/StaticHelper.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,12 +2690,13 @@ public static String parseS7String(ReadBuffer io, int stringLength, String encod
26902690
* the String as char arrays from your application.
26912691
*/
26922692
public static void serializeS7String(WriteBuffer io, PlcValue value, int stringLength, String encoding) {
2693-
int maxStringLength = 0xFF & Math.min(stringLength, 250);
2694-
int actStringLength = 0xFF & value.getString().length();
2695-
actStringLength = Math.min(maxStringLength, actStringLength);
2696-
26972693
switch (encoding) {
26982694
case "UTF-8": {
2695+
// In the case of STRING, the default and the max stringLength is 254.
2696+
int maxStringLength = 0xFF & Math.min(stringLength, 254);
2697+
int actStringLength = 0xFF & value.getString().length();
2698+
actStringLength = Math.min(maxStringLength, actStringLength);
2699+
26992700
byte[] chars = new byte[maxStringLength];
27002701
byte[] actChars = value.getString().substring(0, actStringLength).getBytes(StandardCharsets.UTF_8);
27012702
System.arraycopy(actChars, 0, chars, 0, actChars.length);
@@ -2709,6 +2710,12 @@ public static void serializeS7String(WriteBuffer io, PlcValue value, int stringL
27092710
break;
27102711
}
27112712
case "UTF-16": {
2713+
// In the case of WSTRING the default is also 254. However, the max stringLength is 16382.
2714+
// As we've settled the default handling in S7ProtocolLogic, we'll only handle the max here.
2715+
int maxStringLength = 0xFFFF & Math.min(stringLength, 16382);
2716+
int actStringLength = 0xFFFF & value.getString().length();
2717+
actStringLength = Math.min(maxStringLength, actStringLength);
2718+
27122719
byte[] chars = new byte[maxStringLength * 2];
27132720
byte[] actChars = value.getString().substring(0, actStringLength).getBytes(StandardCharsets.UTF_16BE);
27142721
System.arraycopy(actChars, 0, chars, 0, actChars.length);

plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/protocol/S7ProtocolLogic.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ public void setDriverContext(DriverContext driverContext) {
7171
super.setDriverContext(driverContext);
7272
this.s7DriverContext = (S7DriverContext) driverContext;
7373
// Initialize Transaction Manager.
74-
// Until the number of concurrent requests is successfully negotiated we set it to a
75-
// maximum of only one request being able to be sent at a time. During the login process
76-
// No concurrent requests can be sent anyway. It will be updated when receiving the
74+
// Until the number of concurrent requests is successfully negotiated, we set it to a
75+
// maximum of only one request being able to be sent at a time. During the login process,
76+
// no concurrent requests can be sent anyway. It will be updated when receiving the
7777
// S7ParameterSetupCommunication response.
7878
this.tm = new RequestTransactionManager(1);
7979
}
@@ -136,7 +136,7 @@ public void onConnect(ConversationContext<TPKTPacket> context) {
136136

137137
// If the controller type is explicitly set, were finished with the login
138138
// process. If it's set to ANY, we have to query the serial number information
139-
// in order to detect the type of PLC.
139+
// to detect the type of PLC.
140140
if (s7DriverContext.getControllerType() != ControllerType.ANY) {
141141
// Send an event that connection setup is complete.
142142
context.fireConnected();
@@ -225,7 +225,7 @@ public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
225225
CompletableFuture<S7Message> responseFuture = new CompletableFuture<>();
226226

227227
// If the list of tags contains at least one STRING/WSTRING element,
228-
// we need to check the sizes of the string fields in a first request.
228+
// we need to check the sizes of the string fields in the first request.
229229
if (request.getTagNames().stream().anyMatch(t -> request.getTag(t) instanceof S7StringVarLengthTag)) {
230230
responseFuture = performVarLengthStringWriteRequest((DefaultPlcWriteRequest) writeRequest);
231231
}
@@ -776,6 +776,9 @@ private PlcResponse decodeWriteResponse(S7Message responseMessage, PlcWriteReque
776776
private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
777777
try {
778778
DataTransportSize transportSize = tag.getDataType().getDataTransportSize();
779+
// In the case of STRING, the default and the max stringLength are both 254. With WSTRING the default
780+
// is also 254. For WSTRING, the max stringLength is 16382. Here we're only handling the default, the
781+
// max is handled in the StaticHelper.
779782
int stringLength = (tag instanceof S7StringFixedLengthTag) ? ((S7StringFixedLengthTag) tag).getStringLength() : 254;
780783
ByteBuffer byteBuffer = null;
781784
if((tag.getDataType() == TransportSize.BYTE) && (tag.getNumberOfElements() > 1)) {
@@ -956,15 +959,15 @@ protected S7Address encodeS7Address(PlcTag tag) {
956959

957960
private int getTpduId() {
958961
int tpduId = tpduGenerator.getAndIncrement();
959-
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
962+
// If we've reached the max value for a 16-bit transaction identifier, reset back to 1
960963
if (tpduGenerator.get() == 0xFFFF) {
961964
tpduGenerator.set(1);
962965
}
963966
return tpduId;
964967
}
965968

966969
/**
967-
* A generic purpose error handler which terminates transaction and calls back given future with error message.
970+
* A generic purpose error handler which terminates a transaction and calls back the given future with an error message.
968971
*/
969972
static class TransactionErrorCallback<T, E extends Throwable> implements Consumer<TimeoutException>, BiConsumer<TPKTPacket, E> {
970973

@@ -1007,7 +1010,7 @@ protected CompletableFuture<Map<S7StringVarLengthTag, StringSizes>> getStringSiz
10071010
.collect(Collectors.toList());
10081011
List<S7VarRequestParameterItem> stringFields = new ArrayList<>(varLengthStringTags.size());
10091012
for (S7StringVarLengthTag varLengthStringTag : varLengthStringTags) {
1010-
// For STRING, the header is 2 bytes (first byte contains the max length and the second the actual length)
1013+
// For STRING, the header is 2 bytes (The first byte contains the max length, and the second the actual length)
10111014
if (varLengthStringTag.getDataType() == TransportSize.STRING) {
10121015
stringFields.add(new S7VarRequestParameterItemAddress(
10131016
new S7AddressAny(
@@ -1019,7 +1022,7 @@ protected CompletableFuture<Map<S7StringVarLengthTag, StringSizes>> getStringSiz
10191022
varLengthStringTag.getBitOffset()
10201023
)));
10211024
}
1022-
// For WSTRING, the header is 4 bytes (first word contains the max length and the second the actual length)
1025+
// For WSTRING, the header is 4 bytes (The first word contains the max length, and the second the actual length)
10231026
else if (varLengthStringTag.getDataType() == TransportSize.WSTRING) {
10241027
stringFields.add(new S7VarRequestParameterItemAddress(
10251028
new S7AddressAny(

0 commit comments

Comments
 (0)