This is an automated email from the ASF dual-hosted git repository. cdutz pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit ae5a5a259bc6c894043355929ff3f196ba9ab462 Author: Christofer Dutz <[email protected]> AuthorDate: Wed Nov 5 15:57:10 2025 +0100 fix: Fixed a small issue in serializing STRING and WSTRING values. fixes: #2328 --- .../java/s7/readwrite/protocol/S7ProtocolLogic.java | 3 +++ .../plc4x/java/s7/readwrite/utils/StaticHelper.java | 15 +++++++++++---- .../s7light/readwrite/protocol/S7ProtocolLogic.java | 21 ++++++++++++--------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java index bc759e2c4b..d3ae7fbfbe 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java @@ -2055,6 +2055,9 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) { try { DataTransportSize transportSize = tag.getDataType().getDataTransportSize(); + // In the case of STRING, the default and the max stringLength are both 254. With WSTRING the default + // is also 254. For WSTRING, the max stringLength is 16382. Here we're only handling the default, the + // max is handled in the StaticHelper. int stringLength = (tag instanceof S7StringFixedLengthTag) ? ((S7StringFixedLengthTag) tag).getStringLength() : 254; ByteBuffer byteBuffer = null; if((tag.getDataType() == TransportSize.BYTE) && (tag.getNumberOfElements() > 1)) { diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/StaticHelper.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/StaticHelper.java index 709cfc7fcf..453d9c2b75 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/StaticHelper.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/utils/StaticHelper.java @@ -2690,12 +2690,13 @@ public class StaticHelper { * the String as char arrays from your application. */ public static void serializeS7String(WriteBuffer io, PlcValue value, int stringLength, String encoding) { - int maxStringLength = 0xFF & Math.min(stringLength, 250); - int actStringLength = 0xFF & value.getString().length(); - actStringLength = Math.min(maxStringLength, actStringLength); - switch (encoding) { case "UTF-8": { + // In the case of STRING, the default and the max stringLength is 254. + int maxStringLength = 0xFF & Math.min(stringLength, 254); + int actStringLength = 0xFF & value.getString().length(); + actStringLength = Math.min(maxStringLength, actStringLength); + byte[] chars = new byte[maxStringLength]; byte[] actChars = value.getString().substring(0, actStringLength).getBytes(StandardCharsets.UTF_8); System.arraycopy(actChars, 0, chars, 0, actChars.length); @@ -2709,6 +2710,12 @@ public class StaticHelper { break; } case "UTF-16": { + // In the case of WSTRING the default is also 254. However, the max stringLength is 16382. + // As we've settled the default handling in S7ProtocolLogic, we'll only handle the max here. + int maxStringLength = 0xFFFF & Math.min(stringLength, 16382); + int actStringLength = 0xFFFF & value.getString().length(); + actStringLength = Math.min(maxStringLength, actStringLength); + byte[] chars = new byte[maxStringLength * 2]; byte[] actChars = value.getString().substring(0, actStringLength).getBytes(StandardCharsets.UTF_16BE); System.arraycopy(actChars, 0, chars, 0, actChars.length); diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/protocol/S7ProtocolLogic.java index 357e7ea02a..a83d39bdf3 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/protocol/S7ProtocolLogic.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7light/readwrite/protocol/S7ProtocolLogic.java @@ -71,9 +71,9 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { super.setDriverContext(driverContext); this.s7DriverContext = (S7DriverContext) driverContext; // Initialize Transaction Manager. - // Until the number of concurrent requests is successfully negotiated we set it to a - // maximum of only one request being able to be sent at a time. During the login process - // No concurrent requests can be sent anyway. It will be updated when receiving the + // Until the number of concurrent requests is successfully negotiated, we set it to a + // maximum of only one request being able to be sent at a time. During the login process, + // no concurrent requests can be sent anyway. It will be updated when receiving the // S7ParameterSetupCommunication response. this.tm = new RequestTransactionManager(1); } @@ -136,7 +136,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { // If the controller type is explicitly set, were finished with the login // process. If it's set to ANY, we have to query the serial number information - // in order to detect the type of PLC. + // to detect the type of PLC. if (s7DriverContext.getControllerType() != ControllerType.ANY) { // Send an event that connection setup is complete. context.fireConnected(); @@ -225,7 +225,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { CompletableFuture<S7Message> responseFuture = new CompletableFuture<>(); // If the list of tags contains at least one STRING/WSTRING element, - // we need to check the sizes of the string fields in a first request. + // we need to check the sizes of the string fields in the first request. if (request.getTagNames().stream().anyMatch(t -> request.getTag(t) instanceof S7StringVarLengthTag)) { responseFuture = performVarLengthStringWriteRequest((DefaultPlcWriteRequest) writeRequest); } @@ -776,6 +776,9 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) { try { DataTransportSize transportSize = tag.getDataType().getDataTransportSize(); + // In the case of STRING, the default and the max stringLength are both 254. With WSTRING the default + // is also 254. For WSTRING, the max stringLength is 16382. Here we're only handling the default, the + // max is handled in the StaticHelper. int stringLength = (tag instanceof S7StringFixedLengthTag) ? ((S7StringFixedLengthTag) tag).getStringLength() : 254; ByteBuffer byteBuffer = null; if((tag.getDataType() == TransportSize.BYTE) && (tag.getNumberOfElements() > 1)) { @@ -956,7 +959,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { private int getTpduId() { int tpduId = tpduGenerator.getAndIncrement(); - // If we've reached the max value for a 16 bit transaction identifier, reset back to 1 + // If we've reached the max value for a 16-bit transaction identifier, reset back to 1 if (tpduGenerator.get() == 0xFFFF) { tpduGenerator.set(1); } @@ -964,7 +967,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { } /** - * A generic purpose error handler which terminates transaction and calls back given future with error message. + * A generic purpose error handler which terminates a transaction and calls back the given future with an error message. */ static class TransactionErrorCallback<T, E extends Throwable> implements Consumer<TimeoutException>, BiConsumer<TPKTPacket, E> { @@ -1007,7 +1010,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { .collect(Collectors.toList()); List<S7VarRequestParameterItem> stringFields = new ArrayList<>(varLengthStringTags.size()); for (S7StringVarLengthTag varLengthStringTag : varLengthStringTags) { - // For STRING, the header is 2 bytes (first byte contains the max length and the second the actual length) + // For STRING, the header is 2 bytes (The first byte contains the max length, and the second the actual length) if (varLengthStringTag.getDataType() == TransportSize.STRING) { stringFields.add(new S7VarRequestParameterItemAddress( new S7AddressAny( @@ -1019,7 +1022,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { varLengthStringTag.getBitOffset() ))); } - // For WSTRING, the header is 4 bytes (first word contains the max length and the second the actual length) + // For WSTRING, the header is 4 bytes (The first word contains the max length, and the second the actual length) else if (varLengthStringTag.getDataType() == TransportSize.WSTRING) { stringFields.add(new S7VarRequestParameterItemAddress( new S7AddressAny(
