QuickOPC User's Guide and Reference
UAModelNodeDescriptor Class
Members  Example 



OpcLabs.EasyOpcUA Assembly > OpcLabs.EasyOpc.UA.InformationModel Namespace : UAModelNodeDescriptor Class
Identifies a node in OPC UA information model.
Object Model
UAModelNodeDescriptor ClassUAEndpointDescriptor ClassUANodeDescriptor ClassUAModelNodeDescriptor Class
Syntax
'Declaration
 
<ComDefaultInterfaceAttribute(OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor)>
<ComVisibleAttribute(True)>
<GuidAttribute("A5D29221-DD3E-4557-B253-1F5FE49E5441")>
<TypeConverterAttribute(System.ComponentModel.ExpandableObjectConverter)>
<CLSCompliantAttribute(True)>
<ValueControlAttribute("OpcLabs.BaseLib.Forms.Common.ObjectSerializationControl, OpcLabs.BaseLibForms, Version=5.72.465.1, Culture=neutral, PublicKeyToken=6faddca41dacb409", 
   DefaultReadWrite=False, 
   Export=True, 
   PageId=10001)>
<SerializableAttribute()>
Public Class UAModelNodeDescriptor 
   Inherits OpcLabs.BaseLib.Info
   Implements LINQPad.ICustomMemberProvider, OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor, System.ICloneable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable 
'Usage
 
Dim instance As UAModelNodeDescriptor
[ComDefaultInterface(OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor)]
[ComVisible(true)]
[Guid("A5D29221-DD3E-4557-B253-1F5FE49E5441")]
[TypeConverter(System.ComponentModel.ExpandableObjectConverter)]
[CLSCompliant(true)]
[ValueControl("OpcLabs.BaseLib.Forms.Common.ObjectSerializationControl, OpcLabs.BaseLibForms, Version=5.72.465.1, Culture=neutral, PublicKeyToken=6faddca41dacb409", 
   DefaultReadWrite=false, 
   Export=true, 
   PageId=10001)]
[Serializable()]
public class UAModelNodeDescriptor : OpcLabs.BaseLib.Info, LINQPad.ICustomMemberProvider, OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor, System.ICloneable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable  
[ComDefaultInterface(OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor)]
[ComVisible(true)]
[Guid("A5D29221-DD3E-4557-B253-1F5FE49E5441")]
[TypeConverter(System.ComponentModel.ExpandableObjectConverter)]
[CLSCompliant(true)]
[ValueControl("OpcLabs.BaseLib.Forms.Common.ObjectSerializationControl, OpcLabs.BaseLibForms, Version=5.72.465.1, Culture=neutral, PublicKeyToken=6faddca41dacb409", 
   DefaultReadWrite=false, 
   Export=true, 
   PageId=10001)]
[Serializable()]
public ref class UAModelNodeDescriptor : public OpcLabs.BaseLib.Info, LINQPad.ICustomMemberProvider, OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.EasyOpc.UA.InformationModel.ComTypes._UAModelNodeDescriptor, System.ICloneable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable  
Remarks

The model node descriptor is basically a combination of an endpoint descriptor and a node descriptor.

Example

.NET

COM

.NET

COM

// Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.

using System;
using Microsoft.Extensions.DependencyInjection;
using OpcLabs.BaseLib.DataTypeModel;
using OpcLabs.BaseLib.OperationModel.Generic;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.InformationModel;
using OpcLabs.EasyOpc.UA.Plugins.ComplexData;

namespace UADocExamples.ComplexData._IEasyUAClientComplexData
{
    class ResolveDataType
    {
        public static void Main1()
        {
            // Define which server 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/"

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

            // Obtain the data type ID.
            //
            // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
            // attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface.
            // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract
            // data type, and the actual values are then sub-types of this base data type. This abstract data type does not
            // have any encodings associated with it and it is therefore not possible to extract its description from the
            // server. We therefore use a hard-coded data type ID for one of the sub-types in this example.
            //
            // The code to obtain the data type ID for given node would normally look like this:
            //    UANodeId dataTypeId = client.ReadDataType(
            //        endpointDescriptor,
            //        "nsu=http://test.org/UA/Data/ ;i=10239");    // [ObjectsFolder]/Data.Static.Scalar.StructureValue
            //
            UANodeId dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440";    // ScalarValueDataType

            // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
            // operations.
            IEasyUAClientComplexData complexData = client.GetService<IEasyUAClientComplexData>();
            
            // Resolve the data type ID to the data type object, containing description of the data type.
            ValueResult<DataType> dataTypeResult = complexData.ResolveDataType(
                new UAModelNodeDescriptor(endpointDescriptor, dataTypeId), 
                UABrowseNames.DefaultBinary);
            // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            if (!dataTypeResult.Succeeded)
            {
                Console.WriteLine("*** Failure: {0}", dataTypeResult.ErrorMessageBrief);
                return;
            }

            // The actual data type is in the Value property.
            // Display basic information about what we have obtained.
            Console.WriteLine(dataTypeResult.Value);

            // If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose)
            // specifier. In the debugger, you can view the same by displaying the private DebugView property.
            Console.WriteLine();
            Console.WriteLine("{0:V}", dataTypeResult.Value);

            // For processing the internals of the data type, refer to examples for GenericData class.


            // Example output (truncated):
            //
            //ScalarValueDataType = structured
            //
            //ScalarValueDataType = structured
            //  [BooleanValue] Boolean = primitive(System.Boolean)
            //  [ByteStringValue] ByteString = primitive(System.Byte[])
            //  [ByteValue] Byte = primitive(System.Byte)
            //  [DateTimeValue] DateTime = primitive(System.DateTime)
            //  [DoubleValue] Double = primitive(System.Double)
            //  [EnumerationValue] Int32 = primitive(System.Int32)
            //  [ExpandedNodeIdValue] ExpandedNodeId = structured
            //    [ByteString] optional ByteStringNodeId = structured
            //      [Identifier] ByteString = primitive(System.Byte[])
            //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            //    [FourByte] optional FourByteNodeId = structured
            //      [Identifier] UInt16 = primitive(System.UInt16)
            //      [NamespaceIndex] Byte = primitive(System.Byte)
            //    [Guid] optional GuidNodeId = structured
            //      [Identifier] Guid = primitive(System.Guid)
            //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            //    [NamespaceURI] optional CharArray = primitive(System.String)
            //    [NamespaceURISpecified] switch Bit = primitive(System.Boolean)
            //    [NodeIdType] switch NodeIdType = enumeration(6)
            //      TwoByte = 0
            //      FourByte = 1
            //      Numeric = 2
            //      String = 3
            //      Guid = 4
            //      ByteString = 5
            //    [Numeric] optional NumericNodeId = structured
            //      [Identifier] UInt32 = primitive(System.UInt32)
            //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            //    [ServerIndex] optional UInt32 = primitive(System.UInt32)
            //    [ServerIndexSpecified] switch Bit = primitive(System.Boolean)
            //    [String] optional StringNodeId = structured
            //      [Identifier] CharArray = primitive(System.String)
            //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            //    [TwoByte] optional TwoByteNodeId = structured
            //      [Identifier] Byte = primitive(System.Byte)
            //  [FloatValue] Float = primitive(System.Single)
            //  [GuidValue] Guid = primitive(System.Guid)
            //  [Int16Value] Int16 = primitive(System.Int16)
            //  [Int32Value] Int32 = primitive(System.Int32)
            //  [Int64Value] Int64 = primitive(System.Int64)
            //  [Integer] Variant = structured
            //    [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32)
            //    [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
            //    [ArrayLength] length optional Int32 = primitive(System.Int32)
            //    [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
            //    [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean)
            //    [Byte] optional sequence[*] of Byte = primitive(System.Byte)
        }
    }
}
# Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from Microsoft.Extensions.DependencyInjection import *
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
#from OpcLabs.EasyOpc.UA.Extensions import *
from OpcLabs.EasyOpc.UA.InformationModel import *
from OpcLabs.EasyOpc.UA.Plugins.ComplexData 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()

# Obtain the data type ID.
#
# In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
# attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface.
# The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract
# data type, and the actual values are then sub-types of this base data type. This abstract data type does not
# have any encodings associated with it and it is therefore not possible to extract its description from the
# server. We therefore use a hard-coded data type ID for one of the sub-types in this example.
#
# The code to obtain the data type ID for given node would normally look like this:
#    dataTypeId = IEasyUAClientExtension2.ReadDataType(client,
#        endpointDescriptor,
#        UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239'))    # [ObjectsFolder]/Data.Static.Scalar.StructureValue
dataTypeId = UANodeId('nsu=http://test.org/UA/Data/ ;i=9440')   # ScalarValueDataType

# Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data
# operations.
complexData = ServiceProviderServiceExtensions.GetService[IEasyUAClientComplexData](client)
if complexData is None:
    print('The client complex data service is not available.')
    exit()

# Resolve the data type ID to the data type object, containing description of the data type.
dataTypeResult = IEasyUAClientComplexDataExtension.ResolveDataType(complexData,
    UAModelNodeDescriptor(endpointDescriptor, UANodeDescriptor(dataTypeId)),
    UABrowseNames.DefaultBinary)
# Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
if not dataTypeResult.Succeeded:
    print('*** Failure: ', dataTypeResult.ErrorMessageBrief)
    exit()

# The actual data type is in the Value property.
# Display basic information about what we have obtained.
print(dataTypeResult.Value)

# If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose)
# specifier. In the debugger, you can view the same by displaying the private DebugView property.
print()
print(String.Format('{0:V}', dataTypeResult.Value))

# For processing the internals of the data type, refer to examples for GenericData class.

print()
print('Finished.')
' Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.

Imports System
Imports Microsoft.Extensions.DependencyInjection
Imports OpcLabs.BaseLib.DataTypeModel
Imports OpcLabs.BaseLib.OperationModel.Generic
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.InformationModel
Imports OpcLabs.EasyOpc.UA.Plugins.ComplexData

Namespace ComplexData._IEasyUAClientComplexData

    Friend Class ResolveDataType

        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/"

            ' Instantiate the client object.
            Dim client = New EasyUAClient

            ' Obtain the data type ID.
            '
            ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
            ' attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample
            ' server, however, shows a more advanced approach in which the data type ID refers to an abstract data type,
            ' and the actual values are then sub-types of this base data type. This abstract data type does not have any
            ' encodings associated with it and it is therefore not possible to extract its description from the server.
            ' We therefore use a hard-coded data type ID for one of the sub-types in this example.
            '
            ' The code to obtain the data type ID for given node would normally look like this:
            '    UANodeId dataTypeId = client.ReadDataType(
            '        endpointDescriptor,
            '        "nsu=http://test.org/UA/Data/ ;i=10239");    // [ObjectsFolder]/Data.Static.Scalar.StructureValue
            '
            Dim dataTypeId As UANodeId = "nsu=http://test.org/UA/Data/ ;i=9440"  ' ScalarValueDataType

            ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
            ' operations.
            Dim complexData As IEasyUAClientComplexData = client.GetService(Of IEasyUAClientComplexData)()

            ' Resolve the data type ID to the data type object, containing description of the data type.
            Dim dataTypeResult As ValueResult(Of DataType) = complexData.ResolveDataType( _
                New UAModelNodeDescriptor(endpointDescriptor, dataTypeId), _
                UABrowseNames.DefaultBinary)
            ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            If Not dataTypeResult.Succeeded Then
                Console.WriteLine("*** Failure: {0}", dataTypeResult.ErrorMessageBrief)
                Exit Sub
            End If

            ' The actual data type is in the Value property.
            ' Display basic information about what we have obtained.
            Console.WriteLine(dataTypeResult.Value)

            ' If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose)
            ' specifier. In the debugger, you can view the same by displaying the private DebugView property.
            Console.WriteLine()
            Console.WriteLine("{0:V}", dataTypeResult.Value)

            ' For processing the internals of the data type, refer to examples for GenericData class.


            ' Example output (truncated):
            '
            'ScalarValueDataType = structured
            '
            'ScalarValueDataType = structured
            '  [BooleanValue] Boolean = primitive(System.Boolean)
            '  [ByteStringValue] ByteString = primitive(System.Byte[])
            '  [ByteValue] Byte = primitive(System.Byte)
            '  [DateTimeValue] DateTime = primitive(System.DateTime)
            '  [DoubleValue] Double = primitive(System.Double)
            '  [EnumerationValue] Int32 = primitive(System.Int32)
            '  [ExpandedNodeIdValue] ExpandedNodeId = structured
            '    [ByteString] optional ByteStringNodeId = structured
            '      [Identifier] ByteString = primitive(System.Byte[])
            '      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            '    [FourByte] optional FourByteNodeId = structured
            '      [Identifier] UInt16 = primitive(System.UInt16)
            '      [NamespaceIndex] Byte = primitive(System.Byte)
            '    [Guid] optional GuidNodeId = structured
            '      [Identifier] Guid = primitive(System.Guid)
            '      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            '    [NamespaceURI] optional CharArray = primitive(System.String)
            '    [NamespaceURISpecified] switch Bit = primitive(System.Boolean)
            '    [NodeIdType] switch NodeIdType = enumeration(6)
            '      TwoByte = 0
            '      FourByte = 1
            '      Numeric = 2
            '      String = 3
            '      Guid = 4
            '      ByteString = 5
            '    [Numeric] optional NumericNodeId = structured
            '      [Identifier] UInt32 = primitive(System.UInt32)
            '      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            '    [ServerIndex] optional UInt32 = primitive(System.UInt32)
            '    [ServerIndexSpecified] switch Bit = primitive(System.Boolean)
            '    [String] optional StringNodeId = structured
            '      [Identifier] CharArray = primitive(System.String)
            '      [NamespaceIndex] UInt16 = primitive(System.UInt16)
            '    [TwoByte] optional TwoByteNodeId = structured
            '      [Identifier] Byte = primitive(System.Byte)
            '  [FloatValue] Float = primitive(System.Single)
            '  [GuidValue] Guid = primitive(System.Guid)
            '  [Int16Value] Int16 = primitive(System.Int16)
            '  [Int32Value] Int32 = primitive(System.Int32)
            '  [Int64Value] Int64 = primitive(System.Int64)
            '  [Integer] Variant = structured
            '    [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32)
            '    [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
            '    [ArrayLength] length optional Int32 = primitive(System.Int32)
            '    [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
            '    [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean)
            '    [Byte] optional sequence[*] of Byte = primitive(System.Byte)
        End Sub
    End Class
End Namespace
// Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.

class procedure ResolveDataType.Main;
var
  Client: _EasyUAClient;
  ComplexData: _EasyUAClientComplexData;
  DataType: _DataType;
  DataTypeId: string;
  DataTypeResult: _ValueResult;
  EncodingName: _UAQualifiedName;
  EndpointDescriptor: string;
  ModelNodeDescriptor: _UAModelNodeDescriptor;
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';

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

  // Obtain the data type ID.
  //
  // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
  // attribute.
  // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and
  // the actual values are then sub-types of this base data type. This abstract data type does not have any encodings
  // associated with it and it is therefore not possible to extract its description from the server. We therefore use
  // a hard-coded data type ID for one of the sub-types in this example.
  DataTypeId := 'nsu=http://test.org/UA/Data/ ;i=9440';    // ScalarValueDataType

  // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data
  // operations.
  ComplexData := IInterface(Client.GetServiceByName('OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA')) as _EasyUAClientComplexData;

  // Resolve the data type ID to the data type object, containing description of the data type.
  ModelNodeDescriptor := CoUAModelNodeDescriptor.Create;
  ModelNodeDescriptor.EndpointDescriptor.UrlString := EndpointDescriptor;
  ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText := DataTypeId;
  EncodingName := CoUAQualifiedName.Create;
  EncodingName.StandardName := 'DefaultBinary';
  DataTypeResult := ComplexData.ResolveDataType(ModelNodeDescriptor, EncodingName);
  if not DataTypeResult.Succeeded then
  begin
    WriteLn(Format('*** Failure: %s', [DataTypeResult.ErrorMessageBrief]));
    Exit;
  end;

  // The actual data type is in the Value property.
  DataType := IUnknown(DataTypeResult.Value) as _DataType;

  // Display basic information about what we have obtained.
  WriteLn(DataType.ToString);

  // If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose)
  // specifier.
  Writeln;
  Writeln(DataType.ToString_2['V', nil]);

  // For processing the internals of the data type, refer to examples for GenericData class.


  // Example output (truncated):
  //
  //ScalarValueDataType = structured
  //
  //ScalarValueDataType = structured
  //  [BooleanValue] Boolean = primitive(System.Boolean)
  //  [ByteStringValue] ByteString = primitive(System.Byte[])
  //  [ByteValue] Byte = primitive(System.Byte)
  //  [DateTimeValue] DateTime = primitive(System.DateTime)
  //  [DoubleValue] Double = primitive(System.Double)
  //  [EnumerationValue] Int32 = primitive(System.Int32)
  //  [ExpandedNodeIdValue] ExpandedNodeId = structured
  //    [ByteString] optional ByteStringNodeId = structured
  //      [Identifier] ByteString = primitive(System.Byte[])
  //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
  //    [FourByte] optional FourByteNodeId = structured
  //      [Identifier] UInt16 = primitive(System.UInt16)
  //      [NamespaceIndex] Byte = primitive(System.Byte)
  //    [Guid] optional GuidNodeId = structured
  //      [Identifier] Guid = primitive(System.Guid)
  //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
  //    [NamespaceURI] optional CharArray = primitive(System.String)
  //    [NamespaceURISpecified] switch Bit = primitive(System.Boolean)
  //    [NodeIdType] switch NodeIdType = enumeration(6)
  //      TwoByte = 0
  //      FourByte = 1
  //      Numeric = 2
  //      String = 3
  //      Guid = 4
  //      ByteString = 5
  //    [Numeric] optional NumericNodeId = structured
  //      [Identifier] UInt32 = primitive(System.UInt32)
  //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
  //    [ServerIndex] optional UInt32 = primitive(System.UInt32)
  //    [ServerIndexSpecified] switch Bit = primitive(System.Boolean)
  //    [String] optional StringNodeId = structured
  //      [Identifier] CharArray = primitive(System.String)
  //      [NamespaceIndex] UInt16 = primitive(System.UInt16)
  //    [TwoByte] optional TwoByteNodeId = structured
  //      [Identifier] Byte = primitive(System.Byte)
  //  [FloatValue] Float = primitive(System.Single)
  //  [GuidValue] Guid = primitive(System.Guid)
  //  [Int16Value] Int16 = primitive(System.Int16)
  //  [Int32Value] Int32 = primitive(System.Int32)
  //  [Int64Value] Int64 = primitive(System.Int64)
  //  [Integer] Variant = structured
  //    [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32)
  //    [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
  //    [ArrayLength] length optional Int32 = primitive(System.Int32)
  //    [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
  //    [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean)
  //    [Byte] optional sequence[*] of Byte = primitive(System.Byte)

end;
Rem Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.

Option Explicit

' Define which server we will work with.
Dim endpointDescriptor: endpointDescriptor = _
    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
    '"http://opcua.demo-this.com:51211/UA/SampleServer"  
    '"https://opcua.demo-this.com:51212/UA/SampleServer/"

' Instantiate the client object.
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")

' Obtain the data type ID.
'
' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
' attribute. 
' The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and 
' the actual values are then sub-types of this base data type. This abstract data type does not have any encodings 
' associated with it and it is therefore not possible to extract its description from the server. We therefore use 
' a hard-coded data type ID for one of the sub-types in this example.
Dim dataTypeId: dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440"    ' ScalarValueDataType

' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
' operations.
Dim ComplexData: Set ComplexData = _
    Client.GetServiceByName("OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA")

' Resolve the data type ID to the data type object, containing description of the data type.
Dim ModelNodeDescriptor: Set ModelNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.InformationModel.UAModelNodeDescriptor")
ModelNodeDescriptor.EndpointDescriptor.UrlString = endpointDescriptor
ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText = dataTypeId
Dim EncodingName: Set EncodingName = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UAQualifiedName")
EncodingName.StandardName = "DefaultBinary"
Dim DataTypeResult: Set DataTypeResult = ComplexData.ResolveDataType(ModelNodeDescriptor, EncodingName)
If Not DataTypeResult.Succeeded Then
    WScript.Echo "*** Failure: "  & DataTypeResult.Exception.GetBaseException().Message
    WScript.Quit
End If

' The actual data type is in the Value property.
Dim DataType: Set DataType = DataTypeResult.Value

' Display basic information about what we have obtained.
WScript.Echo DataType

' If we want to see the whole hierarchy of the received data type, we can format it with the "V" (verbose)
' specifier. 
WScript.Echo
WScript.Echo DataType.ToString_2("V", Nothing)

' For processing the internals of the data type, refer to examples for GenericData class.


' Example output (truncated):
'
'ScalarValueDataType = structured
'
'ScalarValueDataType = structured
'  [BooleanValue] Boolean = primitive(System.Boolean)
'  [ByteStringValue] ByteString = primitive(System.Byte[])
'  [ByteValue] Byte = primitive(System.Byte)
'  [DateTimeValue] DateTime = primitive(System.DateTime)
'  [DoubleValue] Double = primitive(System.Double)
'  [EnumerationValue] Int32 = primitive(System.Int32)
'  [ExpandedNodeIdValue] ExpandedNodeId = structured
'    [ByteString] optional ByteStringNodeId = structured
'      [Identifier] ByteString = primitive(System.Byte[])
'      [NamespaceIndex] UInt16 = primitive(System.UInt16)
'    [FourByte] optional FourByteNodeId = structured
'      [Identifier] UInt16 = primitive(System.UInt16)
'      [NamespaceIndex] Byte = primitive(System.Byte)
'    [Guid] optional GuidNodeId = structured
'      [Identifier] Guid = primitive(System.Guid)
'      [NamespaceIndex] UInt16 = primitive(System.UInt16)
'    [NamespaceURI] optional CharArray = primitive(System.String)
'    [NamespaceURISpecified] switch Bit = primitive(System.Boolean)
'    [NodeIdType] switch NodeIdType = enumeration(6)
'      TwoByte = 0
'      FourByte = 1
'      Numeric = 2
'      String = 3
'      Guid = 4
'      ByteString = 5
'    [Numeric] optional NumericNodeId = structured
'      [Identifier] UInt32 = primitive(System.UInt32)
'      [NamespaceIndex] UInt16 = primitive(System.UInt16)
'    [ServerIndex] optional UInt32 = primitive(System.UInt32)
'    [ServerIndexSpecified] switch Bit = primitive(System.Boolean)
'    [String] optional StringNodeId = structured
'      [Identifier] CharArray = primitive(System.String)
'      [NamespaceIndex] UInt16 = primitive(System.UInt16)
'    [TwoByte] optional TwoByteNodeId = structured
'      [Identifier] Byte = primitive(System.Byte)
'  [FloatValue] Float = primitive(System.Single)
'  [GuidValue] Guid = primitive(System.Guid)
'  [Int16Value] Int16 = primitive(System.Int16)
'  [Int32Value] Int32 = primitive(System.Int32)
'  [Int64Value] Int64 = primitive(System.Int64)
'  [Integer] Variant = structured
'    [ArrayDimensions] optional sequence[*] of Int32 = primitive(System.Int32)
'    [ArrayDimensionsSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
'    [ArrayLength] length optional Int32 = primitive(System.Int32)
'    [ArrayLengthSpecified] switch sequence[1] of Bit = primitive(System.Boolean)
'    [Boolean] optional sequence[*] of Boolean = primitive(System.Boolean)
'    [Byte] optional sequence[*] of Byte = primitive(System.Byte)
// Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual
// content of the data type dictionary.

using System;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using OpcLabs.BaseLib.OperationModel.Generic;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.DataTypeModel;
using OpcLabs.EasyOpc.UA.DataTypeModel.Extensions;
using OpcLabs.EasyOpc.UA.InformationModel;
using OpcLabs.EasyOpc.UA.Plugins.ComplexData;

namespace UADocExamples.ComplexData._IUADataTypeDictionaryProvider
{
    class ResolveDataTypeDescriptorFromDataTypeEncodingId
    {
        public static void Main1()
        {
            // Define which server 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/"

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

            // Obtain the data type ID.
            //
            // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
            // attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample
            // server, however, shows a more advanced approach in which the data type ID refers to an abstract data type,
            // and the actual values are then sub-types of this base data type. This abstract data type does not have any
            // encodings associated with it and it is therefore not possible to extract its description from the server.
            // We therefore use a hard-coded data type ID for one of the sub-types in this example.
            //
            // The code to obtain the data type ID for given node would normally look like this:
            //    UANodeId dataTypeId = client.ReadDataType(
            //        endpointUriString,
            //        "nsu=http://test.org/UA/Data/ ;i=10239");    // [ObjectsFolder]/Data.Static.Scalar.StructureValue
            //
            UANodeId dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440";    // ScalarValueDataType

            // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
            // operations.
            IEasyUAClientComplexData complexData = client.GetService<IEasyUAClientComplexData>();

            // Get the data type model provider. Provides methods to access data types in OPC UA model.
            IUADataTypeModelProvider dataTypeModelProvider = complexData.DataTypeModelProvider;

            // Resolve the data type ID from our data type ID, for encoding name "Default Binary".
            ValueResult<UAModelNodeDescriptor> encodingIdResult = dataTypeModelProvider.ResolveEncodingIdFromDataTypeId(
                new UAModelNodeDescriptor(endpointDescriptor, dataTypeId),
                UABrowseNames.DefaultBinary);
            // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            if (!encodingIdResult.Succeeded)
            {
                Console.WriteLine("*** Failure: {0}", encodingIdResult.ErrorMessageBrief);
                return;
            }
            UAModelNodeDescriptor encodingId = encodingIdResult.Value;

            // Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model.
            IUADataTypeDictionaryProvider dataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider;

            // Resolve the data type descriptor from the encoding ID.
            ValueResult<UADataTypeDescriptor> dataTypeDescriptorResult =
                dataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(encodingId);
            // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            if (!dataTypeDescriptorResult.Succeeded)
            {
                Console.WriteLine("*** Failure: {0}", dataTypeDescriptorResult.ErrorMessageBrief);
                return;
            }
            UADataTypeDescriptor dataTypeDescriptor = dataTypeDescriptorResult.Value;

            // The data type descriptor contains two pieces of information:
            // The data type dictionary ID: This determines the dictionary where the data type is defined.
            Console.WriteLine(dataTypeDescriptor.DataTypeDictionaryId);
            // And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific 
            // type definition inside the data type dictionary. The format of it depends on the data type system;
            // in our case, it is a string that is the name of one of the type elements in the XML document of the data type
            // dictionary.
            Console.WriteLine(dataTypeDescriptor.DataTypeDescription);

            // Obtain the actual content of the data type dictionary.
            ValueResult<byte[]> dataTypeDictionaryResult =
                dataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(dataTypeDescriptor.DataTypeDictionaryId);
            // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            if (!dataTypeDictionaryResult.Succeeded)
            {
                Console.WriteLine("*** Failure: {0}", dataTypeDictionaryResult.ErrorMessageBrief);
                return;
            }
            byte[] dataTypeDictionary = dataTypeDictionaryResult.Value;

            // The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type 
            // system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8.
            string text = Encoding.UTF8.GetString(dataTypeDictionary);
            Console.WriteLine();
            Console.WriteLine(text);


            // Example output (truncated):
            //
            //http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422"
            //ScalarValueDataType
            //
            //<opc:TypeDictionary
            //  xmlns:opc="http://opcfoundation.org/BinarySchema/"
            //  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            //  xmlns:ua="http://opcfoundation.org/UA/"
            //  xmlns:tns="http://test.org/UA/Data/"
            //  DefaultByteOrder="LittleEndian"
            //  TargetNamespace="http://test.org/UA/Data/"
            //>
            //  <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. -->
            //  <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/>
            //
            //  <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject">
            //    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" />
            //    <opc:Field Name="SByteValue" TypeName="opc:SByte" />
            //    <opc:Field Name="ByteValue" TypeName="opc:Byte" />
            //    <opc:Field Name="Int16Value" TypeName="opc:Int16" />
            //    <opc:Field Name="UInt16Value" TypeName="opc:UInt16" />
            //    <opc:Field Name="Int32Value" TypeName="opc:Int32" />
            //    <opc:Field Name="UInt32Value" TypeName="opc:UInt32" />
            //    <opc:Field Name="Int64Value" TypeName="opc:Int64" />
            //    <opc:Field Name="UInt64Value" TypeName="opc:UInt64" />
            //    <opc:Field Name="FloatValue" TypeName="opc:Float" />
            //    <opc:Field Name="DoubleValue" TypeName="opc:Double" />
            //    <opc:Field Name="StringValue" TypeName="opc:String" />
            //    <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" />
            //    <opc:Field Name="GuidValue" TypeName="opc:Guid" />
            //    <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" />
            //    <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" />
            //    <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" />
            //    <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" />
            //    <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" />
            //    <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" />
            //    <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" />
            //    <opc:Field Name="VariantValue" TypeName="ua:Variant" />
            //    <opc:Field Name="EnumerationValue" TypeName="ua:Int32" />
            //    <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" />
            //    <opc:Field Name="Number" TypeName="ua:Variant" />
            //    <opc:Field Name="Integer" TypeName="ua:Variant" />
            //    <opc:Field Name="UInteger" TypeName="ua:Variant" />
            //  </opc:StructuredType>
            //
            //  <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject">
            //    <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" />
            //    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" />
            //    <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" />
        }
    }
}
# Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the
# actual content of the data type dictionary.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from Microsoft.Extensions.DependencyInjection import *
from System import *
from System.Text import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.DataTypeModel.Extensions import *
#from OpcLabs.EasyOpc.UA.Extensions import *
from OpcLabs.EasyOpc.UA.InformationModel import *
from OpcLabs.EasyOpc.UA.Plugins.ComplexData 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()

# Obtain the data type ID.
#
# In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
# attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface.
# The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract
# data type, and the actual values are then sub-types of this base data type. This abstract data type does not
# have any encodings associated with it and it is therefore not possible to extract its description from the
# server. We therefore use a hard-coded data type ID for one of the sub-types in this example.
#
# The code to obtain the data type ID for given node would normally look like this:
#    dataTypeId = IEasyUAClientExtension2.ReadDataType(client,
#        endpointDescriptor,
#        UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239'))    # [ObjectsFolder]/Data.Static.Scalar.StructureValue
dataTypeId = UANodeId('nsu=http://test.org/UA/Data/ ;i=9440')   # ScalarValueDataType

# Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data
# operations.
complexData = ServiceProviderServiceExtensions.GetService[IEasyUAClientComplexData](client)
if complexData is None:
    print('The client complex data service is not available.')
    exit()

# Get the data type model provider. Provides methods to access data types in OPC UA model.
dataTypeModelProvider = complexData.DataTypeModelProvider

# Resolve the data type ID from our data type ID, for encoding name "Default Binary".
encodingIdResult = IUADataTypeModelProviderExtension.ResolveEncodingIdFromDataTypeId(dataTypeModelProvider,
    UAModelNodeDescriptor(endpointDescriptor, UANodeDescriptor(dataTypeId)),
    UABrowseNames.DefaultBinary)
# Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
if not encodingIdResult.Succeeded:
    print('*** Failure: ', encodingIdResult.ErrorMessageBrief)
    exit()
encodingId = encodingIdResult.Value

# Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model.
dataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider

# Resolve the data type descriptor from the encoding ID.
dataTypeDescriptorResult = IUADataTypeDictionaryProviderExtension.ResolveDataTypeDescriptorFromDataTypeEncodingId(
    dataTypeDictionaryProvider, encodingId)
# Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
if not dataTypeDescriptorResult.Succeeded:
    print('*** Failure: ', dataTypeDescriptorResult.ErrorMessageBrief)
    exit()
dataTypeDescriptor = dataTypeDescriptorResult.Value

# The data type descriptor contains two pieces of information:
# The data type dictionary ID: This determines the dictionary where the data type is defined.
print(dataTypeDescriptor.DataTypeDictionaryId)
# And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific
# type definition inside the data type dictionary. The format of it depends on the data type system;
# in our case, it is a string that is the name of one of the type elements in the XML document of the data type
# dictionary.
print(dataTypeDescriptor.DataTypeDescription)

# Obtain the actual content of the data type dictionary.
dataTypeDictionaryResult = IUADataTypeDictionaryProviderExtension.GetDataTypeDictionaryFromDataTypeDictionaryId(
    dataTypeDictionaryProvider, dataTypeDescriptor.DataTypeDictionaryId)
# Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
if not dataTypeDictionaryResult.Succeeded:
    print('*** Failure: ', dataTypeDictionaryResult.ErrorMessageBrief)
    exit()
dataTypeDictionary = dataTypeDictionaryResult.Value

# The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type
# system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8.
text = Encoding.UTF8.GetString(dataTypeDictionary)
print()
print(text)

print()
print('Finished.')
' Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual
' content of the data type dictionary.

Imports System
Imports System.Text
Imports Microsoft.Extensions.DependencyInjection
Imports OpcLabs.BaseLib.OperationModel.Generic
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.DataTypeModel
Imports OpcLabs.EasyOpc.UA.DataTypeModel.Extensions
Imports OpcLabs.EasyOpc.UA.InformationModel
Imports OpcLabs.EasyOpc.UA.Plugins.ComplexData

Namespace ComplexData._IUADataTypeDictionaryProvider

    Friend Class ResolveDataTypeDescriptorFromDataTypeEncodingId

        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/"

            ' Instantiate the client object.
            Dim client = New EasyUAClient

            ' Obtain the data type ID.
            '
            ' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
            ' attribute, or easier, by calling the extension method ReadDataType on the IEasyUAClient interface. The sample
            ' server, however, shows a more advanced approach in which the data type ID refers to an abstract data type,
            ' and the actual values are then sub-types of this base data type. This abstract data type does not have any
            ' encodings associated with it and it is therefore not possible to extract its description from the server.
            ' We therefore use a hard-coded data type ID for one of the sub-types in this example.
            '
            ' The code to obtain the data type ID for given node would normally look like this:
            '    UANodeId dataTypeId = client.ReadDataType(
            '        endpointUriString,
            '        "nsu=http://test.org/UA/Data/ ;i=10239");    // [ObjectsFolder]/Data.Static.Scalar.StructureValue
            '
            Dim dataTypeId As UANodeId = "nsu=http://test.org/UA/Data/ ;i=9440"  ' ScalarValueDataType

            ' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
            ' operations.
            Dim complexData As IEasyUAClientComplexData = client.GetService(Of IEasyUAClientComplexData)()

            ' Get the data type model provider. Provides methods to access data types in OPC UA model.
            Dim dataTypeModelProvider As IUADataTypeModelProvider = complexData.DataTypeModelProvider

            ' Resolve the data type ID from our data type ID, for encoding name "Default Binary".
            Dim encodingIdResult As ValueResult(Of UAModelNodeDescriptor) = dataTypeModelProvider.ResolveEncodingIdFromDataTypeId(
                New UAModelNodeDescriptor(endpointDescriptor, dataTypeId),
                UABrowseNames.DefaultBinary)
            ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            If Not encodingIdResult.Succeeded Then
                Console.WriteLine("*** Failure: {0}", encodingIdResult.ErrorMessageBrief)
                Exit Sub
            End If
            Dim encodingId As UAModelNodeDescriptor = encodingIdResult.Value

            ' Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model.
            Dim dataTypeDictionaryProvider As IUADataTypeDictionaryProvider = complexData.DataTypeDictionaryProvider

            ' Resolve the data type descriptor from the encoding ID.
            Dim dataTypeDescriptorResult As ValueResult(Of UADataTypeDescriptor) =
                    dataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(encodingId)
            ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            If Not dataTypeDescriptorResult.Succeeded Then
                Console.WriteLine("*** Failure: {0}", dataTypeDescriptorResult.ErrorMessageBrief)
                Exit Sub
            End If
            Dim dataTypeDescriptor As UADataTypeDescriptor = dataTypeDescriptorResult.Value

            ' The data type descriptor contains two pieces of information:
            ' The data type dictionary ID: This determines the dictionary where the data type is defined.
            Console.WriteLine(dataTypeDescriptor.DataTypeDictionaryId)
            ' And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific 
            ' type definition inside the data type dictionary. The format of it depends on the data type system;
            ' in our case, it is a string that is the name of one of the type elements in the XML document of the data type
            ' dictionary.
            Console.WriteLine(dataTypeDescriptor.DataTypeDescription)

            ' Obtain the actual content of the data type dictionary.
            Dim dataTypeDictionaryResult As ValueResult(Of Byte()) =
                    dataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(dataTypeDescriptor.DataTypeDictionaryId)
            ' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
            If Not dataTypeDictionaryResult.Succeeded Then
                Console.WriteLine("*** Failure: {0}", dataTypeDictionaryResult.ErrorMessageBrief)
                Exit Sub
            End If
            Dim dataTypeDictionary() As Byte = dataTypeDictionaryResult.Value

            ' The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type 
            ' system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8.
            Dim text As String = Encoding.UTF8.GetString(dataTypeDictionary)
            Console.WriteLine()
            Console.WriteLine(text)


            ' Example output (truncated):
            '
            'http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422"
            'ScalarValueDataType
            '
            '<opc:TypeDictionary
            '  xmlns:opc="http://opcfoundation.org/BinarySchema/"
            '  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            '  xmlns:ua="http://opcfoundation.org/UA/"
            '  xmlns:tns="http://test.org/UA/Data/"
            '  DefaultByteOrder="LittleEndian"
            '  TargetNamespace="http://test.org/UA/Data/"
            '>
            '  <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. -->
            '  <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/>
            '
            '  <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject">
            '    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" />
            '    <opc:Field Name="SByteValue" TypeName="opc:SByte" />
            '    <opc:Field Name="ByteValue" TypeName="opc:Byte" />
            '    <opc:Field Name="Int16Value" TypeName="opc:Int16" />
            '    <opc:Field Name="UInt16Value" TypeName="opc:UInt16" />
            '    <opc:Field Name="Int32Value" TypeName="opc:Int32" />
            '    <opc:Field Name="UInt32Value" TypeName="opc:UInt32" />
            '    <opc:Field Name="Int64Value" TypeName="opc:Int64" />
            '    <opc:Field Name="UInt64Value" TypeName="opc:UInt64" />
            '    <opc:Field Name="FloatValue" TypeName="opc:Float" />
            '    <opc:Field Name="DoubleValue" TypeName="opc:Double" />
            '    <opc:Field Name="StringValue" TypeName="opc:String" />
            '    <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" />
            '    <opc:Field Name="GuidValue" TypeName="opc:Guid" />
            '    <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" />
            '    <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" />
            '    <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" />
            '    <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" />
            '    <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" />
            '    <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" />
            '    <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" />
            '    <opc:Field Name="VariantValue" TypeName="ua:Variant" />
            '    <opc:Field Name="EnumerationValue" TypeName="ua:Int32" />
            '    <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" />
            '    <opc:Field Name="Number" TypeName="ua:Variant" />
            '    <opc:Field Name="Integer" TypeName="ua:Variant" />
            '    <opc:Field Name="UInteger" TypeName="ua:Variant" />
            '  </opc:StructuredType>
            '
            '  <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject">
            '    <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" />
            '    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" />
            '    <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" />
        End Sub
    End Class
End Namespace
// Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual
// content of the data type dictionary.

class procedure ResolveDataTypeDescriptorFromDataTypeEncodingId.Main;
var
  Client: _EasyUAClient;
  ComplexData: _EasyUAClientComplexData;
  DataTypeDictionary: OleVariant;
  DataTypeDictionaryResult: _ValueResult;
  DataTypeDescriptor: _UADataTypeDescriptor;
  DataTypeDescriptorResult: _ValueResult;
  DataTypeId: string;
  DataTypeModelProvider: _UADataTypeModelProvider;
  DataTypeDictionaryProvider: _UADataTypeDictionaryProvider;
  EncodingId: _UAModelNodeDescriptor;
  EncodingIdResult: _ValueResult;
  EncodingName: _UAQualifiedName;
  EndpointDescriptor: string;
  I: Cardinal;
  ModelNodeDescriptor: _UAModelNodeDescriptor;
  Text: string;
begin
  // Define which server and node we will work with.
  EndpointDescriptor :=
    'http://opcua.demo-this.com:51211/UA/SampleServer';
    //or 'https://opcua.demo-this.com:51212/UA/SampleServer/';
    //or 'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';

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

  // Obtain the data type ID.
  //
  // In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
  // attribute.
  // The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and
  // the actual values are then sub-types of this base data type. This abstract data type does not have any encodings
  // associated with it and it is therefore not possible to extract its description from the server. We therefore use
  // a hard-coded data type ID for one of the sub-types in this example.
  DataTypeId := 'nsu=http://test.org/UA/Data/ ;i=9440';    // ScalarValueDataType

  // Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data
  // operations.
  ComplexData := IInterface(Client.GetServiceByName('OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA')) as _EasyUAClientComplexData;

  // Get the data type model provider. Provides methods to access data types in OPC UA model.
  DataTypeModelProvider := ComplexData.DataTypeModelProvider;

  // Resolve the data type ID from our data type ID, for encoding name "Default Binary".
  ModelNodeDescriptor := CoUAModelNodeDescriptor.Create;
  ModelNodeDescriptor.EndpointDescriptor.UrlString := EndpointDescriptor;
  ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText := DataTypeId;
  EncodingName := CoUAQualifiedName.Create;
  EncodingName.StandardName := 'DefaultBinary';
  EncodingIdResult := DataTypeModelProvider.ResolveEncodingIdFromDataTypeId(ModelNodeDescriptor, EncodingName);
  // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
  if not EncodingIdResult.Succeeded then
  begin
    WriteLn(Format('*** Failure: %s', [EncodingIdResult.ErrorMessageBrief]));
    Exit;
  end;
  EncodingId := IUnknown(EncodingIdResult.Value) as _UAModelNodeDescriptor;

  // Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model.
  DataTypeDictionaryProvider := ComplexData.DataTypeDictionaryProvider;

  // Resolve the data type descriptor from the encoding ID.
  DataTypeDescriptorResult := DataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(EncodingId);
  // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
  if not DataTypeDescriptorResult.Succeeded then
  begin
    WriteLn(Format('*** Failure: %s', [DataTypeDescriptorResult.ErrorMessageBrief]));
    Exit;
  end;
  DataTypeDescriptor := IUnknown(DataTypeDescriptorResult.Value) as _UADataTypeDescriptor;

  // The data type descriptor contains two pieces of information:
  // The data type dictionary ID: This determines the dictionary where the data type is defined.
  WriteLn(DataTypeDescriptor.DataTypeDictionaryId.ToString);
  // And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific
  // type definition inside the data type dictionary. The format of it depends on the data type system;
  // in our case, it is a string that is the name of one of the type elements in the XML document of the data type
  // dictionary.
  WriteLn(DataTypeDescriptor.DataTypeDescription);

  // Obtain the actual content of the data type dictionary.
  DataTypeDictionaryResult :=
    DataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(DataTypeDescriptor.DataTypeDictionaryId);
  // Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
  if not DataTypeDictionaryResult.Succeeded then
  begin
    WriteLn(Format('*** Failure: %s', [DataTypeDictionaryResult.ErrorMessageBrief]));
    Exit;
  end;
  DataTypeDictionary := DataTypeDictionaryResult.Value;

  // The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type
  // system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8.
  for I := VarArrayLowBound(DataTypeDictionary, 1) to VarArrayHighBound(DataTypeDictionary, 1) do
  begin
      Text := Text + Chr(Byte(DataTypeDictionary[I]));
  end;

  WriteLn;
  WriteLn(Text);

  // Example output (truncated):
  //
  //http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http://test.org/UA/Data/ ;ns=2;i=11422"
  //ScalarValueDataType
  //
  //<opc:TypeDictionary
  //  xmlns:opc="http://opcfoundation.org/BinarySchema/"
  //  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  //  xmlns:ua="http://opcfoundation.org/UA/"
  //  xmlns:tns="http://test.org/UA/Data/"
  //  DefaultByteOrder="LittleEndian"
  //  TargetNamespace="http://test.org/UA/Data/"
  //>
  //  <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. -->
  //  <opc:Import Namespace="http://opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/>
  //
  //  <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject">
  //    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" />
  //    <opc:Field Name="SByteValue" TypeName="opc:SByte" />
  //    <opc:Field Name="ByteValue" TypeName="opc:Byte" />
  //    <opc:Field Name="Int16Value" TypeName="opc:Int16" />
  //    <opc:Field Name="UInt16Value" TypeName="opc:UInt16" />
  //    <opc:Field Name="Int32Value" TypeName="opc:Int32" />
  //    <opc:Field Name="UInt32Value" TypeName="opc:UInt32" />
  //    <opc:Field Name="Int64Value" TypeName="opc:Int64" />
  //    <opc:Field Name="UInt64Value" TypeName="opc:UInt64" />
  //    <opc:Field Name="FloatValue" TypeName="opc:Float" />
  //    <opc:Field Name="DoubleValue" TypeName="opc:Double" />
  //    <opc:Field Name="StringValue" TypeName="opc:String" />
  //    <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" />
  //    <opc:Field Name="GuidValue" TypeName="opc:Guid" />
  //    <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" />
  //    <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" />
  //    <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" />
  //    <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" />
  //    <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" />
  //    <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" />
  //    <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" />
  //    <opc:Field Name="VariantValue" TypeName="ua:Variant" />
  //    <opc:Field Name="EnumerationValue" TypeName="ua:Int32" />
  //    <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" />
  //    <opc:Field Name="Number" TypeName="ua:Variant" />
  //    <opc:Field Name="Integer" TypeName="ua:Variant" />
  //    <opc:Field Name="UInteger" TypeName="ua:Variant" />
  //  </opc:StructuredType>
  //
  //  <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject">
  //    <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" />
  //    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" />
  //    <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" />

end;
Rem Shows how to obtain data type description object for complex data node with OPC UA Complex Data plug-in, and the actual
Rem content of the data type dictionary.

Option Explicit

' Define which server we will work with.
Dim endpointDescriptor: endpointDescriptor = _
    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
    '"http://opcua.demo-this.com:51211/UA/SampleServer"  
    '"https://opcua.demo-this.com:51212/UA/SampleServer/"

' Instantiate the client object.
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")

' Obtain the data type ID.
'
' In many cases, you would be able to obtain the data type ID of a particular node by reading its DataType
' attribute. 
' The sample server, however, shows a more advanced approach in which the data type ID refers to an abstract data type, and 
' the actual values are then sub-types of this base data type. This abstract data type does not have any encodings 
' associated with it and it is therefore not possible to extract its description from the server. We therefore use 
' a hard-coded data type ID for one of the sub-types in this example.
Dim dataTypeId: dataTypeId = "nsu=http://test.org/UA/Data/ ;i=9440"    ' ScalarValueDataType

' Get the IEasyUAClientComplexData service from the client. This is needed for advanced complex data 
' operations.
Dim ComplexData: Set ComplexData = _
    Client.GetServiceByName("OpcLabs.EasyOpc.UA.Plugins.ComplexData.IEasyUAClientComplexData, OpcLabs.EasyOpcUA")

' Get the data type model provider. Provides methods to access data types in OPC UA model.
Dim DataTypeModelProvider: Set DataTypeModelProvider = ComplexData.DataTypeModelProvider

' Resolve the data type ID from our data type ID, for encoding name "Default Binary".
Dim ModelNodeDescriptor: Set ModelNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.InformationModel.UAModelNodeDescriptor")
ModelNodeDescriptor.EndpointDescriptor.UrlString = endpointDescriptor
ModelNodeDescriptor.NodeDescriptor.NodeId.ExpandedText = dataTypeId
Dim EncodingName: Set EncodingName = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UAQualifiedName")
EncodingName.StandardName = "DefaultBinary"
Dim EncodingIdResult: Set EncodingIdResult = _
    DataTypeModelProvider.ResolveEncodingIdFromDataTypeId(ModelNodeDescriptor, EncodingName)
' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
If Not EncodingIdResult.Succeeded Then
    WScript.Echo "*** Failure: "  & EncodingIdResult.Exception.GetBaseException().Message
    WScript.Quit
End If
Dim EncodingId: Set EncodingId = EncodingIdResult.Value

' Get the data type dictionary provider. Provides methods to access data type dictionaries in OPC UA model.
Dim DataTypeDictionaryProvider: Set DataTypeDictionaryProvider = ComplexData.DataTypeDictionaryProvider

' Resolve the data type descriptor from the encoding ID.
Dim DataTypeDescriptorResult: Set DataTypeDescriptorResult = _
    DataTypeDictionaryProvider.ResolveDataTypeDescriptorFromDataTypeEncodingId(EncodingId)
' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
If Not DataTypeDescriptorResult.Succeeded Then
    WScript.Echo "*** Failure: "  & DataTypeDescriptorResult.Exception.GetBaseException().Message
    WScript.Quit
End If
Dim DataTypeDescriptor: Set DataTypeDescriptor = DataTypeDescriptorResult.Value

' The data type descriptor contains two pieces of information:
' The data type dictionary ID: This determines the dictionary where the data type is defined.
WScript.Echo DataTypeDescriptor.DataTypeDictionaryId
' And the data type description: It is a "pointer" into the data type dictionary itself, selecting a specific 
' type definition inside the data type dictionary. The format of it depends on the data type system;
' in our case, it is a string that is the name of one of the type elements in the XML document of the data type
' dictionary.
WScript.Echo DataTypeDescriptor.DataTypeDescription

' Obtain the actual content of the data type dictionary.
Dim DataTypeDictionaryResult: Set DataTypeDictionaryResult = _
    DataTypeDictionaryProvider.GetDataTypeDictionaryFromDataTypeDictionaryId(DataTypeDescriptor.DataTypeDictionaryId)
' Check if the operation succeeded. Use the ThrowIfFailed method instead if you want exception be thrown.
If Not DataTypeDictionaryResult.Succeeded Then
    WScript.Echo "*** Failure: "  & DataTypeDictionaryResult.Exception.GetBaseException().Message
    WScript.Quit
End If
Dim DataTypeDictionary: DataTypeDictionary = DataTypeDictionaryResult.Value

' The data type dictionary returned is an array of bytes; its syntax and semantics depends on the data type 
' system. In our case, we know that the data type dictionary is actually a string encoded in UTF-8.
Dim text
Dim i: For i = LBound(DataTypeDictionary) To UBound(DataTypeDictionary)
    text = text & Chr(DataTypeDictionary(i))
Next
WScript.Echo
WScript.Echo text


' Example output (truncated):
'
'http://opcua.demo-this.com:51211/UA/SampleServer; NodeId="nsu=http:'test.org/UA/Data/;ns=2;i=11422"
'ScalarValueDataType
'
'<opc:TypeDictionary
'  xmlns:opc="http:'opcfoundation.org/BinarySchema/"
'  xmlns:xsi="http:'www.w3.org/2001/XMLSchema-instance"
'  xmlns:ua="http:'opcfoundation.org/UA/"
'  xmlns:tns="http:'test.org/UA/Data/"
'  DefaultByteOrder="LittleEndian"
'  TargetNamespace="http:'test.org/UA/Data/"
'>
'  <!-- This File was generated on 2013-01-22 and supports the specifications supported by version 1.1.334.0 of the OPC UA deliverables. -->
'  <opc:Import Namespace="http:'opcfoundation.org/UA/" Location="Opc.Ua.BinarySchema.bsd"/>
'
'  <opc:StructuredType Name="ScalarValueDataType" BaseType="ua:ExtensionObject">
'    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" />
'    <opc:Field Name="SByteValue" TypeName="opc:SByte" />
'    <opc:Field Name="ByteValue" TypeName="opc:Byte" />
'    <opc:Field Name="Int16Value" TypeName="opc:Int16" />
'    <opc:Field Name="UInt16Value" TypeName="opc:UInt16" />
'    <opc:Field Name="Int32Value" TypeName="opc:Int32" />
'    <opc:Field Name="UInt32Value" TypeName="opc:UInt32" />
'    <opc:Field Name="Int64Value" TypeName="opc:Int64" />
'    <opc:Field Name="UInt64Value" TypeName="opc:UInt64" />
'    <opc:Field Name="FloatValue" TypeName="opc:Float" />
'    <opc:Field Name="DoubleValue" TypeName="opc:Double" />
'    <opc:Field Name="StringValue" TypeName="opc:String" />
'    <opc:Field Name="DateTimeValue" TypeName="opc:DateTime" />
'    <opc:Field Name="GuidValue" TypeName="opc:Guid" />
'    <opc:Field Name="ByteStringValue" TypeName="opc:ByteString" />
'    <opc:Field Name="XmlElementValue" TypeName="ua:XmlElement" />
'    <opc:Field Name="NodeIdValue" TypeName="ua:NodeId" />
'    <opc:Field Name="ExpandedNodeIdValue" TypeName="ua:ExpandedNodeId" />
'    <opc:Field Name="QualifiedNameValue" TypeName="ua:QualifiedName" />
'    <opc:Field Name="LocalizedTextValue" TypeName="ua:LocalizedText" />
'    <opc:Field Name="StatusCodeValue" TypeName="ua:StatusCode" />
'    <opc:Field Name="VariantValue" TypeName="ua:Variant" />
'    <opc:Field Name="EnumerationValue" TypeName="ua:Int32" />
'    <opc:Field Name="StructureValue" TypeName="ua:ExtensionObject" />
'    <opc:Field Name="Number" TypeName="ua:Variant" />
'    <opc:Field Name="Integer" TypeName="ua:Variant" />
'    <opc:Field Name="UInteger" TypeName="ua:Variant" />
'  </opc:StructuredType>
'
'  <opc:StructuredType Name="ArrayValueDataType" BaseType="ua:ExtensionObject">
'    <opc:Field Name="NoOfBooleanValue" TypeName="opc:Int32" />
'    <opc:Field Name="BooleanValue" TypeName="opc:Boolean" LengthField="NoOfBooleanValue" />
'    <opc:Field Name="NoOfSByteValue" TypeName="opc:Int32" />
Inheritance Hierarchy

System.Object
   OpcLabs.BaseLib.Object2
      OpcLabs.BaseLib.Info
         OpcLabs.EasyOpc.UA.InformationModel.UAModelNodeDescriptor

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