OPC Studio User's Guide and Reference
ReadValue(IEasyUAClient,UAEndpointDescriptor,UANodeDescriptor) Method
Example 



OpcLabs.EasyOpcUA Assembly > OpcLabs.EasyOpc.UA Namespace > IEasyUAClientExtension Class > ReadValue Method : ReadValue(IEasyUAClient,UAEndpointDescriptor,UANodeDescriptor) Method
The client object that will perform the operation.

This is typically the EasyUAClient object.

The value of this parameter cannot be null (Nothing in Visual Basic).

Endpoint descriptor. Identifies the OPC-UA server.

Because the UAEndpointDescriptor has implicit conversions from System.String and System.Uri, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a string (representing the endpoint URL, or a so-called OPC UA endpoint descriptor string), or a System.Uri object, in place of this parameter, and the corresponding endpoint descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can use the UAEndpointDescriptor.FromString or UAEndpointDescriptor.FromUri static method instead.

Also, because the OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement and OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement have an implicit conversion to UAEndpointDescriptor, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement (results from OPC UA discovery) in place of this parameter, and the corresponding endpoint descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can convert a (non-null) OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement to UAEndpointDescriptor using the OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement.ToUAEndpointDescriptor or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement.ToUAEndpointDescriptor method instead.

If you are using OPC Wizard (for server development), an implicit conversion from EasyUAServerCore can be used in the same way to simply pass the server object in place of this parameter, which will use its OpcLabs.EasyOpc.UA.EasyUAServerCore.EffectiveServerDescriptor property for the connection.

The value of this parameter cannot be null (Nothing in Visual Basic).

Node descriptor. Identifies the node in OPC server's address space.

Because the UANodeDescriptor has implicit conversions from OpcLabs.EasyOpc.UA.AddressSpace.UANodeId, OpcLabs.EasyOpc.UA.AddressSpace.UANodeElement, OpcLabs.EasyOpc.UA.Navigation.UABrowsePath and System.String, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a OpcLabs.EasyOpc.UA.AddressSpace.UANodeId object (representing the Id of the OPC UA node), a node element object (from OPC UA browsing), OpcLabs.EasyOpc.UA.Navigation.UABrowsePath object (representing OPC UA absolute browse path), or a string (with expanded node Id text) in place of this parameter, and the corresponding node descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can use the UANodeDescriptor.FromString, UANodeDescriptor.FromUABrowsePath, UANodeDescriptor.FromUANodeElement or UANodeDescriptor.FromUANodeId static method instead.

If you are using OPC Wizard (for server development), an implicit conversion from OpcLabs.EasyOpc.UA.NodeSpace.UAServerNode can be used in the same way to simply pass the server node in place of this parameter, which will use its OpcLabs.EasyOpc.UA.NodeSpace.UAServerNode.EffectiveNodeDescriptor property for the operation.

The value of this parameter cannot be null (Nothing in Visual Basic).

Reads an attribute's value using an endpoint descriptor and a node Id.
Syntax
'Declaration
 
<ExtensionAttribute()>
<CanBeNullAttribute()>
Public Overloads Shared Function ReadValue( _
   ByVal client As IEasyUAClient, _
   ByVal endpointDescriptor As UAEndpointDescriptor, _
   ByVal nodeDescriptor As UANodeDescriptor _
) As Object
'Usage
 
Dim client As IEasyUAClient
Dim endpointDescriptor As UAEndpointDescriptor
Dim nodeDescriptor As UANodeDescriptor
Dim value As Object
 
value = IEasyUAClientExtension.ReadValue(client, endpointDescriptor, nodeDescriptor)

Parameters

client
The client object that will perform the operation.

This is typically the EasyUAClient object.

The value of this parameter cannot be null (Nothing in Visual Basic).

endpointDescriptor
Endpoint descriptor. Identifies the OPC-UA server.

Because the UAEndpointDescriptor has implicit conversions from System.String and System.Uri, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a string (representing the endpoint URL, or a so-called OPC UA endpoint descriptor string), or a System.Uri object, in place of this parameter, and the corresponding endpoint descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can use the UAEndpointDescriptor.FromString or UAEndpointDescriptor.FromUri static method instead.

Also, because the OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement and OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement have an implicit conversion to UAEndpointDescriptor, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement (results from OPC UA discovery) in place of this parameter, and the corresponding endpoint descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can convert a (non-null) OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement to UAEndpointDescriptor using the OpcLabs.EasyOpc.UA.Discovery.UAApplicationElement.ToUAEndpointDescriptor or OpcLabs.EasyOpc.UA.Discovery.UADiscoveryElement.ToUAEndpointDescriptor method instead.

If you are using OPC Wizard (for server development), an implicit conversion from EasyUAServerCore can be used in the same way to simply pass the server object in place of this parameter, which will use its OpcLabs.EasyOpc.UA.EasyUAServerCore.EffectiveServerDescriptor property for the connection.

The value of this parameter cannot be null (Nothing in Visual Basic).

nodeDescriptor
Node descriptor. Identifies the node in OPC server's address space.

Because the UANodeDescriptor has implicit conversions from OpcLabs.EasyOpc.UA.AddressSpace.UANodeId, OpcLabs.EasyOpc.UA.AddressSpace.UANodeElement, OpcLabs.EasyOpc.UA.Navigation.UABrowsePath and System.String, in languages that support implicit conversion operators (such as C# or VB.NET), you can simply use a OpcLabs.EasyOpc.UA.AddressSpace.UANodeId object (representing the Id of the OPC UA node), a node element object (from OPC UA browsing), OpcLabs.EasyOpc.UA.Navigation.UABrowsePath object (representing OPC UA absolute browse path), or a string (with expanded node Id text) in place of this parameter, and the corresponding node descriptor will be constructed automatically. When the implicit conversion operators are not supported (such as with Python.NET), you can use the UANodeDescriptor.FromString, UANodeDescriptor.FromUABrowsePath, UANodeDescriptor.FromUANodeElement or UANodeDescriptor.FromUANodeId static method instead.

If you are using OPC Wizard (for server development), an implicit conversion from OpcLabs.EasyOpc.UA.NodeSpace.UAServerNode can be used in the same way to simply pass the server node in place of this parameter, which will use its OpcLabs.EasyOpc.UA.NodeSpace.UAServerNode.EffectiveNodeDescriptor property for the operation.

The value of this parameter cannot be null (Nothing in Visual Basic).

Return Value

If successful, the method returns the actual value of OPC attribute requested.

This method can return null (Nothing in Visual Basic).

Exceptions
ExceptionDescription

A null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument.

This is a usage error, i.e. it will never occur (the exception will not be thrown) in a correctly written program. Your code should not catch this exception.

The OPC UA operation has failed. This operation exception in uniformly used to allow common handling of various kinds of errors. The System.Exception.InnerException always contains information about the actual error cause.

This is an operation error that depends on factors external to your program, and thus cannot be always avoided. Your code must handle it appropriately.

Remarks

The status code must be 'good' for this method to succeed; otherwise, a OpcLabs.EasyOpc.UA.OperationModel.UAException is thrown.

You can obtain nodeDescriptor e.g. by calling one of the browsing methods on EasyUAClientCore object.

Only the attribute's value is returned (status code and timestamps are not returned). The status code must be 'good' for this method to succeed; otherwise, a OpcLabs.EasyOpc.UA.OperationModel.UAException is thrown.

This is an extension method (info: C#, VB.NET). In languages that have support for extensions methods (such as C# and VB.NET), you can use the extension method as if it were a regular method on the object that is its first parameter. In other languages (such as with Python.NET), you will call the extension as a static method, and pass it the object on which it acts as its first parameter.

Example
// This example shows how to read value of a single node, and display it.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    partial class ReadValue
    {
        public static void Overload1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Instantiate the client object.
            var client = new EasyUAClient();

            Console.WriteLine("Obtaining value of a node...");
            object value;
            try
            {
                value = client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853");
            }
            catch (UAException uaException)
            {
                Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
                return;
            }

            // Display results
            Console.WriteLine($"value: {value}");
        }
    }
}
# This example shows how to read value of a single node, and display it.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in PowerShell on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-PowerShell .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.OperationModel

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll"

[UAEndpointDescriptor]$endpointDescriptor =
    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
# or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
# or "https://opcua.demo-this.com:51212/UA/SampleServer/"

# Instantiate the client object.
$client = New-Object EasyUAClient

Write-Host "Obtaining value of a node..."
try {
    $value = $client.ReadValue($endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853")
}
catch [UAException] {
    Write-Host "*** Failure: $($PSItem.Exception.GetBaseException().Message)"
    return
}

# Display results
Write-Host "value: $($value)"
' This example shows how to read value of a single node, and display it.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Partial Friend Class ReadValue
        Public Shared Sub Overload1()

            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Instantiate the client object
            Dim client = New EasyUAClient()

            ' Obtain value of a node
            Dim value As Object
            Try
                value = client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853")
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            ' Display results
            Console.WriteLine("value: {0}", value)
        End Sub
    End Class
End Namespace
# This example shows how to read value of a single node, and display it.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

# Instantiate the client object.
client = EasyUAClient()

# Perform the operation.
try:
    value = IEasyUAClientExtension.ReadValue(client,
                                             endpointDescriptor,
                                             UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'))
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display results.
print('value: ', value, sep='')

print('Finished.')
// This example shows how to read a value from a single node that is an array of UInt16.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    partial class ReadValue
    {
        public static void ArrayOfUInt16()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Instantiate the client object
            var client = new EasyUAClient();

            Console.WriteLine("Obtaining value of a node...");
            int[] value;
            try
            {
                // UInt16 is returned as Int32, because UInt16 is not a CLS-compliant type (and is not supported in VB.NET).
                value = (int[])client.ReadValue(endpointDescriptor,
                    "nsu=http://test.org/UA/Data/ ;ns=2;i=10932");   // /Data.Dynamic.Array.UInt16Value
            }
            catch (UAException uaException)
            {
                Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
                return;
            }

            if (!(value is null))
            {
                Console.WriteLine(value[0]);
                Console.WriteLine(value[1]);
                Console.WriteLine(value[2]);
            }

            Console.WriteLine("Finished.");
        }
    }
}
' This example shows how to read a value from a single node that is an array of UInt16.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Partial Friend Class ReadValue
        Public Shared Sub ArrayOfUInt16()

            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Instantiate the client object
            Dim client = New EasyUAClient()

            Console.WriteLine("Obtaining value of a node...")
            Dim value As Int32()
            Try
                ' UInt16 is returned as Int32, because UInt16 is not a CLS-compliant type (and is not supported in VB.NET).
                ' // /Data.Dynamic.Array.UInt16Value
                value = CType(client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;ns=2;i=10932"), Int32())
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            If Not IsNothing(value) Then
                Console.WriteLine(value(0))
                Console.WriteLine(value(1))
                Console.WriteLine(value(2))
            End If
        End Sub
    End Class
End Namespace
# This example shows how to read a value from a single node that is an array of UInt16.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


# Instantiate the client object.
client = EasyUAClient()

print('Obtaining value of a node...')
try:
    # UInt16 is returned as Int32, because UInt16 is not a CLS-compliant type (and is not supported in VB.NET).
    value = IEasyUAClientExtension.ReadValue(client,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor('nsu=http://test.org/UA/Data/ ;ns=2;i=10932')) # /Data.Dynamic.Array.UInt16Value
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display results.
if value is not None:
    print(value[0])
    print(value[1])
    print(value[2])

print()
print('Finished.')
// This example shows how to read value of server's NamespaceArray, and display the namespace URIs in it.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    partial class ReadValue
    {
        public static void NamespaceArray()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Instantiate the client object
            var client = new EasyUAClient();

            // Perform the operation: Obtain value of a node
            object value;
            try
            {
                value = client.ReadValue(endpointDescriptor, UAVariableIds.Server_NamespaceArray);  // i=2255
            }
            catch (UAException uaException)
            {
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                return;
            }

            if (!(value is string[] arrayValue))
            {
                Console.WriteLine("*** Not a string array");
                return;
            }

            // Display results
            for (int i = 0; i < arrayValue.Length; i++)
                Console.WriteLine($"{i}: {arrayValue[i]}");
        }


        // Example output:
        //
        //0: http://opcfoundation.org/UA/
        //1: urn:DEMO-5:UA Sample Server
        //2: http://test.org/UA/Data/
        //3: http://test.org/UA/Data//Instance
        //4: http://opcfoundation.org/UA/Boiler/
        //5: http://opcfoundation.org/UA/Boiler//Instance
        //6: http://opcfoundation.org/UA/Diagnostics
        //7: http://samples.org/UA/memorybuffer
        //8: http://samples.org/UA/memorybuffer/Instance
    }
}
' This example shows how to read value of server's NamespaceArray, and display the namespace URIs in it.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Partial Friend Class ReadValue
        Public Shared Sub NamespaceArray()

            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Perform the operation: Obtain value of a node
            Dim client = New EasyUAClient()

            ' Obtain value of a node
            Dim value As Object
            Try
                value = client.ReadValue(endpointDescriptor, UAVariableIds.Server_NamespaceArray) ' i = 2255
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            If TypeOf value IsNot String() Then
                Console.WriteLine("*** Not a string array")
                Exit Sub
            End If

            Dim arrayValue() As String = CType(value, String())

            ' Display results
            For i = 0 To arrayValue.Length - 1
                Console.WriteLine($"{i}: {arrayValue(i)}")
            Next i
        End Sub

        ' Example output
        '
        '0: http://opcfoundation.org/UA/
        '1: urn:DEMO-5:UA Sample Server
        '2: http://test.org/UA/Data/
        '3: http://test.org/UA/Data'Instance
        '4: http://opcfoundation.org/UA/Boiler/
        '5: http://opcfoundation.org/UA/Boiler'Instance
        '6: http://opcfoundation.org/UA/Diagnostics
        '7: http://samples.org/UA/memorybuffer
        '8: http://samples.org/UA/memorybuffer/Instance
    End Class
End Namespace
# This example shows how to read value of server's NamespaceArray, and display the namespace URIs in it.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.OperationModel import *


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

# Instantiate the client object.
client = EasyUAClient()

# Perform the operation: Obtain value of a node.
try:
    value = IEasyUAClientExtension.ReadValue(client,
                                             endpointDescriptor,
                                             UANodeDescriptor(UAVariableIds.Server_NamespaceArray)) # i=2255
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

if not isinstance(value, Array):
    print('*** Not an array')
    exit()
arrayValue = value

# Display results.
for i, element in enumerate(arrayValue):
    print(i, ': ', element, sep='')

print()
print('Finished.')
// This example shows how to repeatedly read value of a single node, and display it.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Threading;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    partial class ReadValue
    {
        public static void Repeated()
        {
            const string endpointDescriptorUrlString =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            const string nodeIdExpandedText = "nsu=http://test.org/UA/Data/ ;i=10221";
            // Example settings with Softing dataFEED OPC Suite:
            //  endpointDescriptorUrlString = "opc.tcp://localhost:4980/Softing_dataFEED_OPC_Suite_Configuration1";
            //  nodeIdExpandedText = "nsu=Local%20Items ;s=Local Items.EAK_Test1.EAK_Testwert1_I4";

            // Instantiate the client object.
            var client = new EasyUAClient();

            for (int i = 1; i <= 60; i++)
            {
                Console.Write($"@{DateTime.Now}: ");

                // Obtain value of a node
                object value;
                try
                {
                    value = client.ReadValue(endpointDescriptorUrlString, nodeIdExpandedText);
                }
                catch (UAException uaException)
                {
                    Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
                    return;
                }

                // Display results
                Console.WriteLine($"Read {value}");

                //
                Thread.Sleep(1000);
            }
        }
    }
}
' This example shows how to repeatedly read value of a single node, and display it.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System.Threading
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Partial Friend Class ReadValue
        Public Shared Sub Repeated()

            ' Define which server we will work with.
            Const endpointDescriptorUrlString As String =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            Const nodeIdExpandedText As String = "nsu=http://test.org/UA/Data/ ;i=10221"
            ' Example settings with Softing dataFEED OPC Suite:
            '  endpointDescriptorUrlString = "opc.tcp://localhost:4980/Softing_dataFEED_OPC_Suite_Configuration1";
            '  nodeIdExpandedText = "nsu=Local%20Items ;s=Local Items.EAK_Test1.EAK_Testwert1_I4";

            ' Instantiate the client object.
            Dim client = New EasyUAClient()

            For i = 1 To 60
                Console.Write($"@{DateTime.Now}: ")

                ' Obtain value of a node
                Dim value As Object
                Try
                    value = client.ReadValue(endpointDescriptorUrlString, nodeIdExpandedText)
                Catch uaException As UAException
                    Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}")
                    Exit Sub
                End Try

                ' Display results
                Console.WriteLine($"Read {value}")

                '
                Thread.Sleep(1000)
            Next i
        End Sub
    End Class
End Namespace
# This example shows how to repeatedly read value of a single node, and display it.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
from datetime import datetime
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'
nodeIdExpandedText = 'nsu=http://test.org/UA/Data/ ;i=10221'
# Example settings with Softing dataFEED OPC Suite:
# 'endpointDescriptorUrlString = "'opc.tcp://localhost:4980/Softing_dataFEED_OPC_Suite_Configuration1'
# 'nsu=Local%20Items ;s=Local Items.EAK_Test1.EAK_Testwert1_I4'

# Instantiate the client object.
client = EasyUAClient()

for i in range(1, 61):
    print('@', datetime.now(), ': ', sep='', end='')

    # Obtain value of a node.
    try:
        value = IEasyUAClientExtension.ReadValue(client, endpointDescriptor, UANodeDescriptor(nodeIdExpandedText))
    except UAException as uaException:
        print('*** Failure: ' + uaException.GetBaseException().Message)
        exit()

    # Display results.
    print('Read ', value, sep='')

    time.sleep(1)

print()
print('Finished.')
// Shows how to process a data type, displaying some of its properties, recursively.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Linq;
using OpcLabs.BaseLib.DataTypeModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.ComplexData;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.ComplexData._DataType
{
    class Kind
    {
        public static void Main1()
        {
            // Define which server and node we will work with.
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            UANodeDescriptor nodeDescriptor = 
                "nsu=http://test.org/UA/Data/ ;i=10239"; // [ObjectsFolder]/Data.Static.Scalar.StructureValue

            // Instantiate the client object.
            var client = new EasyUAClient();

            // Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
            UAGenericObject genericObject;
            try
            {
                genericObject = (UAGenericObject)client.ReadValue(endpointDescriptor, nodeDescriptor);
            }
            catch (UAException uaException)
            {
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                return;
            }
            // The data type is in the GenericData.DataType property of the UAGenericObject.
            DataType dataType = genericObject.GenericData.DataType;

            // Process the data type. We will inspect some of its properties, and dump them.
            ProcessDataType(dataType, maximumDepth: 3);
        }
        

        // Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with, 
        // it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
        public static void ProcessDataType(DataType dataType, int maximumDepth)
        {
            if (maximumDepth == 0)
                return;

            Console.WriteLine();
            Console.WriteLine("dataType.Name: {0}", dataType.Name);

            switch (dataType.Kind)
            {
                case DataTypeKind.Enumeration:
                    Console.WriteLine("The data type is an enumeration.");
                    var enumerationDataType = (EnumerationDataType) dataType;
                    Console.WriteLine("It has {0} enumeration members.", enumerationDataType.EnumerationMembers.Count);
                    Console.WriteLine("The names of the enumeration members are: {0}.",
                        String.Join(", ", enumerationDataType.EnumerationMembers.Select(member => member.Name)));
                    // Here you can process the members, or inspect SizeInBits etc.
                    break;

                case DataTypeKind.Opaque:
                    Console.WriteLine("The data type is opaque.");
                    var opaqueDataType = (OpaqueDataType) dataType;
                    Console.WriteLine("Its size is {0} bits.", opaqueDataType.SizeInBits);
                    // There isn't much more you can learn about an opaque data type (well, it may have Description and 
                    // other common members). It is, after all, opaque...
                    break;

                case DataTypeKind.Primitive:
                    Console.WriteLine("The data type is primitive.");
                    var primitiveDataType = (PrimitiveDataType) dataType;
                    Console.WriteLine("Its .NET value type is \"{0}\".", primitiveDataType.ValueType);
                    // There isn't much more you can learn about the primitive data type.
                    break;

                case DataTypeKind.Sequence:
                    Console.WriteLine("The data type is a sequence.");
                    var sequenceDataType = (SequenceDataType) dataType;
                    Console.WriteLine("Its length is {0} (-1 means that the length can vary).", sequenceDataType.Length);

                    Console.WriteLine("A dump of the element data type follows.");
                    ProcessDataType(sequenceDataType.ElementDataType, maximumDepth - 1);
                    break;

                case DataTypeKind.Structured:
                    Console.WriteLine("The data type is structured.");
                    var structuredDataType = (StructuredDataType) dataType;
                    Console.WriteLine("It has {0} data fields.", structuredDataType.DataFields.Count);
                    Console.WriteLine("The names of the data fields are: {0}.",
                        String.Join(", ", structuredDataType.DataFields.Select(field => field.Name)));

                    Console.WriteLine("A dump of each of the data fields follows.");
                    foreach (DataField dataField in structuredDataType.DataFields)
                    {
                        Console.WriteLine();
                        Console.WriteLine("dataField.Name: {0}", dataField.Name);
                        // Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might 
                        // be of interest, but we are not dumping them here.
                        ProcessDataType(dataField.DataType, maximumDepth - 1);
                    }
                    break;

                case DataTypeKind.Union:
                    Console.WriteLine("The data type is union.");
                    var unionDataType = (UnionDataType)dataType;
                    Console.WriteLine("It has {0} data fields.", unionDataType.DataFields.Count);
                    Console.WriteLine("The names of the data fields are: {0}.",
                        String.Join(", ", unionDataType.DataFields.Select(field => field.Name)));
                    break;
            }
        }
    }
}
' Shows how to process a data type, displaying some of its properties, recursively.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports System.Linq
Imports OpcLabs.BaseLib.DataTypeModel
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.ComplexData
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace ComplexData._DataType

    Friend Class Kind

        Public Shared Sub Main1()

            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Define which node we will work with.
            Dim nodeDescriptor As UANodeDescriptor = _
                "nsu=http://test.org/UA/Data/ ;i=10239"  ' [ObjectsFolder]/Data.Static.Scalar.StructureValue

            ' Instantiate the client object.
            Dim client = New EasyUAClient

            ' Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
            Dim genericObject As UAGenericObject
            Try
                genericObject = CType(client.ReadValue(endpointDescriptor, nodeDescriptor), UAGenericObject)
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try
            ' The data type is in the GenericData.DataType property of the UAGenericObject.

            Dim dataType As DataType = genericObject.GenericData.DataType

            ' Process the data type. We will inspect some of its properties, and dump them.
            ProcessDataType(dataType, maximumDepth:=2)
        End Sub


        ' Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with, 
        ' it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
        Public Shared Sub ProcessDataType(dataType As DataType, ByVal maximumDepth As Integer)
            If (maximumDepth = 0) Then
                Return
            End If

            Console.WriteLine()
            Console.WriteLine("dataType.Name: {0}", dataType.Name)

            Select Case (dataType.Kind)
                Case DataTypeKind.Enumeration
                    Console.WriteLine("The data type is an enumeration.")
                    Dim enumerationDataType = CType(dataType, EnumerationDataType)
                    Console.WriteLine("It has {0} enumeration members.", enumerationDataType.EnumerationMembers.Count)
                    Console.WriteLine("The names of the enumeration members are: {0}.", _
                                      String.Join(", ", enumerationDataType.EnumerationMembers.Select(Function(member) member.Name)))
                    ' Here you can process the members, or inspect SizeInBits etc.

                Case DataTypeKind.Opaque
                    Console.WriteLine("The data type is opaque.")
                    Dim opaqueDataType = CType(dataType, OpaqueDataType)
                    Console.WriteLine("Its size is {0} bits.", opaqueDataType.SizeInBits)
                    ' There isn't much more you can learn about an opaque data type (well, it may have Description and 
                    ' other common members). It is, after all, opaque...

                Case DataTypeKind.Primitive
                    Console.WriteLine("The data type is primitive.")
                    Dim primitiveDataType = CType(dataType, PrimitiveDataType)
                    Console.WriteLine("Its .NET value type is ""{0}"".", primitiveDataType.ValueType)
                    ' There isn't much more you can learn about the primitive data type.

                Case DataTypeKind.Sequence
                    Console.WriteLine("The data type is a sequence.")
                    Dim sequenceDataType = CType(dataType, SequenceDataType)
                    Console.WriteLine("Its length is {0} (-1 means that the length can vary).", sequenceDataType.Length)
                    Console.WriteLine("A dump of the element data type follows.")
                    ProcessDataType(sequenceDataType.ElementDataType, (maximumDepth - 1))

                Case DataTypeKind.Structured
                    Console.WriteLine("The data type is structured.")
                    Dim structuredDataType = CType(dataType, StructuredDataType)
                    Console.WriteLine("It has {0} data fields.", structuredDataType.DataFields.Count)
                    Console.WriteLine("The names of the data fields are: {0}.", _
                                      String.Join(", ", structuredDataType.DataFields.Select(Function(field) field.Name)))
                    Console.WriteLine("A dump of each of the data fields follows.")

                    For Each dataField As DataField In structuredDataType.DataFields
                        Console.WriteLine()
                        Console.WriteLine("dataField.Name: {0}", dataField.Name)
                        ' Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might 
                        ' be of interest but we are not dumping them here.
                        ProcessDataType(dataField.DataType, (maximumDepth - 1))
                    Next

                Case DataTypeKind.Union
                    Console.WriteLine("The data type is union.")
                    Dim unionDataType = CType(dataType, UnionDataType)
                    Console.WriteLine("It has {0} data fields.", unionDataType.DataFields.Count)
                    Console.WriteLine("The names of the data fields are: {0}.",
                                      String.Join(", ", unionDataType.DataFields.Select(Function(field) field.Name)))

            End Select

        End Sub
    End Class
End Namespace
// Shows how to process a data type, displaying some of its properties, recursively.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

class procedure Kind.Main;
var
  Client: _EasyUAClient;
  DataType: OpcLabs_BaseLib_TLB._DataType;
  EndpointDescriptor: string;
  GenericObject: _UAGenericObject;
  NodeDescriptor: string;
begin
  // Define which server and node we will work with.
  EndpointDescriptor := 
    //'http://opcua.demo-this.com:51211/UA/SampleServer';
    //'https://opcua.demo-this.com:51212/UA/SampleServer/';
    'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
  NodeDescriptor := 'nsu=http://test.org/UA/Data/ ;i=10239';  // [ObjectsFolder]/Data.Static.Scalar.StructureValue

  // Instantiate the client object
  Client := CoEasyUAClient.Create;

  // Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.

  try
    GenericObject := IUnknown(Client.ReadValue(EndpointDescriptor, NodeDescriptor)) as _UAGenericObject;
  except
    on E: EOleException do
    begin
      WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
      Exit;
    end;
  end;

  // The data type is in the GenericData.DataType property of the UAGenericObject.
  DataType := genericObject.GenericData.DataType;

  // Process the data type. We will inspect some of its properties, and dump them.
  ProcessDataType(DataType, 2);
end;

// Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with,
// it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
class procedure Kind.ProcessDataType(DataType: OpcLabs_BaseLib_TLB._DataType; MaximumDepth: Cardinal);
var
  Count: Cardinal;
  DataField: _DataField;
  Element: OleVariant;
  ElementEnumerator: IEnumVARIANT;
  EnumerationMember: _EnumerationMember;
  EnumerationDataType: _EnumerationDataType;
  FieldNames: string;
  First: boolean;
  MemberNames: string;
  OpaqueDataType: _OpaqueDataType;
  PrimitiveDataType: _PrimitiveDataType;
  SequenceDataType: _SequenceDataType;
  StructuredDataType: _StructuredDataType;
  TypeName: WideString;
begin
  if MaximumDepth = 0 then
    Exit;

  WriteLn;
  WriteLn('dataType.Name: ', DataType.Name);

  case DataType.Kind of
    DataTypeKind_Enumeration:
      begin
        WriteLn('The data type is an enumeration.');
        EnumerationDataType := DataType as _EnumerationDataType;
        WriteLn(Format('It has %s enumeration members.', [EnumerationDataType.EnumerationMembers.Count]));
        ElementEnumerator := EnumerationDataType.EnumerationMembers.GetEnumerator;
        MemberNames := '';
        First := True;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          EnumerationMember := IUnknown(Element) as _EnumerationMember;
          if First then
            First := False
          else
            MemberNames := MemberNames + ', ';
          MemberNames := MemberNames + EnumerationMember.Name;
        end;
        WriteLn(Format('The names of the enumeration members are: %s.', [MemberNames]));
        // Here you can process the members, or inspect SizeInBits etc.
      end;
    DataTypeKind_Opaque:
      begin
        WriteLn('The data type is opaque.');
        OpaqueDataType := DataType as _OpaqueDataType;
        WriteLn(Format('Its size is %s bits.', [OpaqueDataType.SizeInBits]));
        // There isn't much more you can learn about an opaque data type (well, it may have Description and
        // other common members). It is, after all, opaque...
      end;
    DataTypeKind_Primitive:
      begin
        WriteLn('The data type is primitive.');
        PrimitiveDataType := DataType as _PrimitiveDataType;
        PrimitiveDataType.ValueType.Get_ToString(TypeName);
        WriteLn(Format('Its .NET value type is "%s".', [TypeName]));
        // There isn't much more you can learn about the primitive data type.
      end;
    DataTypeKind_Sequence:
      begin
        WriteLn('The data type is a sequence.');
        SequenceDataType := DataType as _SequenceDataType;
        WriteLn(Format('Its length is %s (-1 means that the length can vary).', [SequenceDataType.Length.ToString]));
        WriteLn('A dump of the element data type follows.');
        ProcessDataType(SequenceDataType.ElementDataType, MaximumDepth - 1);
      end;
    DataTypeKind_Structured:
      begin
        WriteLn('The data type is structured.');
        StructuredDataType := DataType as _StructuredDataType;
        WriteLn(Format('It has %s data fields.', [StructuredDataType.DataFields.Count.ToString]));
        ElementEnumerator := StructuredDataType.DataFields.GetEnumerator;
        FieldNames := '';
        First := True;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          if First then
            First := False
          else
            FieldNames := FieldNames + ', ';
          FieldNames := FieldNames + Element.Name;
        end;
        WriteLn(Format('The names of the data fields are: %s.', [FieldNames]));

        WriteLn('A dump of each of the data fields follows.');
        ElementEnumerator := StructuredDataType.DataFields.GetEnumerator;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          DataField := IUnknown(Element) as _DataField;
          WriteLn;
          WriteLn(Format('dataField.Name: %s', [DataField.Name]));
          // Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
          // be of interest but we are not dumping them here.
          ProcessDataType(DataField.DataType, MaximumDepth - 1);
        end;
    end;
  end;

end;

# Shows how to process a data type, displaying some of its properties, recursively.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from System import *
from OpcLabs.BaseLib.DataTypeModel import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


def processDataType(dataType, maximumDepth):
    if maximumDepth == 0:
        print('* Reached maximum depth *')
        return

    print()
    print('dataType.Name: ', dataType.Name, sep='')

    if dataType.Kind == DataTypeKind.Enumeration:
        print('The data type is an enumeration.')
        enumerationDataType = dataType
        print('It has ', enumerationDataType.EnumerationMembers.Count, ' enumeration members.', sep='')
        print('The names of the enumeration members are: ', end='')
        for i, member in enumerate(enumerationDataType.EnumerationMembers):
            if i != 0:
                print(', ', end='')
            print(member.Name, end='')
        print('.')
        # Here you can process the members, or inspect SizeInBits etc.

    elif dataType.Kind == DataTypeKind.Opaque:
        print('The data type is opaque.')
        opaqueDataType = dataType
        print('Its size is ', opaqueDataType.SizeInBits, ' bits.', sep='')
        # There isn't much more you can learn about an opaque data type (well, it may have Description and
        # other common members). It is, after all, opaque...

    elif dataType.Kind == DataTypeKind.Primitive:
        print('The data type is primitive.')
        primitiveDataType = dataType
        print('Its .NET value type is "', primitiveDataType.ValueType, '".', sep='')
        # There isn't much more you can learn about the primitive data type.

    elif dataType.Kind == DataTypeKind.Sequence:
        print('The data type is a sequence.')
        sequenceDataType = dataType
        print('Its length is ', sequenceDataType.Length, ' (-1 means that the length can vary).', sep='')

        print('A dump of the element data type follows.')
        processDataType(sequenceDataType.ElementDataType, maximumDepth - 1)

    elif dataType.Kind == DataTypeKind.Structured:
        print('The data type is structured.')
        structuredDataType = dataType
        print('It has ', structuredDataType.DataFields.Count, ' data fields.', sep='')
        print('The names of the data fields are: ', end='')
        for i, field in enumerate(structuredDataType.DataFields):
            if i != 0:
                print(', ', end='')
            print(field.Name, end='')
        print('.')

        print('A dump of each of the data fields follows.')
        for dataField in structuredDataType.DataFields:
            print()
            print('dataField.Name: ', dataField.Name, sep='')
            # Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
            # be of interest, but we are not dumping them here.
            processDataType(dataField.DataType, maximumDepth - 1)

    elif dataType.Kind == DataTypeKind.Union:
        print('The data type is union.')
        unionDataType = dataType
        print('It has ', unionDataType.DataFields.Count, ' data fields.', sep='')
        print('The names of the data fields are: ', end='')
        for i, field in enumerate(unionDataType.DataFields):
            if i != 0:
                print(', ', end='')
            print(field.Name, end='')
        print('.')


# Define which server and node we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

# [ObjectsFolder]/Data.Static.Scalar.StructureValue
nodeDescriptor = UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239')

# Instantiate the client object.
client = EasyUAClient()

# Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
try:
    print('Reading...')
    genericObject = IEasyUAClientExtension.ReadValue(client, endpointDescriptor, nodeDescriptor)
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()
print('Reading successful.')
# The data type is in the GenericData.DataType property of the UAGenericObject.
dataType = genericObject.GenericData.DataType

# Process the data type. We will inspect some of its properties, and dump them.
processDataType(dataType, 3)

print()
print('Finished.')
// This example shows that either a single client object, or multiple client objects can be used to read values from two
// servers.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    partial class ReadValue
    {
        public static void MultipleServers()
        {
            // Define which servers we will work with.
            UAEndpointDescriptor endpointDescriptor1 =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            UAEndpointDescriptor endpointDescriptor2 =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";



            // Part 1: Use a single client object.
            // This demonstrates the fact that the client objects do *not* represent connections to individual servers.
            // Instead, they are able to maintain connections to multiple servers internally. API method calls on the client
            // object include the server's endpoint descriptor in their arguments, so you can specify a different endpoint
            // with each operation.
            Console.WriteLine();

            // Instantiate the client object
            var client = new EasyUAClient();

            Console.WriteLine("Obtaining values of nodes using a single client object...");
            object value1, value2;
            try
            {
                // The node Id we are reading returns the product name of the server.
                value1 = client.ReadValue(endpointDescriptor1, "nsu=http://opcfoundation.org/UA/ ;i=2261");
                value2 = client.ReadValue(endpointDescriptor2, "nsu=http://opcfoundation.org/UA/ ;i=2261");
                // Note: For efficiency (reading from the two servers in parallel), it would be better to use the
                // ReadMultipleValues method here, but this example is made for code clarity.
            }
            catch (UAException uaException)
            {
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                return;
            }

            // Display results
            Console.WriteLine("value1: {0}", value1);
            Console.WriteLine("value2: {0}", value2);



            // Part 2: Use multiple client objects.
            // This demonstrates the fact that it is also possible to use multiple client objects, and on the OPC side, the
            // behavior will be the same as if you had used a single client object. Multiple client objects consume somewhat
            // more resources on the client side, but they come handy if, for example,
            // - you cannot easily pass around the single pre-created client object to various parts in your code, or
            // - you are using subscriptions, and you want to hook separate event handlers for different purposes, or
            // - you need to set something in the instance parameters of the client object differently for different
            // connections.
            Console.WriteLine();

            // Instantiate the client objects.
            var client1 = new EasyUAClient();
            var client2 = new EasyUAClient();

            Console.WriteLine("Obtaining values of nodes using multiple client objects...");
            try
            {
                // The node Id we are reading returns the product name of the server.
                value1 = client1.ReadValue(endpointDescriptor1, "nsu=http://opcfoundation.org/UA/ ;i=2261");
                value2 = client2.ReadValue(endpointDescriptor2, "nsu=http://opcfoundation.org/UA/ ;i=2261");
            }
            catch (UAException uaException)
            {
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                return;
            }

            // Display results
            Console.WriteLine("value1: {0}", value1);
            Console.WriteLine("value2: {0}", value2);



            // Example output:
            //
            //Obtaining values of nodes using a single client object...
            //value1: OPC UA SDK Samples
            //value2: OPC UA Workshop Samples
            //
            //Obtaining values of nodes using multiple client objects...
            //value1: OPC UA SDK Samples
            //value2: OPC UA Workshop Samples
        }
    }
}
' This example shows that either a single client object, or multiple client objects can be used to read values from two
' servers.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports Newtonsoft.Json.Linq
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Partial Friend Class ReadValue
        Public Shared Sub MultipleServers()

            ' Define which server we will work with.
            Dim endpointDescriptor1 As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            Dim endpointDescriptor2 As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"


            ' Part 1: Use a single client object.
            ' This demonstrates the fact that the client objects do *not* represent connections to individual servers.
            ' Instead, they are able to maintain connections to multiple servers internally. API method calls on the client
            ' object include the server's endpoint descriptor in their arguments, so you can specify a different endpoint
            ' with each operation.
            Console.WriteLine()

            ' Instantiate the client object
            Dim client = New EasyUAClient()

            Console.WriteLine("Obtaining values of nodes using a single client object...")
            ' Obtain value of a node
            Dim value1 As Object
            Dim value2 As Object
            Try
                ' The node Id we are reading returns the product name of the server.
                value1 = client.ReadValue(endpointDescriptor1, "nsu=http://opcfoundation.org/UA/ ;i=2261")
                value2 = client.ReadValue(endpointDescriptor2, "nsu=http://opcfoundation.org/UA/ ;i=2261")
                ' Note: For efficiency(reading from the two servers in parallel), it would be better to use the
                ' ReadMultipleValues method here, but this example is made for code clarity.
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            ' Display results
            Console.WriteLine("value1: {0}", value1)
            Console.WriteLine("value2: {0}", value2)


            ' Part 2: Use multiple client objects.
            ' This demonstrates the fact that it is also possible to use multiple client objects, and on the OPC side, the
            ' behavior will be the same as if you had used a single client object. Multiple client objects consume somewhat
            ' more resources on the client side, but they come handy if, for example,
            ' - you cannot easily pass around the single pre-created client object to various parts in your code, or
            ' - you are using subscriptions, and you want to hook separate event handlers for different purposes, or
            ' - you need to set something in the instance parameters of the client object differently for different
            ' connections.
            Console.WriteLine()

            ' Instantiate the client objects.
            Dim client1 = New EasyUAClient()
            Dim client2 = New EasyUAClient()

            Console.WriteLine("Obtaining values of nodes using multiple client objects...")
            Try
                ' The node Id we are reading returns the product name of the server.
                value1 = client1.ReadValue(endpointDescriptor1, "nsu=http://opcfoundation.org/UA/ ;i=2261")
                value2 = client2.ReadValue(endpointDescriptor2, "nsu=http://opcfoundation.org/UA/ ;i=2261")
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            ' Display results
            Console.WriteLine("value1: {0}", value1)
            Console.WriteLine("value2: {0}", value2)


            ' Example output
            '
            'Obtaining values of nodes using a single client object...
            'value1: Opc UA SDK Samples
            'value2: Opc UA Workshop Samples
            '
            'Obtaining values of nodes using multiple client objects...
            'value1: Opc UA SDK Samples
            'value2: Opc UA Workshop Samples
        End Sub
    End Class
End Namespace
# This example shows that either a single client object, or multiple client objects can be used to read values from two
# servers.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


# Define which servers we will work with.
endpointDescriptor1 = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'
endpointDescriptor2 = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer')


# Part 1: Use a single client object.
# This demonstrates the fact that the client objects do *not* represent connections to individual servers.
# Instead, they are able to maintain connections to multiple servers internally. API method calls on the client
# object include the server's endpoint descriptor in their arguments, so you can specify a different endpoint
# with each operation.
print()

# Instantiate the client object.
client = EasyUAClient()

print('Obtaining values of nodes using a single client object...')
try:
    # The node Id we are reading returns the product name of the server.
    value1 = IEasyUAClientExtension.ReadValue(client,
                                              endpointDescriptor1,
                                              UANodeDescriptor('nsu=http://opcfoundation.org/UA/ ;i=2261'))
    value2 = IEasyUAClientExtension.ReadValue(client,
                                              endpointDescriptor2,
                                              UANodeDescriptor('nsu=http://opcfoundation.org/UA/ ;i=2261'))
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display results.
print('value1: ', value1, sep='')
print('value2: ', value2, sep='')


# Part 2: Use multiple client objects.
# This demonstrates the fact that it is also possible to use multiple client objects, and on the OPC side, the
# behavior will be the same as if you had used a single client object. Multiple client objects consume somewhat
# more resources on the client side, but they come handy if, for example,
# - you cannot easily pass around the single pre-created client object to various parts in your code, or
# - you are using subscriptions, and you want to hook separate event handlers for different purposes, or
# - you need to set something in the instance parameters of the client object differently for different
# connections.
print()

# Instantiate the client objects.
client1 = EasyUAClient()
client2 = EasyUAClient()

print('Obtaining values of nodes using multiple client objects...')
try:
    # The node Id we are reading returns the product name of the server.
    value1 = IEasyUAClientExtension.ReadValue(client1,
                                              endpointDescriptor1,
                                              UANodeDescriptor('nsu=http://opcfoundation.org/UA/ ;i=2261'))
    value2 = IEasyUAClientExtension.ReadValue(client2,
                                              endpointDescriptor2,
                                              UANodeDescriptor('nsu=http://opcfoundation.org/UA/ ;i=2261'))
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display results.
print('value1: ', value1, sep='')
print('value2: ', value2, sep='')


print()
print('Finished.')
Requirements

Target Platforms: .NET Framework: Windows 10 (selected versions), Windows 11 (selected versions), Windows Server 2016, Windows Server 2022; .NET: Linux, macOS, Microsoft Windows

See Also