You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by hu...@apache.org on 2021/01/11 12:43:49 UTC
[plc4x] branch feature/native_opua_client updated: [BROKEN] Added
an optimizer to read mulitple values at once.
This is an automated email from the ASF dual-hosted git repository.
hutcheb pushed a commit to branch feature/native_opua_client
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/native_opua_client by this push:
new 0353653 [BROKEN] Added an optimizer to read mulitple values at once.
0353653 is described below
commit 0353653ad8ad0dc290e520b7a3889a523adcee58
Author: hutcheb <be...@gmail.com>
AuthorDate: Mon Jan 11 07:41:48 2021 -0500
[BROKEN] Added an optimizer to read mulitple values at once.
Need to look into return structures so I can read arrays of ByteStrings,
probably just a PlcList of PlcList of PlcValue no that I think of it.
---
.../apache/plc4x/java/opcua/OpcuaPlcDriver.java | 5 +-
.../plc4x/java/opcua/optimizer/OpcuaOptimizer.java | 63 ++++
.../java/opcua/protocol/OpcuaProtocolLogic.java | 410 +++++++++++----------
protocols/opcua/src/main/xslt/opc-types.xsl | 11 +-
4 files changed, 290 insertions(+), 199 deletions(-)
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index 4e5cdfa..a005cb3 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -21,6 +21,7 @@ package org.apache.plc4x.java.opcua;
import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.authentication.PlcAuthentication;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
+import org.apache.plc4x.java.opcua.optimizer.OpcuaOptimizer;
import org.apache.plc4x.java.opcua.protocol.*;
import org.apache.plc4x.java.opcua.config.*;
import org.apache.plc4x.java.opcua.readwrite.*;
@@ -109,8 +110,8 @@ public class OpcuaPlcDriver extends GeneratedDriverBase<OpcuaAPU> {
}
@Override
- protected BaseOptimizer getOptimizer() {
- return new SingleFieldOptimizer();
+ protected OpcuaOptimizer getOptimizer() {
+ return new OpcuaOptimizer();
}
@Override
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/optimizer/OpcuaOptimizer.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/optimizer/OpcuaOptimizer.java
new file mode 100644
index 0000000..abaf4f4
--- /dev/null
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/optimizer/OpcuaOptimizer.java
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ * http://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.opcua.optimizer;
+
+import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcRequest;
+import org.apache.plc4x.java.api.messages.PlcWriteRequest;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.api.value.PlcValue;
+import org.apache.plc4x.java.opcua.protocol.OpcuaField;
+import org.apache.plc4x.java.spi.context.DriverContext;
+import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest;
+import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest;
+import org.apache.plc4x.java.spi.messages.utils.FieldValueItem;
+import org.apache.plc4x.java.spi.optimizer.BaseOptimizer;
+
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+public class OpcuaOptimizer extends BaseOptimizer{
+
+ @Override
+ protected List<PlcRequest> processReadRequest(PlcReadRequest readRequest, DriverContext driverContext) {
+ List<PlcRequest> processedRequests = new LinkedList<>();
+
+ // List of all items in the current request.
+ LinkedHashMap<String, PlcField> curFields = new LinkedHashMap<>();
+
+ for (String fieldName : readRequest.getFieldNames()) {
+ OpcuaField field = (OpcuaField) readRequest.getField(fieldName);
+ curFields.put(fieldName, field);
+ }
+
+ // Create a new PlcReadRequest from the remaining field items.
+ if(!curFields.isEmpty()) {
+ processedRequests.add(new DefaultPlcReadRequest(
+ ((DefaultPlcReadRequest) readRequest).getReader(), curFields));
+ }
+
+ return processedRequests;
+ }
+
+
+}
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
index 229992a..9d7f8de 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
@@ -69,13 +69,14 @@ import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.nio.charset.StandardCharsets;
-import static org.apache.plc4x.java.spi.configuration.ConfigurationFactory.configure;
/**
* The S7 Protocol states that there can not be more then {min(maxAmqCaller, maxAmqCallee} "ongoing" requests.
@@ -176,11 +177,11 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
.unwrap(p -> (OpcuaMessageResponse) p.getMessage())
.handle(opcuaMessageResponse -> {
LOGGER.info("Got Close Session Response Connection Response" + opcuaMessageResponse.toString());
- closeSecureChannel(context);
+ onDisconnectCloseSecureChannel(context);
});
}
- private void closeSecureChannel(ConversationContext<OpcuaAPU> context) {
+ private void onDisconnectCloseSecureChannel(ConversationContext<OpcuaAPU> context) {
int transactionId = transactionIdentifierGenerator.getAndIncrement();
if(transactionIdentifierGenerator.get() == 0xFFFF) {
@@ -496,214 +497,233 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
CompletableFuture<PlcReadResponse> future = new CompletableFuture<>();
DefaultPlcReadRequest request = (DefaultPlcReadRequest) readRequest;
- if(request.getFieldNames().size() == 1) {
- String fieldName = request.getFieldNames().iterator().next();
- OpcuaField field = (OpcuaField) request.getField(fieldName);
-
- int requestHandle = requestHandleGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
- if(requestHandleGenerator.get() == 0xFFFF) {
- requestHandleGenerator.set(1);
- }
- RequestHeader requestHeader = new RequestHeader(authenticationToken,
- getCurrentDateTime(),
- requestHandle,
- 0L,
- NULL_STRING,
- REQUEST_TIMEOUT_LONG,
- NULL_EXTENSION_OBJECT);
+ int requestHandle = requestHandleGenerator.getAndIncrement();
+ // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
+ if(requestHandleGenerator.get() == 0xFFFF) {
+ requestHandleGenerator.set(1);
+ }
- ReadValueId[] readValueArray = new ReadValueId[1];
+ RequestHeader requestHeader = new RequestHeader(authenticationToken,
+ getCurrentDateTime(),
+ requestHandle,
+ 0L,
+ NULL_STRING,
+ REQUEST_TIMEOUT_LONG,
+ NULL_EXTENSION_OBJECT);
- NodeIdString nodeId = new NodeIdString(NodeIdType.nodeIdTypeString, new StringNodeId(field.getNamespace(), new PascalString(field.getIdentifier().length(), field.getIdentifier())));
+ ReadValueId[] readValueArray = new ReadValueId[request.getFieldNames().size()];
+ Iterator<String> iterator = request.getFieldNames().iterator();
+ for (int i = 0; i < request.getFieldNames().size(); i++ ) {
+ String fieldName = iterator.next();
+ OpcuaField field = (OpcuaField) request.getField(fieldName);
- readValueArray[0] = new ReadValueId(nodeId,
+ NodeId nodeId = null;
+ if (field.getIdentifierType() == OpcuaIdentifierType.BINARY_IDENTIFIER) {
+ nodeId = new NodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte, new TwoByteNodeId(Short.valueOf(field.getIdentifier())));
+ } else if (field.getIdentifierType() == OpcuaIdentifierType.NUMBER_IDENTIFIER) {
+ nodeId = new NodeIdNumeric(NodeIdType.nodeIdTypeNumeric, new NumericNodeId(field.getNamespace(),Long.valueOf(field.getIdentifier())));
+ } else if (field.getIdentifierType() == OpcuaIdentifierType.GUID_IDENTIFIER) {
+ nodeId = new NodeIdGuid(NodeIdType.nodeIdTypeGuid, new GuidNodeId(field.getNamespace(), field.getIdentifier()));
+ } else if (field.getIdentifierType() == OpcuaIdentifierType.STRING_IDENTIFIER) {
+ nodeId = new NodeIdString(NodeIdType.nodeIdTypeString, new StringNodeId(field.getNamespace(), new PascalString(field.getIdentifier().length(), field.getIdentifier())));
+ }
+ readValueArray[i] = new ReadValueId(nodeId,
0xD,
NULL_STRING,
new QualifiedName(0, NULL_STRING));
+ }
- ReadRequest opcuaReadRequest = new ReadRequest((byte) 1,
- (byte) 0,
- requestHeader,
- 0.0d,
- TimestampsToReturn.timestampsToReturnNeither,
- readValueArray.length,
- readValueArray);
-
- int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
- // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
- if(transactionIdentifierGenerator.get() == 0xFFFF) {
- transactionIdentifierGenerator.set(1);
- }
+ ReadRequest opcuaReadRequest = new ReadRequest((byte) 1,
+ (byte) 0,
+ requestHeader,
+ 0.0d,
+ TimestampsToReturn.timestampsToReturnNeither,
+ readValueArray.length,
+ readValueArray);
- OpcuaMessageRequest readMessageRequest = new OpcuaMessageRequest(CHUNK,
- channelId.get(),
- tokenId.get(),
- transactionIdentifier,
- transactionIdentifier,
- opcuaReadRequest);
-
- RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
- transaction.submit(() -> context.sendRequest(new OpcuaAPU(readMessageRequest))
- .expectResponse(OpcuaAPU.class, REQUEST_TIMEOUT)
- .onTimeout(future::completeExceptionally)
- .onError((p, e) -> future.completeExceptionally(e))
- .check(p -> p.getMessage() instanceof OpcuaMessageResponse)
- .unwrap(p -> (OpcuaMessageResponse) p.getMessage())
- .handle(opcuaResponse -> {
- // Try to decode the response data based on the corresponding request.
- ReadResponse readResponse = (ReadResponse) opcuaResponse.getMessage();
-
- DataValue[] results = readResponse.getResults();
- PlcValue value = null;
- PlcResponseCode responseCode = PlcResponseCode.OK;
- if (results.length > 0) {
- if (results[0].getStatusCode() == null) {
- Variant variant = results[0].getValue();
- LOGGER.info("Repsponse includes Variant of type " + variant.getClass().toString());
- if (variant instanceof VariantBoolean) {
- boolean[] array = ((VariantBoolean) variant).getValue();
- int length = array.length;
- Boolean[] tmpValue = new Boolean[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantSByte) {
- byte[] array = ((VariantSByte) variant).getValue();
- int length = array.length;
- Byte[] tmpValue = new Byte[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantByte) {
- short[] array = ((VariantByte) variant).getValue();
- int length = array.length;
- Short[] tmpValue = new Short[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantInt16) {
- short[] array = ((VariantInt16) variant).getValue();
- int length = array.length;
- Short[] tmpValue = new Short[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantUInt16) {
- int[] array = ((VariantUInt16) variant).getValue();
- int length = array.length;
- Integer[] tmpValue = new Integer[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantInt32) {
- int[] array = ((VariantInt32) variant).getValue();
- int length = array.length;
- Integer[] tmpValue = new Integer[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantUInt32) {
- long[] array = ((VariantUInt32) variant).getValue();
- int length = array.length;
- Long[] tmpValue = new Long[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantInt64) {
- long[] array = ((VariantInt64) variant).getValue();
- int length = array.length;
- Long[] tmpValue = new Long[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantUInt64) {
- value = IEC61131ValueHandler.of(((VariantUInt64) variant).getValue());
- } else if (variant instanceof VariantFloat) {
- float[] array = ((VariantFloat) variant).getValue();
- int length = array.length;
- Float[] tmpValue = new Float[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantDouble) {
- double[] array = ((VariantDouble) variant).getValue();
- int length = array.length;
- Double[] tmpValue = new Double[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = array[i];
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantString) {
- int length = ((VariantString) variant).getValue().length;
- PascalString[] stringArray = ((VariantString) variant).getValue();
- String[] tmpValue = new String[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = stringArray[i].getStringValue();
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantDateTime) {
- long[] array = ((VariantDateTime) variant).getValue();
- int length = array.length;
- LocalDateTime[] tmpValue = new LocalDateTime[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = LocalDateTime.ofInstant(Instant.ofEpochMilli(array[i]), ZoneId.systemDefault());
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else if (variant instanceof VariantGuid) {
- int length = ((VariantGuid) variant).getValue().length;
- String[] stringArray = ((VariantGuid) variant).getValue();
- value = IEC61131ValueHandler.of(stringArray);
- } else if (variant instanceof VariantXmlElement) {
- int length = ((VariantXmlElement) variant).getValue().length;
- PascalString[] stringArray = ((VariantXmlElement) variant).getValue();
- String[] tmpValue = new String[length];
- for (int i = 0; i < length; i++) {
- tmpValue[i] = stringArray[i].getStringValue();
- }
- value = IEC61131ValueHandler.of(tmpValue);
- } else {
- responseCode = PlcResponseCode.UNSUPPORTED;
- LOGGER.error("Data type - " + variant.getClass() + " is not supported ");
- }
- } else {
- if (results[0].getStatusCode().getStatusCode() == OpcuaStatusCodes.BadNodeIdUnknown.getValue()) {
- responseCode = PlcResponseCode.NOT_FOUND;
- } else {
- responseCode = PlcResponseCode.UNSUPPORTED;
- }
- LOGGER.error("Error while reading value from OPC UA server error code:- " + results[0].getStatusCode().toString());
- }
+ int transactionIdentifier = transactionIdentifierGenerator.getAndIncrement();
+ // If we've reached the max value for a 16 bit transaction identifier, reset back to 1
+ if(transactionIdentifierGenerator.get() == 0xFFFF) {
+ transactionIdentifierGenerator.set(1);
+ }
- }
+ OpcuaMessageRequest readMessageRequest = new OpcuaMessageRequest(CHUNK,
+ channelId.get(),
+ tokenId.get(),
+ transactionIdentifier,
+ transactionIdentifier,
+ opcuaReadRequest);
- // Prepare the response.
- PlcReadResponse response = new DefaultPlcReadResponse(request,
- Collections.singletonMap(fieldName, new ResponseItem<>(responseCode, value)));
+ RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
+ transaction.submit(() -> context.sendRequest(new OpcuaAPU(readMessageRequest))
+ .expectResponse(OpcuaAPU.class, REQUEST_TIMEOUT)
+ .onTimeout(future::completeExceptionally)
+ .onError((p, e) -> future.completeExceptionally(e))
+ .check(p -> p.getMessage() instanceof OpcuaMessageResponse)
+ .unwrap(p -> (OpcuaMessageResponse) p.getMessage())
+ .handle(opcuaResponse -> {
+ // Prepare the response.
+ PlcReadResponse response = new DefaultPlcReadResponse(request,
+ readResponse(request.getFieldNames(), (ReadResponse) opcuaResponse.getMessage()));
- // Pass the response back to the application.
- future.complete(response);
+ // Pass the response back to the application.
+ future.complete(response);
+
+ // Finish the request-transaction.
+ transaction.endRequest();
+ }));
- // Finish the request-transaction.
- transaction.endRequest();
- }));
- } else {
- future.completeExceptionally(new PlcRuntimeException("Modbus only supports single filed requests"));
- }
return future;
}
-
+ private Map<String, ResponseItem<PlcValue>> readResponse(LinkedHashSet<String> fieldNames, ReadResponse readResponse) {
+ DataValue[] results = readResponse.getResults();
+
+ PlcResponseCode responseCode = PlcResponseCode.OK;
+ Map<String, ResponseItem<PlcValue>> response = new HashMap<>();
+ int count = 0;
+ for ( String field : fieldNames ) {
+ PlcValue value = null;
+ if (results[count].getStatusCode() == null) {
+ Variant variant = results[count].getValue();
+ LOGGER.info("Repsponse includes Variant of type " + variant.getClass().toString());
+ if (variant instanceof VariantBoolean) {
+ byte[] array = ((VariantBoolean) variant).getValue();
+ int length = array.length;
+ Byte[] tmpValue = new Byte[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantSByte) {
+ byte[] array = ((VariantSByte) variant).getValue();
+ int length = array.length;
+ Byte[] tmpValue = new Byte[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantByte) {
+ short[] array = ((VariantByte) variant).getValue();
+ int length = array.length;
+ Short[] tmpValue = new Short[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantInt16) {
+ short[] array = ((VariantInt16) variant).getValue();
+ int length = array.length;
+ Short[] tmpValue = new Short[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantUInt16) {
+ int[] array = ((VariantUInt16) variant).getValue();
+ int length = array.length;
+ Integer[] tmpValue = new Integer[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantInt32) {
+ int[] array = ((VariantInt32) variant).getValue();
+ int length = array.length;
+ Integer[] tmpValue = new Integer[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantUInt32) {
+ long[] array = ((VariantUInt32) variant).getValue();
+ int length = array.length;
+ Long[] tmpValue = new Long[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantInt64) {
+ long[] array = ((VariantInt64) variant).getValue();
+ int length = array.length;
+ Long[] tmpValue = new Long[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantUInt64) {
+ value = IEC61131ValueHandler.of(((VariantUInt64) variant).getValue());
+ } else if (variant instanceof VariantFloat) {
+ float[] array = ((VariantFloat) variant).getValue();
+ int length = array.length;
+ Float[] tmpValue = new Float[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantDouble) {
+ double[] array = ((VariantDouble) variant).getValue();
+ int length = array.length;
+ Double[] tmpValue = new Double[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i];
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantString) {
+ int length = ((VariantString) variant).getValue().length;
+ PascalString[] stringArray = ((VariantString) variant).getValue();
+ String[] tmpValue = new String[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = stringArray[i].getStringValue();
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantDateTime) {
+ long[] array = ((VariantDateTime) variant).getValue();
+ int length = array.length;
+ LocalDateTime[] tmpValue = new LocalDateTime[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = LocalDateTime.ofInstant(Instant.ofEpochMilli(array[i]), ZoneId.systemDefault());
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantGuid) {
+ int length = ((VariantGuid) variant).getValue().length;
+ String[] stringArray = ((VariantGuid) variant).getValue();
+ value = IEC61131ValueHandler.of(stringArray);
+ } else if (variant instanceof VariantXmlElement) {
+ int length = ((VariantXmlElement) variant).getValue().length;
+ PascalString[] stringArray = ((VariantXmlElement) variant).getValue();
+ String[] tmpValue = new String[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = stringArray[i].getStringValue();
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else if (variant instanceof VariantByteString) {
+ //TODO:- Looking into returning structures.
+ ByteStringArray[] array = ((VariantByteString) variant).getValue();
+ int length = array.length;
+ Short[] tmpValue = new Short[length];
+ for (int i = 0; i < length; i++) {
+ tmpValue[i] = array[i].getValue();
+ }
+ value = IEC61131ValueHandler.of(tmpValue);
+ } else {
+ responseCode = PlcResponseCode.UNSUPPORTED;
+ LOGGER.error("Data type - " + variant.getClass() + " is not supported ");
+ }
+ } else {
+ if (results[count].getStatusCode().getStatusCode() == OpcuaStatusCodes.BadNodeIdUnknown.getValue()) {
+ responseCode = PlcResponseCode.NOT_FOUND;
+ } else {
+ responseCode = PlcResponseCode.UNSUPPORTED;
+ }
+ LOGGER.error("Error while reading value from OPC UA server error code:- " + results[count].getStatusCode().toString());
+ }
+ count++;
+ response.put(field, new ResponseItem<>(responseCode, value));
+ }
+ return response;
+ }
private long getCurrentDateTime() {
return (System.currentTimeMillis() * 10000) + epochOffset;
diff --git a/protocols/opcua/src/main/xslt/opc-types.xsl b/protocols/opcua/src/main/xslt/opc-types.xsl
index 7402f87..43d5015 100644
--- a/protocols/opcua/src/main/xslt/opc-types.xsl
+++ b/protocols/opcua/src/main/xslt/opc-types.xsl
@@ -165,6 +165,11 @@
[optional uint 16 'serverPicoseconds' 'serverPicosecondsSpecified']
]
+[type 'ByteStringArray'
+ [simple int 32 'arrayLength']
+ [array uint 8 'value' count 'arrayLength']
+]
+
[discriminatedType 'Variant'
[discriminator bit 'arrayLengthSpecified']
[simple bit 'arrayDimensionsSpecified']
@@ -172,7 +177,7 @@
[typeSwitch 'VariantType','arrayLengthSpecified'
['1' VariantBoolean [bit 'arrayLengthSpecified']
[optional int 32 'arrayLength' 'arrayLengthSpecified']
- [array bit 'value' count 'arrayLength == null ? 1 : arrayLength']
+ [array int 8 'value' count 'arrayLength == null ? 1 : arrayLength']
]
['2' VariantSByte [bit 'arrayLengthSpecified']
[optional int 32 'arrayLength' 'arrayLengthSpecified']
@@ -228,7 +233,7 @@
]
['15' VariantByteString [bit 'arrayLengthSpecified']
[optional int 32 'arrayLength' 'arrayLengthSpecified']
- [array PascalString 'value' count 'arrayLength == null ? 1 : arrayLength']
+ [array ByteStringArray 'value' count 'arrayLength == null ? 1 : arrayLength']
]
['16' VariantXmlElement [bit 'arrayLengthSpecified']
[optional int 32 'arrayLength' 'arrayLengthSpecified']
@@ -275,6 +280,8 @@
[array bit 'arrayDimensions' count 'noOfArrayDimensions == null ? 0 : noOfArrayDimensions']
]
+
+
[discriminatedType 'NodeId'
[reserved int 2 '0x00']
[simple NodeIdType 'nodeIdType']