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']