This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/s7strings
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/s7strings by this push:
new c93b723a57 fix: Updated the var-length string handling code and made
it work with WSTRING too.
c93b723a57 is described below
commit c93b723a575c2c00a703a4af298144887e021417
Author: Christofer Dutz <[email protected]>
AuthorDate: Thu Nov 30 16:02:46 2023 +0100
fix: Updated the var-length string handling code and made it work with
WSTRING too.
---
.../java/s7/readwrite/optimizer/S7Optimizer.java | 8 +-
.../s7/readwrite/protocol/S7ProtocolLogic.java | 731 +++++++++------------
.../java/s7/readwrite/tag/S7PlcTagHandler.java | 6 +-
.../s7/readwrite/tag/S7StringFixedLengthTag.java | 129 ++++
.../plc4x/java/s7/readwrite/tag/S7StringTag.java | 199 ------
.../s7/readwrite/tag/S7StringVarLengthTag.java | 119 ++++
.../apache/plc4x/java/s7/readwrite/tag/S7Tag.java | 50 +-
.../java/s7/readwrite/ManualS7DriverTest.java | 6 +
.../plc4x/java/s7/readwrite/tag/S7TagTest.java | 2 +-
9 files changed, 571 insertions(+), 679 deletions(-)
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
index 0487f65f94..57ebcd9a4e 100644
---
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
+++
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/optimizer/S7Optimizer.java
@@ -38,8 +38,8 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import org.apache.plc4x.java.s7.readwrite.tag.S7StringTag;
+
+import org.apache.plc4x.java.s7.readwrite.tag.S7StringVarLengthTag;
public class S7Optimizer extends BaseOptimizer {
@@ -77,7 +77,7 @@ public class S7Optimizer extends BaseOptimizer {
continue;
}
- if ((readRequest.getTag(tagName) instanceof S7StringTag)) {
+ if ((readRequest.getTag(tagName) instanceof S7StringVarLengthTag))
{
LinkedHashMap<String, PlcTag> strTags = new LinkedHashMap<>();
strTags.put(tagName, readRequest.getTag(tagName));
processedRequests.add(new DefaultPlcReadRequest(
@@ -155,7 +155,7 @@ public class S7Optimizer extends BaseOptimizer {
for (String tagName : writeRequest.getTagNames()) {
- if ((writeRequest.getTag(tagName) instanceof S7StringTag)) {
+ if ((writeRequest.getTag(tagName) instanceof
S7StringVarLengthTag)) {
LinkedHashMap<String, TagValueItem> strTags = new
LinkedHashMap<>();
strTags.put(tagName,
new TagValueItem(writeRequest.getTag(tagName),
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 4bfed9bb73..b450981b40 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
@@ -23,6 +23,7 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.tuple.MutablePair;
+import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
@@ -54,7 +55,6 @@ import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
@@ -62,7 +62,6 @@ import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
-import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -247,93 +246,67 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
*/
@Override
public void onDisconnect(ConversationContext<TPKTPacket> context) {
- //1. Clear all pending requests and their associated transaction
+ // 1. Clear all pending requests and their associated transaction
cleanFutures();
- //2. Here we shutdown the local task executor.
+ // 2. Here we shut down the local task executor.
clientExecutorService.shutdown();
- //3. Performs the shutdown of the transaction executor.
+ // 3. Performs the shutdown of the transaction executor.
tm.shutdown();
- //4. Finish the execution of the tasks for the handling of Events.
+ // 4. Finish the execution of the tasks for the handling of Events.
EventLogic.stop();
- //5. Executes the closing of the main channel.
+ // 5. Executes the closing of the main channel.
context.getChannel().close();
- //6. Here is the stop of any task or state machine that is added.
+ // 6. Here is the stop of any task or state machine that is added.
}
@Override
public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest)
{
+ // If we're not connected, just abort with an error.
if (!isConnected()) {
- CompletableFuture<PlcReadResponse> future = new
CompletableFuture<PlcReadResponse>();
+ CompletableFuture<PlcReadResponse> future = new
CompletableFuture<>();
future.completeExceptionally(new
PlcRuntimeException("Disconnected"));
return future;
}
- DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
- List<S7VarRequestParameterItem> requestItems = new
ArrayList<>(request.getNumberOfTags());
-
- if (request.getTags().get(0) instanceof S7SzlTag) {
- S7SzlTag szltag = (S7SzlTag) request.getTags().get(0);
- final S7MessageUserData s7SzlMessageRequest = new
S7MessageUserData(1, new S7ParameterUserData(List.of(
+ DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
+ S7Message s7Message;
+ if (request.getTagNames().stream().anyMatch(t -> request.getTag(t)
instanceof S7SzlTag)) {
+ S7SzlTag szlTag = (S7SzlTag) request.getTags().get(0);
+ // TODO: Is the tpduReference of 1 correct here?
+ s7Message = new S7MessageUserData(1, new
S7ParameterUserData(List.of(
new S7ParameterUserDataItemCPUFunctions((short) 0x11,
(byte) 0x4, (byte) 0x4, (short) 0x01, (short) 0x00, null, null, null)
)), new S7PayloadUserData(List.of(
new
S7PayloadUserDataItemCpuFunctionReadSzlRequest(DataTransportErrorCode.OK,
DataTransportSize.OCTET_STRING,
0x04,
- new SzlId(SzlModuleTypeClass.enumForValue((byte)
((szltag.getSzlId() & 0xf000) >> 12)),
- (byte) ((szltag.getSzlId() & 0x0f00) >> 8),
- SzlSublist.enumForValue((short)
(szltag.getSzlId() & 0x00ff))),
- szltag.getIndex())
+ new SzlId(SzlModuleTypeClass.enumForValue((byte)
((szlTag.getSzlId() & 0xf000) >> 12)),
+ (byte) ((szlTag.getSzlId() & 0x0f00) >> 8),
+ SzlSublist.enumForValue((short)
(szlTag.getSzlId() & 0x00ff))),
+ szlTag.getIndex())
)));
+ }
- return toPlcReadResponse(readRequest,
readInternal(s7SzlMessageRequest));
-
- } else if (request.getTags().get(0) instanceof S7AckTag) {
-
- List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
- encodeAlarmAckRequest(request, parameterItems, payloadItems);
- final S7MessageUserData s7MessageRequest = new
S7MessageUserData(-1,
- new S7ParameterUserData(parameterItems),
- new S7PayloadUserData(payloadItems));
- return toPlcReadResponse(readRequest,
readInternal(s7MessageRequest));
-
- } else if (request.getTags().get(0) instanceof S7ClkTag) {
-
- List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
- encodePlcClkRequest(request, parameterItems, payloadItems);
- final S7MessageUserData s7MessageRequest = new
S7MessageUserData(-1,
- new S7ParameterUserData(parameterItems),
- new S7PayloadUserData(payloadItems));
- return toPlcReadResponse(readRequest,
readInternal(s7MessageRequest));
-
- } else if (request.getTags().get(0) instanceof S7StringTag) {
-
- List<S7ParameterReadVarRequest> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
- encodePlcStringReadRequest(request, parameterItems, payloadItems);
-
- final S7MessageRequest s7MessageRequest = new S7MessageRequest(-1,
- parameterItems.get(0),
- null);
-
- return toPlcReadResponse(readRequest,
readInternal(s7MessageRequest));
+ else if (request.getTagNames().stream().anyMatch(t ->
request.getTag(t) instanceof S7AckTag)) {
+ s7Message = encodeAlarmAckRequest(request);
}
+ else if (request.getTagNames().stream().anyMatch(t ->
request.getTag(t) instanceof S7ClkTag)) {
+ s7Message = encodePlcClkRequest(request);
+ }
- for (PlcTag tag : request.getTags()) {
- requestItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
+ // If the request contains at least one var-length string field, we
need to get the real length first.
+ else if (request.getTagNames().stream().anyMatch(t ->
request.getTag(t) instanceof S7StringVarLengthTag)) {
+ s7Message = encodePlcVarLengthStringReadRequest(request);
}
- // Create a read request template.
- // tpuId will be inserted before sending in #readInternal so we insert
-1 as dummy here
- final S7MessageRequest s7MessageRequest = new S7MessageRequest(-1,
- new S7ParameterReadVarRequest(requestItems),
- null);
+ // This is a "normal" read request.
+ else {
+ s7Message = encodePlcReadRequest(request);
+ }
// Just send a single response and chain it as Response
- return toPlcReadResponse(readRequest, readInternal(s7MessageRequest));
+ return toPlcReadResponse(readRequest, readInternal(s7Message));
}
/**
@@ -357,16 +330,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
}
return clientFuture;
-
-
-// return response
-// .thenApply(p -> {
-// try {
-// return ((PlcReadResponse) decodeReadResponse(p,
readRequest));
-// } catch (PlcProtocolException e) {
-// throw new PlcRuntimeException("Unable to decode
Response", e);
-// }
-// });
}
/**
@@ -378,17 +341,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
*/
private CompletableFuture<S7Message> readInternal(S7Message request) {
CompletableFuture<S7Message> future = new CompletableFuture<>();
- int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
- }
- S7Message message = (request instanceof S7MessageUserData) ?
- new S7MessageUserData(tpduId, request.getParameter(),
request.getPayload()) :
- new S7MessageRequest(tpduId, request.getParameter(),
request.getPayload());
+ int tpduId = request.getTpduReference();
- TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null,
message, true, (byte) tpduId));
+ TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null,
request, true, (byte) tpduId));
// Start a new request-transaction (Is ended in the response-handler)
@@ -414,165 +370,30 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
return future;
}
- //TODO: Clean code
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest
writeRequest) {
-
- CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
- DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
-
- List<String> clkTags = request.getTagNames().stream()
- .filter(t -> request.getTag(t) instanceof S7ClkTag)
- .collect(Collectors.toList());
- if (!clkTags.isEmpty()) {
- return writeClk(writeRequest);
- }
-
- List<String> strTags = request.getTagNames().stream()
- .filter(t -> request.getTag(t) instanceof S7StringTag)
- .collect(Collectors.toList());
- if (!strTags.isEmpty()) {
- return writeString(writeRequest);
- }
-
- List<S7VarRequestParameterItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7VarPayloadDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
-
- Iterator<String> iter = request.getTagNames().iterator();
-
- String tagName;
- while (iter.hasNext()) {
- tagName = iter.next();
- final S7Tag tag = (S7Tag) request.getTag(tagName);
- final PlcValue plcValue = request.getPlcValue(tagName);
- parameterItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
- payloadItems.add(serializePlcValue(tag, plcValue, iter.hasNext()));
- }
-
-
-// for (String tagName : request.getTagNames()) {
-// final S7Tag tag = (S7Tag) request.getTag(tagName);
-// final PlcValue plcValue = request.getPlcValue(tagName);
-// parameterItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
-// payloadItems.add(serializePlcValue(tag, plcValue));
-//
-// }
-
-
- final int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
- }
-
- TPKTPacket tpktPacket = new TPKTPacket(
- new COTPPacketData(
- null,
- new S7MessageRequest(tpduId,
- new S7ParameterWriteVarRequest(parameterItems),
- new S7PayloadWriteVarRequest(payloadItems)
- ),
- true,
- (byte) tpduId
- )
- );
-
- // Start a new request-transaction (Is ended in the response-handler)
- RequestTransactionManager.RequestTransaction transaction =
tm.startRequest();
- transaction.submit(() -> context.sendRequest(tpktPacket)
- .onTimeout(new TransactionErrorCallback<>(future, transaction))
- .onError(new TransactionErrorCallback<>(future, transaction))
- .expectResponse(TPKTPacket.class, REQUEST_TIMEOUT)
- .check(p -> p.getPayload() instanceof COTPPacketData)
- .unwrap(p -> ((COTPPacketData) p.getPayload()))
- .unwrap(COTPPacket::getPayload)
- .check(p -> p.getTpduReference() == tpduId)
- .handle(p -> {
- try {
- future.complete(((PlcWriteResponse) decodeWriteResponse(p,
writeRequest)));
- } catch (PlcProtocolException e) {
- logger.warn("Error sending 'write' message: '{}'",
e.getMessage(), e);
- }
- // Finish the request-transaction.
- transaction.endRequest();
- }));
- return future;
- }
-
- //TODO: Clean code
- public CompletableFuture<PlcWriteResponse> writeClk(PlcWriteRequest
writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
- List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
-
- encodePlcClkSetRequest((DefaultPlcWriteRequest) writeRequest,
- parameterItems, payloadItems);
+ int tpduId = getTpduId();
- final int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
+ TPKTPacket tpktPacket;
+ // TODO: Write one or two lines on what happens here ... to me it
looks as if there's at least on S7ClkTag, then all is handled by the writeClk
method, but what happens if a request would contain mixed tag types?
+ if (request.getTagNames().stream().anyMatch(t -> request.getTag(t)
instanceof S7ClkTag)) {
+ tpktPacket = encodePlcClkSetRequest((DefaultPlcWriteRequest)
writeRequest, tpduId);
}
- TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null,
- new S7MessageUserData(tpduId,
- new S7ParameterUserData(parameterItems),
- new S7PayloadUserData(payloadItems)),
- true, (byte) tpduId));
-
- // Start a new request-transaction (Is ended in the response-handler)
- RequestTransactionManager.RequestTransaction transaction =
tm.startRequest();
- transaction.submit(() -> context.sendRequest(tpktPacket)
- .onTimeout(new TransactionErrorCallback<>(future, transaction))
- .onError(new TransactionErrorCallback<>(future, transaction))
- .expectResponse(TPKTPacket.class, REQUEST_TIMEOUT)
- .check(p -> p.getPayload() instanceof COTPPacketData)
- .unwrap(p -> ((COTPPacketData) p.getPayload()))
- .unwrap(COTPPacket::getPayload)
- .check(p -> p.getTpduReference() == tpduId)
- .handle(p -> {
- try {
- future.complete(((PlcWriteResponse) decodeWriteResponse(p,
writeRequest)));
- } catch (PlcProtocolException e) {
- logger.warn("Error sending 'write' message: '{}'",
e.getMessage(), e);
- }
- // Finish the request-transaction.
- transaction.endRequest();
- }));
- return future;
- }
-
- //TODO: Clean code
- public CompletableFuture<PlcWriteResponse> writeString(PlcWriteRequest
writeRequest) {
- CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
- DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
-
- List<S7VarRequestParameterItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7VarPayloadDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
-
- encodePlcStringWriteRequest((DefaultPlcWriteRequest) writeRequest,
- parameterItems, payloadItems);
+ // 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.
+ else if (request.getTagNames().stream().anyMatch(t ->
request.getTag(t) instanceof S7StringVarLengthTag)) {
+ tpktPacket = encodePlcStringWriteRequest((DefaultPlcWriteRequest)
writeRequest, tpduId);
+ }
- final int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
+ // This is a request only containing ordinary tags
+ else {
+ tpktPacket = encodeOrdinaryWriteRequest(request, tpduId);
}
- TPKTPacket tpktPacket = new TPKTPacket(
- new COTPPacketData(
- null,
- new S7MessageRequest(tpduId,
- new S7ParameterWriteVarRequest(parameterItems),
- new S7PayloadWriteVarRequest(payloadItems)
- ),
- true,
- (byte) tpduId
- )
- );
-
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction =
tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket)
@@ -616,25 +437,21 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
CompletableFuture<PlcSubscriptionResponse> response = new
CompletableFuture<>();
subscriptionRequest.getTagNames().forEach(fieldName ->
futures.put(fieldName, new CompletableFuture<>()));
- //
futures.put("DATA_", new CompletableFuture<>());
DefaultPlcSubscriptionRequest request =
(DefaultPlcSubscriptionRequest) subscriptionRequest;
- List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
- List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+ int tpduId = getTpduId();
//The main task that runs the subscriptions.
Thread t1 = new Thread(() -> {
-
- //for (String tagName : request.getTagNames()) {
- //final DefaultPlcSubscriptionTag sf = (DefaultPlcSubscriptionTag)
request.getTag(tagName);
final DefaultPlcSubscriptionTag sf = (DefaultPlcSubscriptionTag)
request.getTags().get(0);
final S7SubscriptionTag tag = (S7SubscriptionTag) sf.getTag();
+ S7Message s7Message = null;
switch (tag.getTagType()) {
case EVENT_SUBSCRIPTION:
- encodeEventSubscriptionRequest(request, parameterItems,
payloadItems);
+ s7Message = encodeEventSubscriptionRequest(request,
tpduId);
break;
case EVENT_UNSUBSCRIPTION:
//encodeEventUnSubscriptionRequest(request,
parameterItems, payloadItems);
@@ -643,35 +460,24 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
//encodeAlarmAckRequest(request, parameterItems,
payloadItems);
break;
case ALARM_QUERY:
- encodeAlarmQueryRequest(request, parameterItems,
payloadItems);
+ s7Message = encodeAlarmQueryRequest(request, tpduId);
break;
case CYCLIC_SUBSCRIPTION:
- encodeCycledS7ANYSubscriptionRequest(request,
parameterItems, payloadItems);
+ s7Message = encodeCycledS7ANYSubscriptionRequest(request,
tpduId);
break;
case CYCLIC_DB_SUBSCRIPTION:
- encodeCycledDBREADSubscriptionRequest(request,
parameterItems, payloadItems);
+ s7Message = encodeCycledDBREADSubscriptionRequest(request,
tpduId);
break;
case CYCLIC_UNSUBSCRIPTION:
//encodeCycledUnSubscriptionRequest(request,
parameterItems, payloadItems);
break;
default:
}
- //} //Next
-
- //final PlcValue plcValue = request.getPlcValue(tagName);
- //parameterItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
- //payloadItems.add(serializePlcValue(tag, plcValue));
- final int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction
identifier, reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
+ if(s7Message == null) {
+ throw new PlcInvalidTagException("Unsupported tag of type: " +
tag.getTagType());
}
- TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null,
- new S7MessageUserData(tpduId,
- new S7ParameterUserData(parameterItems),
- new S7PayloadUserData(payloadItems)),
- true, (byte) tpduId));
+ TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null,
s7Message,true, (byte) tpduId));
// Start a new request-transaction (Is ended in the
response-handler)
RequestTransactionManager.RequestTransaction transaction =
tm.startRequest();
@@ -697,10 +503,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
try {
S7Message responseMessage = futures.get("DATA_").get();
S7ParameterUserData parameter = (S7ParameterUserData)
responseMessage.getParameter();
- S7ParameterUserDataItemCPUFunctions msgparameter =
(S7ParameterUserDataItemCPUFunctions) parameter.getItems().get(0);
+ S7ParameterUserDataItemCPUFunctions msgParameter =
(S7ParameterUserDataItemCPUFunctions) parameter.getItems().get(0);
-
valuesResponse.put(Integer.toString(msgparameter.getSequenceNumber()),
-
decodeEventSubscriptionRequest(Integer.toString(msgparameter.getSequenceNumber()),
subscriptionRequest, futures.get("DATA_").get()));
+
valuesResponse.put(Integer.toString(msgParameter.getSequenceNumber()),
+
decodeEventSubscriptionResponse(Integer.toString(msgParameter.getSequenceNumber()),
subscriptionRequest, futures.get("DATA_").get()));
} catch (Exception ex) {
logger.warn(ex.toString());
@@ -708,7 +514,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
try {
- ///maintask.get();
HashMap<String, ResponseItem<PlcSubscriptionHandle>> values =
new HashMap<>();
valuesResponse.forEach((s, p) -> {
@@ -750,11 +555,7 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
encodeCycledUnSubscriptionRequest(request, parameterItems,
payloadItems);
- final int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
- }
+ int tpduId = getTpduId();
TPKTPacket tpktPacket = new TPKTPacket(
new COTPPacketData(null,
@@ -788,9 +589,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
return future;
}
- private void encodeEventSubscriptionRequest(DefaultPlcSubscriptionRequest
request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem>
payloadItems) {
+ private S7Message
encodeEventSubscriptionRequest(DefaultPlcSubscriptionRequest request, int
tpduId) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+
byte subsEvent = 0x00;
for (String tagName : request.getTagNames()) {
if (request.getTag(tagName) instanceof DefaultPlcSubscriptionTag) {
@@ -812,12 +614,9 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
- parameterItems.clear();
parameterItems.add(parameter);
-
S7PayloadUserDataItemCpuFunctionMsgSubscriptionRequest payload;
-
if (subsEvent > 0) {
payload = new
S7PayloadUserDataItemCpuFunctionMsgSubscriptionRequest(
DataTransportErrorCode.OK,
@@ -847,13 +646,14 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
alarmType,
(short) 0x00);
}
-
- payloadItems.clear();
payloadItems.add(payload);
+ return new S7MessageUserData(tpduId,
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
- private PlcSubscriptionResponse decodeEventSubscriptionRequest(String
strTagName,
+ private PlcSubscriptionResponse decodeEventSubscriptionResponse(String
strTagName,
PlcSubscriptionRequest plcSubscriptionRequest,
S7Message
responseMessage)
throws PlcProtocolException {
@@ -1118,9 +918,9 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
return null;
}
- private void encodeAlarmAckRequest(DefaultPlcReadRequest request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem>
payloadItems) {
+ private S7Message encodeAlarmAckRequest(DefaultPlcReadRequest request) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
S7ParameterUserDataItemCPUFunctions parameter = new
S7ParameterUserDataItemCPUFunctions(
(short) 0x11, //Method
@@ -1132,7 +932,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
- parameterItems.clear();
parameterItems.add(parameter);
ArrayList<AlarmMessageObjectAckType> messageObjects = null;
@@ -1160,22 +959,22 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
}
}
-
S7PayloadUserDataItemCpuFunctionAlarmAckRequest payload =
new S7PayloadUserDataItemCpuFunctionAlarmAckRequest(
DataTransportErrorCode.OK,
DataTransportSize.OCTET_STRING,
0x0c,
messageObjects);
-//
- payloadItems.clear();
payloadItems.add(payload);
+ return new S7MessageUserData(getTpduId(),
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
- private void encodeAlarmQueryRequest(DefaultPlcSubscriptionRequest request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem>
payloadItems) {
+ private S7Message encodeAlarmQueryRequest(DefaultPlcSubscriptionRequest
request, int tpduId) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
S7ParameterUserDataItemCPUFunctions parameter = new
S7ParameterUserDataItemCPUFunctions(
(short) 0x11, //Method
@@ -1187,8 +986,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
-
- parameterItems.clear();
parameterItems.add(parameter);
//TODO: Chequear el tipo dfe larma.
@@ -1200,20 +997,21 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
SyntaxIdType.ALARM_QUERYREQSET,
QueryType.ALARM_8P,
AlarmType.ALARM_8);
-
- payloadItems.clear();
payloadItems.add(payload);
+
+ return new S7MessageUserData(tpduId,
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
- private void encodeCycledSubscriptionRequest(DefaultPlcSubscriptionRequest
request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem>
payloadItem) {
+ private void encodeCycledSubscriptionRequest(DefaultPlcSubscriptionRequest
request, int tpduId) {
}
- private void
encodeCycledS7ANYSubscriptionRequest(DefaultPlcSubscriptionRequest request,
-
List<S7ParameterUserDataItem> parameterItems,
-
List<S7PayloadUserDataItem> payloadItems) {
+ private S7Message
encodeCycledS7ANYSubscriptionRequest(DefaultPlcSubscriptionRequest request, int
tpduId) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+
S7ParameterUserDataItemCPUFunctions parameter = new
S7ParameterUserDataItemCPUFunctions(
(short) 0x11, //Method
(byte) 0x04, //FunctionType
@@ -1224,8 +1022,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
-
- parameterItems.clear();
parameterItems.add(parameter);
//TODO: Chequear la asignacionde tipo
@@ -1284,15 +1080,18 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
s7tag_base.getMultiplier(),
items
);
-
- payloadItems.clear();
payloadItems.add(payload);
+
+ return new S7MessageUserData(tpduId,
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
- private void
encodeCycledDBREADSubscriptionRequest(DefaultPlcSubscriptionRequest request,
-
List<S7ParameterUserDataItem> parameterItems,
-
List<S7PayloadUserDataItem> payloadItems) {
+ private S7Message
encodeCycledDBREADSubscriptionRequest(DefaultPlcSubscriptionRequest request,
int tpduId) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+
S7ParameterUserDataItemCPUFunctions parameter = new
S7ParameterUserDataItemCPUFunctions(
(short) 0x11, //Method
(byte) 0x04, //FunctionType
@@ -1303,8 +1102,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
-
- parameterItems.clear();
parameterItems.add(parameter);
//TODO: Chequear la asignacionde tipo
@@ -1317,10 +1114,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
//CycServiceItemDbReadType[] cycitems = new
CycServiceItemDbReadType[(int) cycitemcount];
List<CycServiceItemType> cycItems = new ArrayList<>();
ArrayList<SubItem> subItems = new ArrayList<>();
- for (S7Tag userfield : s7tag.getS7Tags()) {
- subItems.add(new SubItem((short) userfield.getNumberOfElements(),
- userfield.getBlockNumber(),
- userfield.getByteOffset()));
+ for (S7Tag userTag : s7tag.getS7Tags()) {
+ subItems.add(new SubItem((short) userTag.getNumberOfElements(),
+ userTag.getBlockNumber(),
+ userTag.getByteOffset()));
}
int initPos = 0;
@@ -1353,9 +1150,11 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
s7tag.getMultiplier(),
cycItems
);
-
- payloadItems.clear();
payloadItems.add(payload);
+
+ return new S7MessageUserData(tpduId,
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
@@ -1413,9 +1212,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
/*
*
*/
- private void encodePlcClkRequest(DefaultPlcReadRequest request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem> payloadItems)
{
+ private S7Message encodePlcClkRequest(DefaultPlcReadRequest request) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+
final S7ClkTag tag = (S7ClkTag) request.getTags().get(0);
int subFunction = tag.getAddressString().equals("CLK") ? 1 : 3;
@@ -1429,8 +1229,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
-
- parameterItems.clear();
parameterItems.add(parameter);
S7PayloadUserDataItemClkRequest payload;
@@ -1438,17 +1236,19 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
DataTransportErrorCode.NOT_FOUND,
DataTransportSize.NULL,
0x00);
-
- payloadItems.clear();
payloadItems.add(payload);
+
+ return new S7MessageUserData(getTpduId(),
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems));
}
/*
*
*/
- private void encodePlcClkSetRequest(DefaultPlcWriteRequest request,
- List<S7ParameterUserDataItem>
parameterItems,
- List<S7PayloadUserDataItem>
payloadItems) {
+ private TPKTPacket encodePlcClkSetRequest(DefaultPlcWriteRequest request,
int tpduId) {
+ List<S7ParameterUserDataItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7PayloadUserDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
S7ParameterUserDataItemCPUFunctions parameter = new
S7ParameterUserDataItemCPUFunctions(
(short) 0x11, //Method
@@ -1460,8 +1260,6 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
null, //LastDataUnit
null //errorCode
);
-
- parameterItems.clear();
parameterItems.add(parameter);
S7ClkTag tag = (S7ClkTag) request.getTags().get(0);
@@ -1472,9 +1270,13 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
DataTransportSize.OCTET_STRING,
0x0A,
tag.getDateAndTime());
-
- payloadItems.clear();
payloadItems.add(payload);
+
+ return new TPKTPacket(new COTPPacketData(null,
+ new S7MessageUserData(tpduId,
+ new S7ParameterUserData(parameterItems),
+ new S7PayloadUserData(payloadItems)),
+ true, (byte) tpduId));
}
@@ -1506,65 +1308,115 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
* by "intActualChars" are recovered.
* TODO: Maximum waiting time managed by system variables.
*/
- private void encodePlcStringReadRequest(DefaultPlcReadRequest request,
- List<S7ParameterReadVarRequest>
parameterItems,
- List<S7PayloadUserDataItem> payloadItems)
{
-
- int intMaxChars = 0;
- int intActualChars = 0;
-
- final S7StringTag tag = (S7StringTag) request.getTags().get(0);
-
- //Read the max length and actual size.
-
- final S7MessageRequest readRequest = new S7MessageRequest(1,new
S7ParameterReadVarRequest(
- List.of(new S7VarRequestParameterItemAddress(
- new S7AddressAny(
- TransportSize.BYTE,
- 2,
- tag.getBlockNumber(),
- MemoryArea.DATA_BLOCKS,
- tag.getByteOffset(),
- tag.getBitOffset()
- ))
-
- )), null);
-
+ private S7Message
encodePlcVarLengthStringReadRequest(DefaultPlcReadRequest request) {
+ List<S7ParameterReadVarRequest> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+
+ // Build a request to read the length information for every var-length
string in the request.
+ List<S7StringVarLengthTag> varLengthStringTags =
request.getTags().stream()
+ .filter(plcTag -> plcTag instanceof S7StringVarLengthTag)
+ .map(plcTag -> (S7StringVarLengthTag) plcTag)
+ .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)
+ if(varLengthStringTag.getDataType() == TransportSize.STRING) {
+ stringFields.add(new S7VarRequestParameterItemAddress(
+ new S7AddressAny(
+ TransportSize.BYTE,
+ 2,
+ varLengthStringTag.getBlockNumber(),
+ MemoryArea.DATA_BLOCKS,
+ varLengthStringTag.getByteOffset(),
+ varLengthStringTag.getBitOffset()
+ )));
+ }
+ // For WSTRING, the header is 4 bytes (first word contains the max
length and the second the actual length)
+ else if(varLengthStringTag.getDataType() == TransportSize.WSTRING)
{
+ stringFields.add(new S7VarRequestParameterItemAddress(
+ new S7AddressAny(
+ TransportSize.BYTE,
+ 4,
+ varLengthStringTag.getBlockNumber(),
+ MemoryArea.DATA_BLOCKS,
+ varLengthStringTag.getByteOffset(),
+ varLengthStringTag.getBitOffset()
+ )));
+ } else {
+ throw new PlcInvalidTagException("Only STRING and WSTRING
allowed here.");
+ }
+ }
+ final S7MessageRequest readRequest = new S7MessageRequest(
+ getTpduId(), new S7ParameterReadVarRequest(stringFields), null);
+
+ // Read the max length and actual size for each of the var-length
strings.
CompletableFuture<S7Message> future = readInternal(readRequest);
-
+
+ Map<S7StringVarLengthTag, Integer> stringLengths = new
HashMap<>(varLengthStringTags.size());
try {
- S7Message get = future.get(2000, TimeUnit.MILLISECONDS);
- final S7VarPayloadDataItem payload =
(S7VarPayloadDataItem)((S7PayloadReadVarResponse)
get.getPayload()).getItems().get(0);
- //intMaxChars = Byte.toUnsignedInt(payload.getData()[0]);
- intActualChars = Byte.toUnsignedInt(payload.getData()[1]);
+ // TODO: Check if we're not blocking the execute method here ...
+ S7Message getLengthsResponseMessage = future.get(2000,
TimeUnit.MILLISECONDS);
+ S7PayloadReadVarResponse getLengthsResponse =
(S7PayloadReadVarResponse) getLengthsResponseMessage.getPayload();
+ int curItemIndex = 0;
+ for (S7StringVarLengthTag varLengthStringTag :
varLengthStringTags) {
+ S7VarPayloadDataItem s7VarPayloadDataItem =
getLengthsResponse.getItems().get(curItemIndex);
+ ReadBufferByteBased readBuffer = new
ReadBufferByteBased(s7VarPayloadDataItem.getData());
+ try {
+ if (varLengthStringTag.getDataType() ==
TransportSize.STRING) {
+ /*int maxChars =
*/readBuffer.readUnsignedInt("maxLength", 8);
+ int actualChars =
readBuffer.readUnsignedInt("maxLength", 8);
+ stringLengths.put(varLengthStringTag, actualChars);
+ } else if (varLengthStringTag.getDataType() ==
TransportSize.WSTRING) {
+ /*int maxChars =
*/readBuffer.readUnsignedInt("maxLength", 16);
+ int actualChars =
readBuffer.readUnsignedInt("maxLength", 16);
+ stringLengths.put(varLengthStringTag, actualChars);
+ } else {
+ throw new PlcInvalidTagException("Only STRING and
WSTRING allowed here.");
+ }
+ } catch (ParseException e) {
+ throw new PlcInvalidTagException("Error reading var-length
string actual lengths.");
+ }
+ }
} catch (InterruptedException ex) {
logger.info(ex.getMessage());
- } catch (ExecutionException ex) {
- logger.info(ex.getMessage());
- } catch (TimeoutException ex) {
+ Thread.currentThread().interrupt();
+ } catch (ExecutionException | TimeoutException ex) {
logger.info(ex.getMessage());
}
-
- //Create the message structure for the user request.
-
- S7ParameterReadVarRequest parameter = new S7ParameterReadVarRequest(
- List.of(new S7VarRequestParameterItemAddress(
- new S7AddressAny(
- TransportSize.BYTE,
- intActualChars,
- tag.getBlockNumber(),
- MemoryArea.DATA_BLOCKS,
- tag.getByteOffset()+2,
- tag.getBitOffset()
- ))
-
- ));
- parameterItems.clear();
- parameterItems.add(parameter);
+ // Create an alternative list of request items, where all var-length
string tags are replaced with
+ // fixed-length string tags using the string length returned by the
previous request.
+ LinkedHashMap<String, PlcTag> updatedRequestItems = new
LinkedHashMap<>(request.getNumberOfTags());
+ for (String tagName : request.getTagNames()) {
+ PlcTag tag = request.getTag(tagName);
+ if(tag instanceof S7StringVarLengthTag) {
+ S7StringVarLengthTag varLengthTag = (S7StringVarLengthTag) tag;
+ int stringLength = stringLengths.get(varLengthTag);
+ S7StringFixedLengthTag newTag = new
S7StringFixedLengthTag(varLengthTag.getDataType(), varLengthTag.getMemoryArea(),
+ varLengthTag.getBlockNumber(),
varLengthTag.getByteOffset(), varLengthTag.getBitOffset(),
+ varLengthTag.getNumberOfElements(), stringLength);
+ updatedRequestItems.put(tagName, newTag);
+ } else {
+ updatedRequestItems.put(tagName, tag);
+ }
+ }
- payloadItems.clear();
+ // Use the normal functionality to execute the read request.
+ // TODO: Here technically the request object in the response will not
match the original request.
+ return encodePlcReadRequest(new
DefaultPlcReadRequest(request.getReader(), updatedRequestItems));
+ }
+
+ private S7Message encodePlcReadRequest(DefaultPlcReadRequest request) {
+ // Convert each tag in the request into a corresponding item used in
the S7 protocol.
+ List<S7VarRequestParameterItem> requestItems = new
ArrayList<>(request.getNumberOfTags());
+ for (PlcTag tag : request.getTags()) {
+ requestItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
+ }
+ // Create a read request template.
+ // tpuId will be inserted before sending in #readInternal, so we
insert -1 as dummy here
+ return new S7MessageRequest(getTpduId(),
+ new S7ParameterReadVarRequest(requestItems),
+ null);
}
@@ -1596,17 +1448,18 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
* by "intMaxChars" are writed.
* TODO: Maximum waiting time managed by system variables.
*/
- private void encodePlcStringWriteRequest(DefaultPlcWriteRequest request,
- List<S7VarRequestParameterItem>
parameterItems,
- List<S7VarPayloadDataItem>
payloadItems) {
+ private TPKTPacket encodePlcStringWriteRequest(DefaultPlcWriteRequest
request,
+ int tpduId) {
+ List<S7VarRequestParameterItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7VarPayloadDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
int intMaxChars = 0;
int intActualChars = 0;
-
- final S7StringTag tag = (S7StringTag) request.getTags().get(0);
+
+ final S7StringVarLengthTag tag = (S7StringVarLengthTag)
request.getTags().get(0);
//Read the max length and actual size.
-
+ // TODO: Is the tpduId of 1 correct here?
final S7MessageRequest readRequest = new S7MessageRequest(1,new
S7ParameterReadVarRequest(
List.of(new S7VarRequestParameterItemAddress(
new S7AddressAny(
@@ -1636,17 +1489,14 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
}
//Create the message structure for the user request.
-
- parameterItems.clear();
- payloadItems.clear();
-
+
Iterator<String> iter = request.getTagNames().iterator();
String tagName;
PlcValue plcValue;
while (iter.hasNext()) {
tagName = iter.next();
- final S7StringTag tagRef = (S7StringTag) request.getTag(tagName);
+ final S7StringVarLengthTag tagRef = (S7StringVarLengthTag)
request.getTag(tagName);
plcValue = request.getPlcValue(tagName);
//Check if String
@@ -1675,10 +1525,45 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
payloadItems.add(new
S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize,
byteBuffer.array()/*, hasNext*/));
}
-
- }
-
-
+
+ return new TPKTPacket(
+ new COTPPacketData(
+ null,
+ new S7MessageRequest(tpduId,
+ new S7ParameterWriteVarRequest(parameterItems),
+ new S7PayloadWriteVarRequest(payloadItems)
+ ),
+ true,
+ (byte) tpduId
+ )
+ );
+ }
+
+ private TPKTPacket encodeOrdinaryWriteRequest(DefaultPlcWriteRequest
request,
+ int tpduId) {
+ List<S7VarRequestParameterItem> parameterItems = new
ArrayList<>(request.getNumberOfTags());
+ List<S7VarPayloadDataItem> payloadItems = new
ArrayList<>(request.getNumberOfTags());
+
+ for (String tagName : request.getTagNames()) {
+ final S7Tag tag = (S7Tag) request.getTag(tagName);
+ final PlcValue plcValue = request.getPlcValue(tagName);
+ parameterItems.add(new
S7VarRequestParameterItemAddress(encodeS7Address(tag)));
+ payloadItems.add(serializePlcValue(tag, plcValue));
+ }
+
+ return new TPKTPacket(
+ new COTPPacketData(
+ null,
+ new S7MessageRequest(tpduId,
+ new S7ParameterWriteVarRequest(parameterItems),
+ new S7PayloadWriteVarRequest(payloadItems)
+ ),
+ true,
+ (byte) tpduId
+ )
+ );
+ }
+
/**
* This method is only called when there is no Response Handler.
*/
@@ -1885,7 +1770,7 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
} else {
logger.warn("Got an unknown error response from the PLC. Error
Class: {}, Error Code {}. " +
"We probably need to implement explicit handling for
this, so please file a bug-report " +
- "on https://issues.apache.org/jira/projects/PLC4X and
ideally attach a WireShark dump " +
+ "on https://github.com/apache/plc4x/issues and ideally
attach a WireShark dump " +
"containing a capture of the communication.",
errorClass, errorCode);
for (String tagName : plcReadRequest.getTagNames()) {
@@ -1896,13 +1781,12 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
}
}
- //TODO: Reemsambling message.
+ //TODO: Reassembling message.
if (responseMessage instanceof S7MessageResponseData) {
for (String tagName : plcReadRequest.getTagNames()) {
- if (plcReadRequest.getTag(tagName) instanceof S7StringTag) {
+ if (plcReadRequest.getTag(tagName) instanceof
S7StringVarLengthTag) {
PlcValue plcValue = null;
PlcResponseCode responseCode =
PlcResponseCode.INTERNAL_ERROR;
- List<PlcValue> plcValues = new LinkedList<>();
ResponseItem<PlcValue> result = new
ResponseItem<>(responseCode, plcValue);
values.put(tagName, result);
}
@@ -2036,32 +1920,24 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
List<S7VarPayloadDataItem> payloadItems = payload.getItems();
int index = 0;
- PlcResponseCode responseCode = null;
- PlcValue plcValue = null;
+ PlcResponseCode responseCode;
+ PlcValue plcValue;
for (String tagName : plcReadRequest.getTagNames()) {
-
- if (plcReadRequest.getTag(tagName) instanceof S7StringTag) {
-
- final S7VarPayloadDataItem payloadItem =
payloadItems.get(index);
- responseCode =
decodeResponseCode(payloadItem.getReturnCode());
- plcValue = new PlcSTRING(new String(payloadItem.getData(),
StandardCharsets.UTF_8));
-
- } else {
- S7Tag tag = (S7Tag) plcReadRequest.getTag(tagName);
- S7VarPayloadDataItem payloadItem = payloadItems.get(index);
+ S7Tag tag = (S7Tag) plcReadRequest.getTag(tagName);
+ S7VarPayloadDataItem payloadItem = payloadItems.get(index);
- responseCode = decodeResponseCode(payloadItem.getReturnCode());
- plcValue = null;
-
- ByteBuf data = Unpooled.wrappedBuffer(payloadItem.getData());
- if (responseCode == PlcResponseCode.OK) {
- try {
- plcValue = parsePlcValue(tag, data);
- } catch (Exception e) {
- throw new PlcProtocolException("Error decoding
PlcValue", e);
- }
+ responseCode = decodeResponseCode(payloadItem.getReturnCode());
+ plcValue = null;
+
+ ByteBuf data = Unpooled.wrappedBuffer(payloadItem.getData());
+ if (responseCode == PlcResponseCode.OK) {
+ try {
+ plcValue = parsePlcValue(tag, data);
+ } catch (Exception e) {
+ throw new PlcProtocolException("Error decoding PlcValue",
e);
}
- };
+ }
+
ResponseItem<PlcValue> result = new ResponseItem<>(responseCode,
plcValue);
values.put(tagName, result);
index++;
@@ -2137,10 +2013,10 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}
- private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue
plcValue, Boolean hasNext) {
+ private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue
plcValue) {
try {
DataTransportSize transportSize =
tag.getDataType().getDataTransportSize();
- int stringLength = (tag instanceof S7StringTag) ? ((S7StringTag)
tag).getStringLength() : 254;
+ int stringLength = (tag instanceof S7StringFixedLengthTag) ?
((S7StringFixedLengthTag) tag).getStringLength() : 254;
ByteBuffer byteBuffer = null;
for (int i = 0; i < tag.getNumberOfElements(); i++) {
final int lengthInBits =
DataItem.getLengthInBits(plcValue.getIndex(i),
tag.getDataType().getDataProtocolId(), stringLength);
@@ -2165,7 +2041,7 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
private PlcValue parsePlcValue(S7Tag tag, ByteBuf data) {
ReadBuffer readBuffer = new ReadBufferByteBased(data.array());
try {
- int stringLength = (tag instanceof S7StringTag) ? ((S7StringTag)
tag).getStringLength() : 254;
+ int stringLength = (tag instanceof S7StringFixedLengthTag) ?
((S7StringFixedLengthTag) tag).getStringLength() : 254;
if (tag.getNumberOfElements() == 1) {
return DataItem.staticParse(readBuffer,
tag.getDataType().getDataProtocolId(),
stringLength);
@@ -2265,11 +2141,11 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
}
if (transportSize == TransportSize.STRING) {
transportSize = TransportSize.CHAR;
- int stringLength = (s7Tag instanceof S7StringTag) ? ((S7StringTag)
s7Tag).getStringLength() : 254;
+ int stringLength = (s7Tag instanceof S7StringFixedLengthTag) ?
((S7StringFixedLengthTag) s7Tag).getStringLength() : 254;
numElements = numElements * (stringLength + 2);
} else if (transportSize == TransportSize.WSTRING) {
transportSize = TransportSize.CHAR;
- int stringLength = (s7Tag instanceof S7StringTag) ? ((S7StringTag)
s7Tag).getStringLength() : 254;
+ int stringLength = (s7Tag instanceof S7StringFixedLengthTag) ?
((S7StringFixedLengthTag) s7Tag).getStringLength() : 254;
numElements = numElements * (stringLength + 2) * 2;
}
return new S7AddressAny(transportSize, numElements,
s7Tag.getBlockNumber(),
@@ -2328,12 +2204,8 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
CompletableFuture<S7MessageUserData> future = new
CompletableFuture<>();
- //TODO: PDU id is the same, we need check.
- int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
- }
+ //TODO: We need to verify that the returned tpdu id is the same in the
response.
+ int tpduId = getTpduId();
TPKTPacket request = createSzlReassembledRequest(tpduId,
sequenceNumber);
@@ -2372,12 +2244,8 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
private CompletableFuture<S7MessageUserData> reassembledAlarmEvents(short
sequenceNumber) {
CompletableFuture<S7MessageUserData> future = new
CompletableFuture<>();
- //TODO: PDU id is the same, we need check.
- int tpduId = tpduGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier,
reset back to 1
- if (tpduGenerator.get() == 0xFFFF) {
- tpduGenerator.set(1);
- }
+ //TODO: We need to verify that the returned tpdu id is the same in the
response.
+ int tpduId = getTpduId();
TPKTPacket request = createAlarmQueryReassembledRequest(tpduId,
sequenceNumber);
@@ -2411,6 +2279,15 @@ public class S7ProtocolLogic extends
Plc4xProtocolBase<TPKTPacket> {
return new TPKTPacket(cotpPacketData);
}
+ 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 (tpduGenerator.get() == 0xFFFF) {
+ tpduGenerator.set(1);
+ }
+ return tpduId;
+ }
+
/**
* A generic purpose error handler which terminates transaction and calls
back given future with error message.
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7PlcTagHandler.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7PlcTagHandler.java
index 4a43836a3a..0a9cdddeaf 100644
---
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7PlcTagHandler.java
+++
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7PlcTagHandler.java
@@ -27,8 +27,10 @@ public class S7PlcTagHandler implements PlcTagHandler {
@Override
public PlcTag parseTag(String tagAddress) {
- if (S7StringTag.matches(tagAddress)) {
- return S7StringTag.of(tagAddress);
+ if (S7StringVarLengthTag.matches(tagAddress)) {
+ return S7StringVarLengthTag.of(tagAddress);
+ } else if (S7StringFixedLengthTag.matches(tagAddress)) {
+ return S7StringFixedLengthTag.of(tagAddress);
} else if (S7SubscriptionTag.matches(tagAddress)) {
return S7SubscriptionTag.of(tagAddress);
} else if (S7ClkTag.matches(tagAddress)) {
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringFixedLengthTag.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringFixedLengthTag.java
new file mode 100644
index 0000000000..b573a8cefc
--- /dev/null
+++
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringFixedLengthTag.java
@@ -0,0 +1,129 @@
+/*
+ * 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
+ *
+ * https://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.java.s7.readwrite.tag;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
+import org.apache.plc4x.java.s7.readwrite.MemoryArea;
+import org.apache.plc4x.java.s7.readwrite.TransportSize;
+import org.apache.plc4x.java.spi.codegen.WithOption;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class S7StringFixedLengthTag extends S7Tag {
+
+ public static final Pattern DATA_BLOCK_STRING_FIXED_LENGTH_ADDRESS_PATTERN
=
+
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}).DB(?<transferSizeCode>[XBWD]?)(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)\\((?<stringLength>\\d{1,3})\\)(\\[(?<numElements>\\d+)])?");
+
+ public static final Pattern DATA_BLOCK_STRING_FIXED_LENGTH_SHORT_PATTERN =
+
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}):(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)\\((?<stringLength>\\d{1,3})\\)(\\[(?<numElements>\\d+)])?");
+
+ private final int stringLength;
+
+ public S7StringFixedLengthTag(TransportSize dataType, MemoryArea
memoryArea,
+ int blockNumber, int byteOffset,
+ byte bitOffset, int numElements,
+ int stringLength) {
+ super(dataType, memoryArea, blockNumber, byteOffset, bitOffset,
numElements);
+ this.stringLength = stringLength;
+ }
+
+ public int getStringLength() {
+ return stringLength;
+ }
+
+ public static boolean matches(String address) {
+ return
DATA_BLOCK_STRING_FIXED_LENGTH_ADDRESS_PATTERN.matcher(address).matches() ||
+
DATA_BLOCK_STRING_FIXED_LENGTH_SHORT_PATTERN.matcher(address).matches();
+ }
+
+
+ @Override
+ public void serialize(WriteBuffer writeBuffer) throws
SerializationException {
+ writeBuffer.pushContext(getClass().getSimpleName());
+
+ String memoryArea = getMemoryArea().name();
+ writeBuffer.writeString("memoryArea",
+ memoryArea.getBytes(StandardCharsets.UTF_8).length * 8,
+ memoryArea,
WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
+
+ writeBuffer.writeUnsignedInt("blockNumber", 16, getBlockNumber());
+ writeBuffer.writeUnsignedInt("byteOffset", 16, getByteOffset());
+ writeBuffer.writeUnsignedInt("bitOffset", 8, getBitOffset());
+ writeBuffer.writeUnsignedInt("numElements", 16, getNumberOfElements());
+ writeBuffer.writeInt("stringLength", 64, getStringLength());
+
+ String dataType = getDataType().name();
+ writeBuffer.writeString("dataType",
+ dataType.getBytes(StandardCharsets.UTF_8).length * 8,
+ dataType, WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
+
+ writeBuffer.popContext(getClass().getSimpleName());
+ }
+
+ public static S7StringFixedLengthTag of(String address) {
+ Matcher matcher;
+
+ if ((matcher =
DATA_BLOCK_STRING_FIXED_LENGTH_ADDRESS_PATTERN.matcher(address)).matches()) {
+ TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
+ int stringLength = Integer.parseInt(matcher.group(STRING_LENGTH));
+ MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
+ int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
+ Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
+ int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
+ byte bitOffset = 0;
+ if (matcher.group(BIT_OFFSET) != null) {
+ bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
+ } else if (dataType == TransportSize.BOOL) {
+ throw new PlcInvalidTagException("Expected bit offset for BOOL
parameters.");
+ }
+ int numElements = 1;
+ if (matcher.group(NUM_ELEMENTS) != null) {
+ numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
+ }
+
+ if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
+ throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
+ "' doesn't match specified data type '" + dataType.name()
+ "'");
+ }
+
+ return new S7StringFixedLengthTag(dataType, memoryArea,
blockNumber, byteOffset, bitOffset, numElements, stringLength);
+ } else if ((matcher =
DATA_BLOCK_STRING_FIXED_LENGTH_SHORT_PATTERN.matcher(address)).matches()) {
+ TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
+ int stringLength = Integer.parseInt(matcher.group(STRING_LENGTH));
+ MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
+ int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
+ int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
+ byte bitOffset = 0;
+ int numElements = 1;
+ if (matcher.group(NUM_ELEMENTS) != null) {
+ numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
+ }
+
+ return new S7StringFixedLengthTag(dataType, memoryArea,
blockNumber,
+ byteOffset, bitOffset, numElements, stringLength);
+ }
+
+ return null;
+ }
+
+}
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringTag.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringTag.java
deleted file mode 100644
index 4e81fb0da2..0000000000
---
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringTag.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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
- *
- * https://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.java.s7.readwrite.tag;
-
-import org.apache.plc4x.java.s7.readwrite.MemoryArea;
-import org.apache.plc4x.java.s7.readwrite.TransportSize;
-import org.apache.plc4x.java.spi.codegen.WithOption;
-import org.apache.plc4x.java.spi.generation.SerializationException;
-import org.apache.plc4x.java.spi.generation.WriteBuffer;
-
-import java.nio.charset.StandardCharsets;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.BIT_OFFSET;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.BLOCK_NUMBER;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.BYTE_OFFSET;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.DATA_TYPE;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.NUM_ELEMENTS;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.STRING_LENGTH;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.TRANSFER_SIZE_CODE;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.checkByteOffset;
-import static
org.apache.plc4x.java.s7.readwrite.tag.S7Tag.checkDataBlockNumber;
-import static org.apache.plc4x.java.s7.readwrite.tag.S7Tag.getSizeCode;
-
-public class S7StringTag extends S7Tag {
-
- private static final Pattern DATA_BLOCK_STRING =
-
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}):(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)?");
-
- private static final Pattern DATA_BLOCK_STRING_SHORT =
-
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}).DB(?<transferSizeCode>[XBWD]?)(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)?");
-
- private static final Pattern DATA_BLOCK_STRING_ADDRESS_PATTERN =
-
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}).DB(?<transferSizeCode>[XBWD]?)(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)\\((?<stringLength>\\d{1,3})\\)(\\[(?<numElements>\\d+)])?");
-
- private static final Pattern DATA_BLOCK_STRING_SHORT_PATTERN =
-
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}):(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)\\((?<stringLength>\\d{1,3})\\)(\\[(?<numElements>\\d+)])?");
-
-
-
- private final int stringLength;
-
- protected S7StringTag(TransportSize dataType, MemoryArea memoryArea,
- int blockNumber, int byteOffset,
- byte bitOffset, int numElements,
- int stringLength) {
- super(dataType, memoryArea, blockNumber, byteOffset, bitOffset,
numElements);
- this.stringLength = stringLength;
- }
-
- public int getStringLength() {
- return stringLength;
- }
-
- public static boolean matches(String address) {
- return DATA_BLOCK_STRING.matcher(address).matches() ||
- DATA_BLOCK_STRING_SHORT.matcher(address).matches() ||
- DATA_BLOCK_STRING_ADDRESS_PATTERN.matcher(address).matches() ||
- DATA_BLOCK_STRING_SHORT_PATTERN.matcher(address).matches();
- }
-
-
- @Override
- public void serialize(WriteBuffer writeBuffer) throws
SerializationException {
- writeBuffer.pushContext(getClass().getSimpleName());
-
- String memoryArea = getMemoryArea().name();
- writeBuffer.writeString("memoryArea",
- memoryArea.getBytes(StandardCharsets.UTF_8).length * 8,
- memoryArea,
WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
-
- writeBuffer.writeUnsignedInt("blockNumber", 16, getBlockNumber());
- writeBuffer.writeUnsignedInt("byteOffset", 16, getByteOffset());
- writeBuffer.writeUnsignedInt("bitOffset", 8, getBitOffset());
- writeBuffer.writeUnsignedInt("numElements", 16, getNumberOfElements());
- writeBuffer.writeInt("stringLength", 64, getStringLength());
-
- String dataType = getDataType().name();
- writeBuffer.writeString("dataType",
- dataType.getBytes(StandardCharsets.UTF_8).length * 8,
- dataType, WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
-
- writeBuffer.popContext(getClass().getSimpleName());
- }
-
- public static S7StringTag of(String address) {
- Matcher matcher;
-
- if ((matcher = DATA_BLOCK_STRING_SHORT.matcher(address)).matches()) {
- TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
- int stringLength = -1;
- MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
- int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
- Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
- int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
- byte bitOffset = 0;
- if (matcher.group(BIT_OFFSET) != null) {
- bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
- } else if (dataType == TransportSize.BOOL) {
- throw new PlcInvalidTagException("Expected bit offset for BOOL
parameters.");
- }
- int numElements = 1;
-// if (matcher.group(NUM_ELEMENTS) != null) {
-// numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
-// }
-
- if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
- throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
- "' doesn't match specified data type '" + dataType.name()
+ "'");
- }
-
- return new S7StringTag(dataType, memoryArea, blockNumber,
byteOffset, bitOffset, numElements, stringLength);
-
- } else if ((matcher = DATA_BLOCK_STRING.matcher(address)).matches()) {
- TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
- int stringLength = Integer.parseInt(matcher.group(STRING_LENGTH));
- MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
- int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
- Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
- int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
- byte bitOffset = 0;
- if (matcher.group(BIT_OFFSET) != null) {
- bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
- } else if (dataType == TransportSize.BOOL) {
- throw new PlcInvalidTagException("Expected bit offset for BOOL
parameters.");
- }
- int numElements = 1;
- if (matcher.group(NUM_ELEMENTS) != null) {
- numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
- }
-
- if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
- throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
- "' doesn't match specified data type '" + dataType.name()
+ "'");
- }
-
- return new S7StringTag(dataType, memoryArea, blockNumber,
byteOffset, bitOffset, numElements, stringLength);
-
- } else if ((matcher =
DATA_BLOCK_STRING_ADDRESS_PATTERN.matcher(address)).matches()) {
- TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
- int stringLength = Integer.parseInt(matcher.group(STRING_LENGTH));
- MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
- int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
- Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
- int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
- byte bitOffset = 0;
- if (matcher.group(BIT_OFFSET) != null) {
- bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
- } else if (dataType == TransportSize.BOOL) {
- throw new PlcInvalidTagException("Expected bit offset for BOOL
parameters.");
- }
- int numElements = 1;
- if (matcher.group(NUM_ELEMENTS) != null) {
- numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
- }
-
- if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
- throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
- "' doesn't match specified data type '" + dataType.name()
+ "'");
- }
-
- return new S7StringTag(dataType, memoryArea, blockNumber,
byteOffset, bitOffset, numElements, stringLength);
- } else if ((matcher =
DATA_BLOCK_STRING_SHORT_PATTERN.matcher(address)).matches()) {
- TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
- int stringLength = Integer.parseInt(matcher.group(STRING_LENGTH));
- MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
- int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
- int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
- byte bitOffset = 0;
- int numElements = 1;
- if (matcher.group(NUM_ELEMENTS) != null) {
- numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
- }
-
- return new S7StringTag(dataType, memoryArea, blockNumber,
- byteOffset, bitOffset, numElements, stringLength);
- }
-
- return null;
- }
-
-}
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringVarLengthTag.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringVarLengthTag.java
new file mode 100644
index 0000000000..b803944481
--- /dev/null
+++
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7StringVarLengthTag.java
@@ -0,0 +1,119 @@
+/*
+ * 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
+ *
+ * https://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.java.s7.readwrite.tag;
+
+import org.apache.plc4x.java.s7.readwrite.MemoryArea;
+import org.apache.plc4x.java.s7.readwrite.TransportSize;
+import org.apache.plc4x.java.spi.codegen.WithOption;
+import org.apache.plc4x.java.spi.generation.SerializationException;
+import org.apache.plc4x.java.spi.generation.WriteBuffer;
+
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.plc4x.java.api.exceptions.PlcInvalidTagException;
+
+public class S7StringVarLengthTag extends S7Tag {
+
+ public static final Pattern DATA_BLOCK_STRING_VAR_LENGTH_ADDRESS_PATTERN =
+
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}).DB(?<transferSizeCode>[XBWD]?)(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)(\\[(?<numElements>\\d+)])?");
+
+ public static final Pattern DATA_BLOCK_STRING_VAR_LENGTH_SHORT_PATTERN =
+
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}):(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>STRING|WSTRING)(\\[(?<numElements>\\d+)])?");
+
+
+ protected S7StringVarLengthTag(TransportSize dataType, MemoryArea
memoryArea,
+ int blockNumber, int byteOffset,
+ byte bitOffset, int numElements) {
+ super(dataType, memoryArea, blockNumber, byteOffset, bitOffset,
numElements);
+ }
+
+ public static boolean matches(String address) {
+ return
DATA_BLOCK_STRING_VAR_LENGTH_ADDRESS_PATTERN.matcher(address).matches() ||
+
DATA_BLOCK_STRING_VAR_LENGTH_SHORT_PATTERN.matcher(address).matches();
+ }
+
+
+ @Override
+ public void serialize(WriteBuffer writeBuffer) throws
SerializationException {
+ writeBuffer.pushContext(getClass().getSimpleName());
+
+ String memoryArea = getMemoryArea().name();
+ writeBuffer.writeString("memoryArea",
+ memoryArea.getBytes(StandardCharsets.UTF_8).length * 8,
+ memoryArea,
WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
+
+ writeBuffer.writeUnsignedInt("blockNumber", 16, getBlockNumber());
+ writeBuffer.writeUnsignedInt("byteOffset", 16, getByteOffset());
+ writeBuffer.writeUnsignedInt("bitOffset", 8, getBitOffset());
+ writeBuffer.writeUnsignedInt("numElements", 16, getNumberOfElements());
+
+ String dataType = getDataType().name();
+ writeBuffer.writeString("dataType",
+ dataType.getBytes(StandardCharsets.UTF_8).length * 8,
+ dataType, WithOption.WithEncoding(StandardCharsets.UTF_8.name()));
+
+ writeBuffer.popContext(getClass().getSimpleName());
+ }
+
+ public static S7StringVarLengthTag of(String address) {
+ Matcher matcher;
+
+ if ((matcher =
DATA_BLOCK_STRING_VAR_LENGTH_ADDRESS_PATTERN.matcher(address)).matches()) {
+ TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
+ MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
+ int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
+ Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
+ int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
+ byte bitOffset = 0;
+ if (matcher.group(BIT_OFFSET) != null) {
+ bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
+ } else if (dataType == TransportSize.BOOL) {
+ throw new PlcInvalidTagException("Expected bit offset for BOOL
parameters.");
+ }
+ int numElements = 1;
+ if (matcher.group(NUM_ELEMENTS) != null) {
+ numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
+ }
+
+ if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
+ throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
+ "' doesn't match specified data type '" + dataType.name()
+ "'");
+ }
+
+ return new S7StringVarLengthTag(dataType, memoryArea, blockNumber,
byteOffset, bitOffset, numElements);
+ } else if ((matcher =
DATA_BLOCK_STRING_VAR_LENGTH_SHORT_PATTERN.matcher(address)).matches()) {
+ TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
+ MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
+ int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
+ int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
+ byte bitOffset = 0;
+ int numElements = 1;
+ if (matcher.group(NUM_ELEMENTS) != null) {
+ numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
+ }
+
+ return new S7StringVarLengthTag(dataType, memoryArea, blockNumber,
+ byteOffset, bitOffset, numElements);
+ }
+
+ return null;
+ }
+
+}
diff --git
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7Tag.java
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7Tag.java
index 26c7917ac4..552555e56f 100644
---
a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7Tag.java
+++
b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/tag/S7Tag.java
@@ -52,8 +52,6 @@ public class S7Tag implements PlcTag, Serializable {
private static final Pattern DATA_BLOCK_SHORT_PATTERN =
Pattern.compile("^%DB(?<blockNumber>\\d{1,5}):(?<byteOffset>\\d{1,7})(.(?<bitOffset>[0-7]))?:(?<dataType>[a-zA-Z_]+)(\\[(?<numElements>\\d+)])?");
-
-
private static final Pattern PLC_PROXY_ADDRESS_PATTERN =
Pattern.compile("[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}");
@@ -131,54 +129,14 @@ public class S7Tag implements PlcTag, Serializable {
}
public static boolean matches(String tagString) {
- return
- DATA_BLOCK_ADDRESS_PATTERN.matcher(tagString).matches() ||
- DATA_BLOCK_SHORT_PATTERN.matcher(tagString).matches() ||
- PLC_PROXY_ADDRESS_PATTERN.matcher(tagString).matches() ||
- ADDRESS_PATTERN.matcher(tagString).matches();
+ return DATA_BLOCK_ADDRESS_PATTERN.matcher(tagString).matches() ||
+ DATA_BLOCK_SHORT_PATTERN.matcher(tagString).matches() ||
+ PLC_PROXY_ADDRESS_PATTERN.matcher(tagString).matches() ||
+ ADDRESS_PATTERN.matcher(tagString).matches();
}
public static S7Tag of(String tagString) {
Matcher matcher;
-// if ((matcher =
DATA_BLOCK_STRING_ADDRESS_PATTERN.matcher(tagString)).matches()) {
-// TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
-// int stringLength =
Integer.parseInt(matcher.group(STRING_LENGTH));
-// MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
-// int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
-// Short transferSizeCode =
getSizeCode(matcher.group(TRANSFER_SIZE_CODE));
-// int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
-// byte bitOffset = 0;
-// if (matcher.group(BIT_OFFSET) != null) {
-// bitOffset = Byte.parseByte(matcher.group(BIT_OFFSET));
-// } else if (dataType == TransportSize.BOOL) {
-// throw new PlcInvalidTagException("Expected bit offset for
BOOL parameters.");
-// }
-// int numElements = 1;
-// if (matcher.group(NUM_ELEMENTS) != null) {
-// numElements = Integer.parseInt(matcher.group(NUM_ELEMENTS));
-// }
-//
-// if ((transferSizeCode != null) && (dataType.getShortName() !=
transferSizeCode)) {
-// throw new PlcInvalidTagException("Transfer size code '" +
transferSizeCode +
-// "' doesn't match specified data type '" +
dataType.name() + "'");
-// }
-//
-// return new S7StringTag(dataType, memoryArea, blockNumber,
byteOffset, bitOffset, numElements, stringLength);
-//// } else if ((matcher =
DATA_BLOCK_STRING_SHORT_PATTERN.matcher(tagString)).matches()) {
-//// TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
-//// int stringLength =
Integer.parseInt(matcher.group(STRING_LENGTH));
-//// MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
-//// int blockNumber =
checkDataBlockNumber(Integer.parseInt(matcher.group(BLOCK_NUMBER)));
-//// int byteOffset =
checkByteOffset(Integer.parseInt(matcher.group(BYTE_OFFSET)));
-//// byte bitOffset = 0;
-//// int numElements = 1;
-//// if (matcher.group(NUM_ELEMENTS) != null) {
-//// numElements =
Integer.parseInt(matcher.group(NUM_ELEMENTS));
-//// }
-////
-//// return new S7StringTag(dataType, memoryArea, blockNumber,
-//// byteOffset, bitOffset, numElements, stringLength);
-// } else
if ((matcher =
DATA_BLOCK_ADDRESS_PATTERN.matcher(tagString)).matches()) {
TransportSize dataType =
TransportSize.valueOf(matcher.group(DATA_TYPE));
MemoryArea memoryArea = MemoryArea.DATA_BLOCKS;
diff --git
a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
index 5632798e97..954080d23f 100644
---
a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
+++
b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/ManualS7DriverTest.java
@@ -93,6 +93,8 @@ public class ManualS7DriverTest extends ManualTest {
test.addTestCase("%DB4:138:WCHAR", new PlcWCHAR("w"));
test.addTestCase("%DB4:140:STRING(10)", new PlcSTRING("hurz"));
test.addTestCase("%DB4:396:WSTRING(10)", new PlcWSTRING("wolf"));
+ test.addTestCase("%DB4:140:STRING", new PlcSTRING("hurz"));
+ test.addTestCase("%DB4:396:WSTRING", new PlcWSTRING("wolf"));
//test.addTestCase("%DB4:70:TIME", new
PlcTIME(Duration.parse("PT1.234S"));
// Not supported in S7 1200
//test.addTestCase("%DB4:62:LTIME", new
PlcLTIME(Duration.parse("PT24015H23M12.034002044S"));
@@ -107,7 +109,11 @@ public class ManualS7DriverTest extends ManualTest {
//test.addTestCase("%DB4:112:LDATE_AND_TIME", "1978-03-28T15:36:30");
// Not supported in S7 1200
//test.addTestCase("%DB4:124:LDT", "1978-03-28T15:36:30");
+
+ long start = System.currentTimeMillis();
test.run();
+ long end = System.currentTimeMillis();
+ System.out.printf("Finished in %d ms", end - start);
}
}
diff --git
a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/tag/S7TagTest.java
b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/tag/S7TagTest.java
index 3127dbe34a..3c4a672c3a 100644
---
a/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/tag/S7TagTest.java
+++
b/plc4j/drivers/s7/src/test/java/org/apache/plc4x/java/s7/readwrite/tag/S7TagTest.java
@@ -49,7 +49,7 @@ public class S7TagTest {
Assertions.assertEquals(38, s7Tag.getByteOffset());
Assertions.assertEquals(0, s7Tag.getBitOffset());
Assertions.assertEquals("S7StringTag",
s7Tag.getClass().getSimpleName());
- S7StringTag s7StringTag = (S7StringTag) s7Tag;
+ S7StringFixedLengthTag s7StringTag = (S7StringFixedLengthTag) s7Tag;
Assertions.assertEquals(8, s7StringTag.getStringLength());
}