QuickOPC User's Guide and Reference
GenericData Class
Members  Example 



OpcLabs.BaseLib Assembly > OpcLabs.BaseLib.DataTypeModel Namespace : GenericData Class
An abstract generic data.
Object Model
GenericData ClassDataType Class
Syntax
'Declaration
 
<CLSCompliantAttribute(True)>
<ComDefaultInterfaceAttribute(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData)>
<ComVisibleAttribute(True)>
<DebuggerDisplayAttribute("{DebuggerDisplay,nq}")>
<ExceptionContractVerificationAttribute(True)>
<GuidAttribute("C69BAEE4-3E48-42E0-B1C4-89B0D762C3DD")>
<TypeConverterAttribute(OpcLabs.BaseLib.Implementation.LogicalSorterConverter)>
<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 MustInherit Class GenericData 
   Inherits OpcLabs.BaseLib.Info
   Implements OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData, System.ICloneable, System.IFormattable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable 
'Usage
 
Dim instance As GenericData
[CLSCompliant(true)]
[ComDefaultInterface(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData)]
[ComVisible(true)]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[ExceptionContractVerification(true)]
[Guid("C69BAEE4-3E48-42E0-B1C4-89B0D762C3DD")]
[TypeConverter(OpcLabs.BaseLib.Implementation.LogicalSorterConverter)]
[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 abstract class GenericData : OpcLabs.BaseLib.Info, OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData, System.ICloneable, System.IFormattable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable  
[CLSCompliant(true)]
[ComDefaultInterface(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData)]
[ComVisible(true)]
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[ExceptionContractVerification(true)]
[Guid("C69BAEE4-3E48-42E0-B1C4-89B0D762C3DD")]
[TypeConverter(OpcLabs.BaseLib.Implementation.LogicalSorterConverter)]
[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 GenericData abstract : public OpcLabs.BaseLib.Info, OpcLabs.BaseLib.ComTypes._Info, OpcLabs.BaseLib.ComTypes._Object2, OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericData, System.ICloneable, System.IFormattable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable  
Remarks

Classes derived from GenericData form following class hierarchy:

.

Example

.NET

COM

.NET

COM

.NET

COM

// Shows how to read complex data with OPC UA Complex Data plug-in.

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

namespace UADocExamples.ComplexData._EasyUAClient
{
    class ReadValue
    {
        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 which returns complex data. This is done in the same way as regular reads - just the data 
            // returned is different.
            object value;
            try
            {
                value = client.ReadValue(endpointDescriptor, nodeDescriptor);
            }
            catch (UAException uaException)
            {
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                return;
            }

            // Display basic information about what we have read.
            Console.WriteLine(value);


            // We know that this node returns complex data, so we can type cast to UAGenericObject.
            var genericObject = (UAGenericObject) value;

            // The actual data is in the GenericData property of the UAGenericObject.
            //
            // If we want to see the whole hierarchy of the received complex data, 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}", genericObject.GenericData);

            // For processing the internals of the data, refer to examples for GenericData and DataType classes.

            // .Int32Value
            var int32Value = ((genericObject.GenericData as StructuredData)
                ?.FieldData["Int32Value"] as PrimitiveData)
                ?.Value as int?;
            Console.WriteLine();
            Console.WriteLine($"Int32Value: {int32Value}");


            // Example output (truncated):
            //
            //(ScalarValueDataType) structured
            //
            //(ScalarValueDataType) structured   
            //  [BooleanValue] (Boolean) primitive; True {System.Boolean}
            //  [ByteStringValue] (ByteString) primitive; System.Byte[] {System.Byte[]}
            //  [ByteValue] (Byte) primitive; 153 {System.Byte}
            //  [DateTimeValue] (DateTime) primitive; 5/11/2013 4:32:00 PM {System.DateTime}
            //  [DoubleValue] (Double) primitive; -8.93178007363702E+27 {System.Double}
            //  [EnumerationValue] (Int32) primitive; 0 {System.Int32}
            //  [ExpandedNodeIdValue] (ExpandedNodeId) structured
            //    [NamespaceURI] (CharArray) primitive; "http://samples.org/UA/memorybuffer/Instance" {System.String}
            //    [NamespaceURISpecified] (Bit) primitive; True {System.Boolean}
            //    [NodeIdType] (NodeIdType) enumeration; 3 (String)
            //    [ServerIndexSpecified] (Bit) primitive; False {System.Boolean}
            //    [String] (StringNodeId) structured
            //      [Identifier] (CharArray) primitive; "????" {System.String}
            //      [NamespaceIndex] (UInt16) primitive; 0 {System.UInt16}
            //  [FloatValue] (Float) primitive; 78.37176 {System.Single}
            //  [GuidValue] (Guid) primitive; 8129cdaf-24d9-8140-64f2-3a6d7a957fd7 {System.Guid}
            //  [Int16Value] (Int16) primitive; 2793 {System.Int16}
            //  [Int32Value] (Int32) primitive; 1133391074 {System.Int32}
            //  [Int64Value] (Int64) primitive; -1039109760798965779 {System.Int64}
            //  [Integer] (Variant) structured
            //    [ArrayDimensionsSpecified] sequence[1]
            //      [0] (Bit) primitive; False {System.Boolean}
            //    [ArrayLengthSpecified] sequence[1]
            //      [0] (Bit) primitive; False {System.Boolean}
            //    [Int64] sequence[1]
            //      [0] (Int64) primitive; 0 {System.Int64}
            //    [VariantType] sequence[6]
            //      [0] (Bit) primitive; False {System.Boolean}
            //      [1] (Bit) primitive; False {System.Boolean}
            //      [2] (Bit) primitive; False {System.Boolean}
            //      [3] (Bit) primitive; True {System.Boolean}
            //      [4] (Bit) primitive; False {System.Boolean}
            //      [5] (Bit) primitive; False {System.Boolean}
            //  [LocalizedTextValue] (LocalizedText) structured
            //    [Locale] (CharArray) primitive; "ko" {System.String}
            //    [LocaleSpecified] (Bit) primitive; True {System.Boolean}
            //    [Reserved1] sequence[6]
            //      [0] (Bit) primitive; False {System.Boolean}
            //      [1] (Bit) primitive; False {System.Boolean}
            //      [2] (Bit) primitive; False {System.Boolean}
            //      [3] (Bit) primitive; False {System.Boolean}
            //      [4] (Bit) primitive; False {System.Boolean}
            //      [5] (Bit) primitive; False {System.Boolean}
            //    [Text] (CharArray) primitive; "? ?? ??+ ??? ??) ?: ???? ?! ?!" {System.String}
            //    [TextSpecified] (Bit) primitive; True {System.Boolean}
            //  [NodeIdValue] (NodeId) structured                                                                               
        }
    }
}
# Shows how to read complex data 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 System import *
from OpcLabs.BaseLib.DataTypeModel import *
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/'

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

# Instantiate the client object.
client = EasyUAClient()

# Read a node which returns complex data. This is done in the same way as regular reads - just the data
# returned is different.
try:
    value = IEasyUAClientExtension.ReadValue(client, endpointDescriptor, nodeDescriptor)
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display basic information about what we have read.
print(value)


# We know that this node returns complex data, so we can type cast to UAGenericObject.
genericObject = value

# The actual data is in the GenericData property of the UAGenericObject.
#
# If we want to see the whole hierarchy of the received complex data, 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}', genericObject.GenericData))

# For processing the internals of the data, refer to examples for GenericData and DataType classes.

# .Int32Value
structuredData = genericObject.GenericData if isinstance(genericObject.GenericData, StructuredData) else None
fieldData = None if structuredData is None else structuredData.FieldData
fieldValue = None if fieldData is None else fieldData.get_Item('Int32Value')
primitiveData = fieldValue if isinstance(fieldValue, PrimitiveData) else None
int32Value = None if primitiveData is None else primitiveData.Value
print()
print('Int32Value: ', int32Value, sep='')

print()
print('Finished.')
' Shows how to read complex data with OPC UA Complex Data plug-in.

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

Namespace ComplexData._EasyUAClient

    Friend Class ReadValue

        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 which returns complex data. This is done in the same way as regular reads - just the data 
            ' returned is different.
            Dim value As Object
            Try
                value = client.ReadValue(endpointDescriptor, nodeDescriptor)
            Catch uaException As UAException
                Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                Exit Sub
            End Try

            ' Display basic information about what we have read.
            Console.WriteLine(value)


            ' We know that this node returns complex data, so we can type cast to UAGenericObject.
            Dim genericObject = CType(value, UAGenericObject)

            ' The actual data is in the GenericData property of the UAGenericObject.
            '
            ' If we want to see the whole hierarchy of the received complex data, 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}", genericObject.GenericData)

            ' For processing the internals of the data, refer to examples for GenericData and DataType classes.


            ' Example output (truncated):
            '
            '(ScalarValueDataType) structured
            '
            '(ScalarValueDataType) structured   
            '  [BooleanValue] (Boolean) primitive; True {System.Boolean}
            '  [ByteStringValue] (ByteString) primitive; System.Byte[] {System.Byte[]}
            '  [ByteValue] (Byte) primitive; 153 {System.Byte}
            '  [DateTimeValue] (DateTime) primitive; 5/11/2013 4:32:00 PM {System.DateTime}
            '  [DoubleValue] (Double) primitive; -8.93178007363702E+27 {System.Double}
            '  [EnumerationValue] (Int32) primitive; 0 {System.Int32}
            '  [ExpandedNodeIdValue] (ExpandedNodeId) structured
            '    [NamespaceURI] (CharArray) primitive; "http://samples.org/UA/memorybuffer/Instance" {System.String}
            '    [NamespaceURISpecified] (Bit) primitive; True {System.Boolean}
            '    [NodeIdType] (NodeIdType) enumeration; 3 (String)
            '    [ServerIndexSpecified] (Bit) primitive; False {System.Boolean}
            '    [String] (StringNodeId) structured
            '      [Identifier] (CharArray) primitive; "????" {System.String}
            '      [NamespaceIndex] (UInt16) primitive; 0 {System.UInt16}
            '  [FloatValue] (Float) primitive; 78.37176 {System.Single}
            '  [GuidValue] (Guid) primitive; 8129cdaf-24d9-8140-64f2-3a6d7a957fd7 {System.Guid}
            '  [Int16Value] (Int16) primitive; 2793 {System.Int16}
            '  [Int32Value] (Int32) primitive; 1133391074 {System.Int32}
            '  [Int64Value] (Int64) primitive; -1039109760798965779 {System.Int64}
            '  [Integer] (Variant) structured
            '    [ArrayDimensionsSpecified] sequence[1]
            '      [0] (Bit) primitive; False {System.Boolean}
            '    [ArrayLengthSpecified] sequence[1]
            '      [0] (Bit) primitive; False {System.Boolean}
            '    [Int64] sequence[1]
            '      [0] (Int64) primitive; 0 {System.Int64}
            '    [VariantType] sequence[6]
            '      [0] (Bit) primitive; False {System.Boolean}
            '      [1] (Bit) primitive; False {System.Boolean}
            '      [2] (Bit) primitive; False {System.Boolean}
            '      [3] (Bit) primitive; True {System.Boolean}
            '      [4] (Bit) primitive; False {System.Boolean}
            '      [5] (Bit) primitive; False {System.Boolean}
            '  [LocalizedTextValue] (LocalizedText) structured
            '    [Locale] (CharArray) primitive; "ko" {System.String}
            '    [LocaleSpecified] (Bit) primitive; True {System.Boolean}
            '    [Reserved1] sequence[6]
            '      [0] (Bit) primitive; False {System.Boolean}
            '      [1] (Bit) primitive; False {System.Boolean}
            '      [2] (Bit) primitive; False {System.Boolean}
            '      [3] (Bit) primitive; False {System.Boolean}
            '      [4] (Bit) primitive; False {System.Boolean}
            '      [5] (Bit) primitive; False {System.Boolean}
            '    [Text] (CharArray) primitive; "? ?? ??+ ??? ??) ?: ???? ?! ?!" {System.String}
            '    [TextSpecified] (Bit) primitive; True {System.Boolean}
            '  [NodeIdValue] (NodeId) structured                                                                               
        End Sub
    End Class
End Namespace
// Shows how to read complex data with OPC UA Complex Data plug-in.

class procedure ReadValue.Main;
var
  Client: _EasyUAClient;
  EndpointDescriptor: string;
  GenericObject: _UAGenericObject;
  NodeDescriptor: string;
  Value: OleVariant;
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 which returns complex data. This is done in the same way as regular reads - just the data
  // returned is different.

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

  // Display basic information about what we have read.
  WriteLn('value: ', Value);

  // We know that this node returns complex data, so it is a UAGenericObject.
  GenericObject := IUnknown(Value) as _UAGenericObject;

  // The actual data is in the GenericData property of the UAGenericObject.
  //
  // If we want to see the whole hierarchy of the received complex data, we can format it with the "V" (verbose)
  // specifier. In the debugger, you can view the same by displaying the private DebugView property.
  WriteLn;
  WriteLn(GenericObject.GenericData.ToString_2['V', nil]);

  // For processing the internals of the data, refer to examples for GenericData and DataType classes.

  // Example output (truncated):
  //
  //(ScalarValueDataType) structured
  //
  //(ScalarValueDataType) structured
  //  [BooleanValue] (Boolean) primitive; True {System.Boolean}
  //  [ByteStringValue] (ByteString) primitive; System.Byte[] {System.Byte[]}
  //  [ByteValue] (Byte) primitive; 153 {System.Byte}
  //  [DateTimeValue] (DateTime) primitive; 5/11/2013 4:32:00 PM {System.DateTime}
  //  [DoubleValue] (Double) primitive; -8.93178007363702E+27 {System.Double}
  //  [EnumerationValue] (Int32) primitive; 0 {System.Int32}
  //  [ExpandedNodeIdValue] (ExpandedNodeId) structured
  //    [NamespaceURI] (CharArray) primitive; "http://samples.org/UA/memorybuffer/Instance" {System.String}
  //    [NamespaceURISpecified] (Bit) primitive; True {System.Boolean}
  //    [NodeIdType] (NodeIdType) enumeration; 3 (String)
  //    [ServerIndexSpecified] (Bit) primitive; False {System.Boolean}
  //    [String] (StringNodeId) structured
  //      [Identifier] (CharArray) primitive; "????" {System.String}
  //      [NamespaceIndex] (UInt16) primitive; 0 {System.UInt16}
  //  [FloatValue] (Float) primitive; 78.37176 {System.Single}
  //  [GuidValue] (Guid) primitive; 8129cdaf-24d9-8140-64f2-3a6d7a957fd7 {System.Guid}
  //  [Int16Value] (Int16) primitive; 2793 {System.Int16}
  //  [Int32Value] (Int32) primitive; 1133391074 {System.Int32}
  //  [Int64Value] (Int64) primitive; -1039109760798965779 {System.Int64}
  //  [Integer] (Variant) structured
  //    [ArrayDimensionsSpecified] sequence[1]
  //      [0] (Bit) primitive; False {System.Boolean}
  //    [ArrayLengthSpecified] sequence[1]
  //      [0] (Bit) primitive; False {System.Boolean}
  //    [Int64] sequence[1]
  //      [0] (Int64) primitive; 0 {System.Int64}
  //    [VariantType] sequence[6]
  //      [0] (Bit) primitive; False {System.Boolean}
  //      [1] (Bit) primitive; False {System.Boolean}
  //      [2] (Bit) primitive; False {System.Boolean}
  //      [3] (Bit) primitive; True {System.Boolean}
  //      [4] (Bit) primitive; False {System.Boolean}
  //      [5] (Bit) primitive; False {System.Boolean}
  //  [LocalizedTextValue] (LocalizedText) structured
  //    [Locale] (CharArray) primitive; "ko" {System.String}
  //    [LocaleSpecified] (Bit) primitive; True {System.Boolean}
  //    [Reserved1] sequence[6]
  //      [0] (Bit) primitive; False {System.Boolean}
  //      [1] (Bit) primitive; False {System.Boolean}
  //      [2] (Bit) primitive; False {System.Boolean}
  //      [3] (Bit) primitive; False {System.Boolean}
  //      [4] (Bit) primitive; False {System.Boolean}
  //      [5] (Bit) primitive; False {System.Boolean}
  //    [Text] (CharArray) primitive; "? ?? ??+ ??? ??) ?: ???? ?! ?!" {System.String}
  //    [TextSpecified] (Bit) primitive; True {System.Boolean}
  //  [NodeIdValue] (NodeId) structured

end;
// Shows how to read complex data with OPC UA Complex Data plug-in.

// 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 = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");

// Read a node which returns complex data. This is done in the same way as regular reads - just the data
// returned is different.

try
{
    $Value = $Client->ReadValue($EndpointDescriptor, $NodeDescriptor);
}
catch (com_exception $e)
{
    printf("*** Failure: %s\n", $e->getMessage());
    Exit();
}

// Display basic information about what we have read.
printf("Value: %s\n", $Value);

// We know that this node returns complex data, so it is a UAGenericObject.
$GenericObject = $Value;

// The actual data is in the GenericData property of the UAGenericObject.
//
// If we want to see the whole hierarchy of the received complex data, we can format it with the "V" (verbose)
// specifier. In the debugger, you can view the same by displaying the private DebugView property.
printf("\n");
printf("%s\n", $GenericObject->GenericData->ToString_3("V"));

// For processing the internals of the data, refer to examples for GenericData and DataType classes.

// Example output (truncated):
//
//(ScalarValueDataType) structured
//
//(ScalarValueDataType) structured
//  [BooleanValue] (Boolean) primitive; True {System.Boolean}
//  [ByteStringValue] (ByteString) primitive; System.Byte[] {System.Byte[]}
//  [ByteValue] (Byte) primitive; 153 {System.Byte}
//  [DateTimeValue] (DateTime) primitive; 5/11/2013 4:32:00 PM {System.DateTime}
//  [DoubleValue] (Double) primitive; -8.93178007363702E+27 {System.Double}
//  [EnumerationValue] (Int32) primitive; 0 {System.Int32}
//  [ExpandedNodeIdValue] (ExpandedNodeId) structured
//    [NamespaceURI] (CharArray) primitive; "http://samples.org/UA/memorybuffer/Instance" {System.String}
//    [NamespaceURISpecified] (Bit) primitive; True {System.Boolean}
//    [NodeIdType] (NodeIdType) enumeration; 3 (String)
//    [ServerIndexSpecified] (Bit) primitive; False {System.Boolean}
//    [String] (StringNodeId) structured
//      [Identifier] (CharArray) primitive; "????" {System.String}
//      [NamespaceIndex] (UInt16) primitive; 0 {System.UInt16}
//  [FloatValue] (Float) primitive; 78.37176 {System.Single}
//  [GuidValue] (Guid) primitive; 8129cdaf-24d9-8140-64f2-3a6d7a957fd7 {System.Guid}
//  [Int16Value] (Int16) primitive; 2793 {System.Int16}
//  [Int32Value] (Int32) primitive; 1133391074 {System.Int32}
//  [Int64Value] (Int64) primitive; -1039109760798965779 {System.Int64}
//  [Integer] (Variant) structured
//    [ArrayDimensionsSpecified] sequence[1]
//      [0] (Bit) primitive; False {System.Boolean}
//    [ArrayLengthSpecified] sequence[1]
//      [0] (Bit) primitive; False {System.Boolean}
//    [Int64] sequence[1]
//      [0] (Int64) primitive; 0 {System.Int64}
//    [VariantType] sequence[6]
//      [0] (Bit) primitive; False {System.Boolean}
//      [1] (Bit) primitive; False {System.Boolean}
//      [2] (Bit) primitive; False {System.Boolean}
//      [3] (Bit) primitive; True {System.Boolean}
//      [4] (Bit) primitive; False {System.Boolean}
//      [5] (Bit) primitive; False {System.Boolean}
//  [LocalizedTextValue] (LocalizedText) structured
//    [Locale] (CharArray) primitive; "ko" {System.String}
//    [LocaleSpecified] (Bit) primitive; True {System.Boolean}
//    [Reserved1] sequence[6]
//      [0] (Bit) primitive; False {System.Boolean}
//      [1] (Bit) primitive; False {System.Boolean}
//      [2] (Bit) primitive; False {System.Boolean}
//      [3] (Bit) primitive; False {System.Boolean}
//      [4] (Bit) primitive; False {System.Boolean}
//      [5] (Bit) primitive; False {System.Boolean}
//    [Text] (CharArray) primitive; "? ?? ??+ ??? ??) ?: ???? ?! ?!" {System.String}
//    [TextSpecified] (Bit) primitive; True {System.Boolean}
//  [NodeIdValue] (NodeId) structured

Rem This example shows how to read and display data of an attribute (value, timestamps, and status code).

Option Explicit

' Define which server and node 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/"
Dim nodeDescriptor: nodeDescriptor = _
    "nsu=http://test.org/UA/Data/ ;i=10239"  ' [ObjectsFolder]/Data.Static.Scalar.StructureValue

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

' Read a node which returns complex data. This is done in the same way as regular reads - just the data 
' returned is different.
On Error Resume Next
Dim Value: Set Value = Client.ReadValue(endpointDescriptor, nodeDescriptor)
If Err.Number <> 0 Then
    WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
    WScript.Quit
End If
On Error Goto 0

' Display basic information about what we have read.
WScript.Echo Value


' We know that this node returns complex data, so it is a UAGenericObject.
Dim GenericObject: Set GenericObject = Value

' The actual data is in the GenericData property of the UAGenericObject.
'
' If we want to see the whole hierarchy of the received complex data, we can format it with the "V" (verbose)
' specifier. In the debugger, you can view the same by displaying the private DebugView property.
WScript.Echo
WScript.Echo GenericObject.GenericData.ToString_2("V", Nothing)

' For processing the internals of the data, refer to examples for GenericData and DataType classes.


' Example output (truncated):
'
'(ScalarValueDataType) structured
'
'(ScalarValueDataType) structured   
'  [BooleanValue] (Boolean) primitive; True {System.Boolean}
'  [ByteStringValue] (ByteString) primitive; System.Byte[] {System.Byte[]}
'  [ByteValue] (Byte) primitive; 153 {System.Byte}
'  [DateTimeValue] (DateTime) primitive; 5/11/2013 4:32:00 PM {System.DateTime}
'  [DoubleValue] (Double) primitive; -8.93178007363702E+27 {System.Double}
'  [EnumerationValue] (Int32) primitive; 0 {System.Int32}
'  [ExpandedNodeIdValue] (ExpandedNodeId) structured
'    [NamespaceURI] (CharArray) primitive; "http://samples.org/UA/memorybuffer/Instance" {System.String}
'    [NamespaceURISpecified] (Bit) primitive; True {System.Boolean}
'    [NodeIdType] (NodeIdType) enumeration; 3 (String)
'    [ServerIndexSpecified] (Bit) primitive; False {System.Boolean}
'    [String] (StringNodeId) structured
'      [Identifier] (CharArray) primitive; "????" {System.String}
'      [NamespaceIndex] (UInt16) primitive; 0 {System.UInt16}
'  [FloatValue] (Float) primitive; 78.37176 {System.Single}
'  [GuidValue] (Guid) primitive; 8129cdaf-24d9-8140-64f2-3a6d7a957fd7 {System.Guid}
'  [Int16Value] (Int16) primitive; 2793 {System.Int16}
'  [Int32Value] (Int32) primitive; 1133391074 {System.Int32}
'  [Int64Value] (Int64) primitive; -1039109760798965779 {System.Int64}
'  [Integer] (Variant) structured
'    [ArrayDimensionsSpecified] sequence[1]
'      [0] (Bit) primitive; False {System.Boolean}
'    [ArrayLengthSpecified] sequence[1]
'      [0] (Bit) primitive; False {System.Boolean}
'    [Int64] sequence[1]
'      [0] (Int64) primitive; 0 {System.Int64}
'    [VariantType] sequence[6]
'      [0] (Bit) primitive; False {System.Boolean}
'      [1] (Bit) primitive; False {System.Boolean}
'      [2] (Bit) primitive; False {System.Boolean}
'      [3] (Bit) primitive; True {System.Boolean}
'      [4] (Bit) primitive; False {System.Boolean}
'      [5] (Bit) primitive; False {System.Boolean}
'  [LocalizedTextValue] (LocalizedText) structured
'    [Locale] (CharArray) primitive; "ko" {System.String}
'    [LocaleSpecified] (Bit) primitive; True {System.Boolean}
'    [Reserved1] sequence[6]
'      [0] (Bit) primitive; False {System.Boolean}
'      [1] (Bit) primitive; False {System.Boolean}
'      [2] (Bit) primitive; False {System.Boolean}
'      [3] (Bit) primitive; False {System.Boolean}
'      [4] (Bit) primitive; False {System.Boolean}
'      [5] (Bit) primitive; False {System.Boolean}
'    [Text] (CharArray) primitive; "? ?? ??+ ??? ??) ?: ???? ?! ?!" {System.String}
'    [TextSpecified] (Bit) primitive; True {System.Boolean}
'  [NodeIdValue] (NodeId) structured                                                                               
// This example shows different ways of constructing generic data.

using System;
using System.Collections;
using OpcLabs.BaseLib.DataTypeModel;

namespace UADocExamples.ComplexData._GenericData
{
    class _Construction
    {
        public static void Main1()
        {
            // Create enumeration data with value of 1.
            var enumerationData = new EnumerationData(1);
            Console.WriteLine(enumerationData);

            // Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
            var opaqueData1 = new OpaqueData(new byte[] {0xAA, 0x55}, sizeInBits:15);
            Console.WriteLine(opaqueData1);

            // Create opaque data from a bit array.
            var opaqueData2 = new OpaqueData(new BitArray(new[] { false, true, false, true, false }));
            Console.WriteLine(opaqueData2);

            // Create primitive data with System.Double value of 180.0.
            var primitiveData1 = new PrimitiveData(180.0d);
            Console.WriteLine(primitiveData1);

            // Create primitive data with System.String value.
            var primitiveData2 = new PrimitiveData("Temperature is too high!");
            Console.WriteLine(primitiveData2);

            // Create sequence data with two elements, using collection initializer syntax.
            var sequenceData1 = new SequenceData
            {
                opaqueData1,
                opaqueData2
            };
            Console.WriteLine(sequenceData1);

            // Create the same sequence data, using the Add method.
            var sequenceData2 = new SequenceData();
            sequenceData2.Elements.Add(opaqueData1);
            sequenceData2.Elements.Add(opaqueData2);
            Console.WriteLine(sequenceData2);

            // Create the same sequence data, using an array (an enumerable) of its elements.
            var sequenceData3 = new SequenceData(
                new GenericDataCollection(new[] {opaqueData1, opaqueData2}));
            Console.WriteLine(sequenceData3);

            // Create structured data with two members, using collection initializer syntax.
            var structuredData1 = new StructuredData
            {
                {"Message", primitiveData2},
                {"Status", enumerationData}
            };
            Console.WriteLine(structuredData1);

            // Create the same structured data using the Add method.
            var structuredData2 = new StructuredData();
            structuredData2.Add("Message", primitiveData2);
            structuredData2.Add("Status", enumerationData);
            Console.WriteLine(structuredData2);

            // Create union data.
            var unionData1 = new UnionData("DoubleField", primitiveData1);
            Console.WriteLine(unionData1);
        }
    }
}
# This example shows different ways of constructing generic data.

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

# Import .NET namespaces.
from System import *
from System.Collections import *
from OpcLabs.BaseLib.DataTypeModel import *


# Create enumeration data with value of 1.
enumerationData = EnumerationData(1)
print(enumerationData)

# Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
opaqueData1 = OpaqueData(
    [0xAA, 0x55],
    15) # sizeInBits
print(opaqueData1)

# Create opaque data from a bit array.
bitArray = BitArray(5)
bitArray[0] = False
bitArray[1] = True
bitArray[2] = False
bitArray[3] = True
bitArray[4] = False
opaqueData2 = OpaqueData(bitArray)
print(opaqueData2)

# Create primitive data with System.Double value of 180.0.
primitiveData1 = PrimitiveData(180.0)
print(primitiveData1)

# Create primitive data with System.String value.
primitiveData2 = PrimitiveData('Temperature is too high!')
print(primitiveData2)

# Create sequence data with two elements, using the Add method.
sequenceData2 = SequenceData()
sequenceData2.Elements.Add(opaqueData1)
sequenceData2.Elements.Add(opaqueData2)
print(sequenceData2)

# Create structured data with two members, using the Add method.
structuredData2 = StructuredData()
structuredData2.Add('Message', primitiveData2)
structuredData2.Add('Status', enumerationData)
print(structuredData2)

# Create union data.
unionData1 = UnionData('DoubleField', primitiveData1)
print(unionData1)

print()
print('Finished.')
' This example shows different ways of constructing generic data.

Imports System
Imports System.Collections
Imports OpcLabs.BaseLib.DataTypeModel

Namespace ComplexData._GenericData

    Friend Class _Construction

        Public Shared Sub Main1()
            ' Create enumeration data with value of 1.
            Dim enumerationData = New EnumerationData(1)
            Console.WriteLine(enumerationData)

            ' Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
            Dim opaqueData1 = New OpaqueData(New Byte() {170, 85}, sizeInBits:=15)
            Console.WriteLine(opaqueData1)

            ' Create opaque data from a bit array.
            Dim opaqueData2 = New OpaqueData(New BitArray(New Boolean() {False, True, False, True, False}))
            Console.WriteLine(opaqueData2)

            ' Create primitive data with System.Double value of 180.0.
            Dim primitiveData1 = New PrimitiveData(180)
            Console.WriteLine(primitiveData1)

            ' Create primitive data with System.String value.
            Dim primitiveData2 = New PrimitiveData("Temperature is too high!")
            Console.WriteLine(primitiveData2)

            ' Create sequence data with two elements, using collection initializer syntax.
            Dim sequenceData1 = New SequenceData() From {opaqueData1, opaqueData2}
            Console.WriteLine(sequenceData1)

            ' Create the same sequence data, using the Add method.
            Dim sequenceData2 = New SequenceData
            sequenceData2.Elements.Add(opaqueData1)
            sequenceData2.Elements.Add(opaqueData2)
            Console.WriteLine(sequenceData2)

            ' Create the same sequence data, using an array (an enumerable) of its elements.
            Dim sequenceData3 = New SequenceData(New GenericDataCollection(New OpaqueData() {opaqueData1, opaqueData2}))
            Console.WriteLine(sequenceData3)

            ' Create structured data with two members, using collection initializer syntax.
            Dim structuredData1 = New StructuredData() From { _
                {"Message", primitiveData2}, _
                {"Status", enumerationData}}
            Console.WriteLine(structuredData1)

            ' Create the same structured data using the Add method.
            Dim structuredData2 = New StructuredData()
            structuredData2.Add("Message", primitiveData2)
            structuredData2.Add("Status", enumerationData)
            Console.WriteLine(structuredData2)
        End Sub
    End Class
End Namespace
// This example shows different ways of constructing generic data.

class procedure _Construction.Main;
var
  ByteArray1, ByteArray2: OleVariant;
  EnumerationData: _EnumerationData;
  OpaqueData1, OpaqueData2: _OpaqueData;
  PrimitiveData1, PrimitiveData2: _PrimitiveData;
  SequenceData1: _SequenceData;
  StructuredData1: _StructuredData;
begin
  // Create enumeration data with value of 1.
  EnumerationData := CoEnumerationData.Create;
  EnumerationData.Value := 1;
  WriteLn(EnumerationData.ToString);

  // Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
  OpaqueData1 := CoOpaqueData.Create;
  ByteArray1 := VarArrayCreate([0, 1], varVariant);
  ByteArray1[0] := $AA;
  ByteArray1[1] := $55;
  OpaqueData1.SetByteArrayValue(ByteArray1, 15);
  WriteLn(OpaqueData1.ToString);
  // Create opaque data from an array of 1 bytes, specifying its size as 5 bits.
  OpaqueData2 := CoOpaqueData.Create;
  ByteArray2 := VarArrayCreate([0, 0], varVariant);
  ByteArray2[0] := $A;
  OpaqueData2.SetByteArrayValue(ByteArray2, 5);
  WriteLn(OpaqueData2.ToString);

  // Create primitive data with System.Double value of 180.0.
  PrimitiveData1 := CoPrimitiveData.Create;
  PrimitiveData1.Value := 180.0;
  WriteLn(PrimitiveData1.ToString);

  // Create primitive data with System.String value.
  PrimitiveData2 := CoPrimitiveData.Create;
  PrimitiveData2.Value := 'Temperature is too high!';
  WriteLn(PrimitiveData2.ToString);

  // Create sequence data with two elements, using the Add method.
  SequenceData1 := CoSequenceData.Create;
  SequenceData1.Elements.Add(OpaqueData1);
  SequenceData1.Elements.Add(OpaqueData2);
  WriteLn(SequenceData1.ToString);

  // Create structured data with two members, using the Add method.
  StructuredData1 := CoStructuredData.Create;
  StructuredData1.Add('Message', PrimitiveData2);
  StructuredData1.Add('Status', EnumerationData);
  WriteLn(StructuredData1.ToString);

  VarClear(ByteArray2);
  VarClear(ByteArray1);
end;
// This example shows different ways of constructing generic data.

// Create enumeration data with value of 1.
$EnumerationData = new COM("OpcLabs.BaseLib.DataTypeModel.EnumerationData");
$EnumerationData->Value = 1;
printf("%s\n", $EnumerationData);

// Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
$OpaqueData1 = new COM("OpcLabs.BaseLib.DataTypeModel.OpaqueData");
$ByteArray1[0] = 0xAA;
$ByteArray1[1] = 0x55;
$OpaqueData1->SetByteArrayValue($ByteArray1, 15);
printf("%s\n", $OpaqueData1);

// Create opaque data from a bit array.
$OpaqueData2 = new COM("OpcLabs.BaseLib.DataTypeModel.OpaqueData");
$BitArray = $OpaqueData2->Value;
$BitArray->Length = 5;
$BitArray->Set(0, false);
$BitArray->Set(1, true);
$BitArray->Set(2, false);
$BitArray->Set(3, true);
$BitArray->Set(4, false);
printf("%s\n", $OpaqueData2);

// Create primitive data with System.Double value of 180.0.
$PrimitiveData1 = new COM("OpcLabs.BaseLib.DataTypeModel.PrimitiveData");
$PrimitiveData1->Value = 180.0;
printf("%s\n", $PrimitiveData1);

// Create primitive data with System.String value.
$PrimitiveData2 = new COM("OpcLabs.BaseLib.DataTypeModel.PrimitiveData");
$PrimitiveData2->Value = "Temperature is too high!";
printf("%s\n", $PrimitiveData2);

// Create sequence data with two elements, using the Add method.
$SequenceData1 = new COM("OpcLabs.BaseLib.DataTypeModel.SequenceData");
$SequenceData1->Elements->Add($OpaqueData1);
$SequenceData1->Elements->Add($OpaqueData2);
printf("%s\n", $SequenceData1);

// Create structured data with two members, using the Add method.
$StructuredData1 = new COM("OpcLabs.BaseLib.DataTypeModel.StructuredData");
$StructuredData1->Add("Message", $PrimitiveData2);
$StructuredData1->Add("Status", $EnumerationData);
printf("%s\n", $StructuredData1);
Rem This example shows different ways of constructing generic data.

Option Explicit

' Create enumeration data with value of 1.
Dim EnumerationData: Set EnumerationData = CreateObject("OpcLabs.BaseLib.DataTypeModel.EnumerationData")
EnumerationData.Value = 1
WScript.Echo EnumerationData

' Create opaque data from an array of 2 bytes, specifying its size as 15 bits.
Dim OpaqueData1: Set OpaqueData1 = CreateObject("OpcLabs.BaseLib.DataTypeModel.OpaqueData")
OpaqueData1.SetByteArrayValue Array(&HAA, &H55), 15
WScript.Echo OpaqueData1

' Create opaque data from a bit array.
Dim OpaqueData2: Set OpaqueData2 = CreateObject("OpcLabs.BaseLib.DataTypeModel.OpaqueData")
Dim BitArray: Set BitArray = OpaqueData2.Value
BitArray.Length = 5
BitArray(0) = False
BitArray(1) = True
BitArray(2) = False
BitArray(3) = True
BitArray(4) = False
WScript.Echo OpaqueData2

' Create primitive data with System.Double value of 180.0.
Dim PrimitiveData1: Set PrimitiveData1 = CreateObject("OpcLabs.BaseLib.DataTypeModel.PrimitiveData")
PrimitiveData1.Value = 180.0
WScript.Echo PrimitiveData1

' Create primitive data with System.String value.
Dim PrimitiveData2: Set PrimitiveData2 = CreateObject("OpcLabs.BaseLib.DataTypeModel.PrimitiveData")
PrimitiveData2.Value = "Temperature is too high!"
WScript.Echo PrimitiveData2

' Create sequence data with two elements, using the Add method.
Dim SequenceData1: Set SequenceData1 = CreateObject("OpcLabs.BaseLib.DataTypeModel.SequenceData")
SequenceData1.Elements.Add OpaqueData1
SequenceData1.Elements.Add OpaqueData2
WScript.Echo SequenceData1

' Create structured data with two members, using the Add method.
Dim StructuredData1: Set StructuredData1 = CreateObject("OpcLabs.BaseLib.DataTypeModel.StructuredData")
StructuredData1.Add "Message", PrimitiveData2
StructuredData1.Add "Status", EnumerationData
WScript.Echo StructuredData1
// Shows how to process generic data type, displaying some of its properties, recursively.

using System;
using System.Collections.Generic;
using OpcLabs.BaseLib.DataTypeModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.ComplexData;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.ComplexData._GenericData
{
    class DataTypeKind1
    {
        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;
            }

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

        // Process the generic data type. Its structure can sometimes be quite deep, therefore we are limiting the depth
        // of the recursion using maximumDepth.
        public static void ProcessGenericData(GenericData genericData, int maximumDepth)
        {
            if (maximumDepth == 0)
                return;

            Console.WriteLine();
            Console.WriteLine("genericData.DataType: {0}", genericData.DataType);

            switch (genericData.DataTypeKind)
            {
                case DataTypeKind.Enumeration:
                    Console.WriteLine("The generic data is an enumeration.");
                    var enumerationData = (EnumerationData) genericData;
                    Console.WriteLine("Its value is {0}.", enumerationData.Value);
                    // There is also a ValueName that you can inspect (if known).
                    break;

                case DataTypeKind.Opaque:
                    Console.WriteLine("The generic data is opaque.");
                    var opaqueData = (OpaqueData) genericData;
                    Console.WriteLine("Its size is {0} bits.", opaqueData.SizeInBits);
                    Console.WriteLine("The data bytes are {0}.", BitConverter.ToString(opaqueData.ByteArray));
                    // Use the Value property (a BitArray) if you need to access the value bit by bit.
                    break;

                case DataTypeKind.Primitive:
                    Console.WriteLine("The generic data is primitive.");
                    var primitiveData = (PrimitiveData) genericData;
                    Console.WriteLine("Its value is \"{0}\".", primitiveData.Value);
                    break;

                case DataTypeKind.Sequence:
                    Console.WriteLine("The generic data is a sequence.");
                    var sequenceData = (SequenceData) genericData;
                    Console.WriteLine("It has {0} elements.", sequenceData.Elements.Count);
                    Console.WriteLine("A dump of the elements follows.");
                    foreach (GenericData element in sequenceData.Elements)
                        ProcessGenericData(element, maximumDepth - 1);
                    break;

                case DataTypeKind.Structured:
                    Console.WriteLine("The generic data is structured.");
                    var structuredData = (StructuredData) genericData;
                    Console.WriteLine("It has {0} field data members.", structuredData.FieldData.Count);
                    Console.WriteLine("The names of the fields are: {0}.",
                        String.Join(", ", structuredData.FieldData.Keys));

                    Console.WriteLine("A dump of each of the fields follows.");
                    foreach (KeyValuePair<string, GenericData> pair in structuredData.FieldData)
                    {
                        Console.WriteLine();
                        Console.WriteLine("Field name: {0}", pair.Key);
                        ProcessGenericData(pair.Value, maximumDepth - 1);
                    }
                    break;

                case DataTypeKind.Union:
                    Console.WriteLine("The generic data is a union.");
                    var unionData = (UnionData)genericData;
                    Console.WriteLine("The name of current field is: {0}", unionData.FieldName);
                    Console.WriteLine("Current field value is: {0}", unionData.FieldValue);
                    break;
            }
        }
    }
}
# Shows how to process generic data type, displaying some of its properties, recursively.

# 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 processGenericData(genericData, maximumDepth):
    if maximumDepth == 0:
        print('* Reached maximum depth *')
        return

    print()
    print('genericData.DataType: ', genericData.DataType, sep='')

    dataTypeKind = genericData.DataTypeKind
    if dataTypeKind == DataTypeKind.Enumeration:
        print('The generic data is an enumeration.')
        enumerationData = genericData
        print('Its value is ', enumerationData.Value, '.', sep='')
        # There is also a ValueName that you can inspect (if known).

    elif dataTypeKind == DataTypeKind.Opaque:
        print('The generic data is opaque.')
        opaqueData = genericData
        print('Its size is ', opaqueData.SizeInBits, ' bits.', sep='')
        print('The data bytes are ', BitConverter.ToString(opaqueData.ByteArray), '.', sep='')
        # Use the Value property (a BitArray) if you need to access the value bit by bit.

    elif dataTypeKind == DataTypeKind.Primitive:
        print('The generic data is primitive.')
        primitiveData = genericData
        print('Its value is "', primitiveData.Value, '".', sep='')

    elif dataTypeKind == DataTypeKind.Sequence:
        print('The generic data is a sequence.')
        sequenceData = genericData
        print('It has ', sequenceData.Elements.Count, ' elements.', sep='')
        print('A dump of the elements follows.')
        for element in sequenceData.Elements:
            processGenericData(element, maximumDepth - 1)

    elif dataTypeKind == DataTypeKind.Structured:
        print('The generic data is structured.')
        structuredData = genericData
        print('It has ', structuredData.FieldData.Count, ' field data members.', sep='')
        print('The names of the fields are: ', end='')
        for i, name in enumerate(structuredData.FieldData.Keys):
            if i != 0:
                print(', ', end='')
            print(name, end='')
        print('.')

        print('A dump of each of the fields follows.')
        for pair in structuredData.FieldData:
            print()
            print('Field name: ', pair.Key, sep='')
            processGenericData(pair.Value, maximumDepth - 1)

    elif dataTypeKind == DataTypeKind.Union:
        print('The generic data is a union.')
        unionData = genericData
        print('The name of current field is: ', unionData.FieldName, sep='')
        print('Current field value is: ', unionData.FieldValue, end='')


# 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.')

# Process the generic data type. We will inspect some of its properties, and dump them.
processGenericData(genericObject.GenericData, 3)

print()
print('Finished.')
' Shows how to process generic data type, displaying some of its properties, recursively.

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

Namespace ComplexData._GenericData

    Friend Class DataTypeKind1

        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

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


        ' Process the generic data type. Its structure can sometimes be quite deep, therefore we are limiting the depth
        ' of the recursion using maximumDepth.
        Public Shared Sub ProcessGenericData(ByVal genericData As GenericData, ByVal maximumDepth As Integer)
            If (maximumDepth = 0) Then
                Return
            End If

            Console.WriteLine()
            Console.WriteLine("genericData.DataType: {0}", genericData.DataType)

            Select Case (genericData.DataTypeKind)
                Case DataTypeKind.Enumeration
                    Console.WriteLine("The generic data is an enumeration.")
                    Dim enumerationData = CType(genericData, EnumerationData)
                    Console.WriteLine("Its value is {0}.", enumerationData.Value)
                    ' There is also a ValueName that you can inspect (if known).

                Case DataTypeKind.Opaque
                    Console.WriteLine("The generic data is opaque.")
                    Dim opaqueData = CType(genericData, OpaqueData)
                    Console.WriteLine("Its size is {0} bits.", opaqueData.SizeInBits)
                    Console.WriteLine("The data bytes are {0}.", BitConverter.ToString(opaqueData.ByteArray))
                    ' Use the Value property (a BitArray) if you need to access the value bit by bit.

                Case DataTypeKind.Primitive
                    Console.WriteLine("The generic data is primitive.")
                    Dim primitiveData = CType(genericData, PrimitiveData)
                    Console.WriteLine("Its value is ""{0}"".", primitiveData.Value)

                Case DataTypeKind.Sequence
                    Console.WriteLine("The generic data is a sequence.")
                    Dim sequenceData = CType(genericData, SequenceData)
                    Console.WriteLine("It has {0} elements.", sequenceData.Elements.Count)
                    Console.WriteLine("A dump of the elements follows.")
                    For Each element As GenericData In sequenceData.Elements
                        ProcessGenericData(element, (maximumDepth - 1))
                    Next

                Case DataTypeKind.Structured
                    Console.WriteLine("The generic data is structured.")
                    Dim structuredData = CType(genericData, StructuredData)
                    Console.WriteLine("It has {0} field data members.", structuredData.FieldData.Count)
                    Console.WriteLine("The names of the fields are: {0}.", String.Join(", ", structuredData.FieldData.Keys))

                    Console.WriteLine("A dump of each of the fields follows.")
                    For Each pair As KeyValuePair(Of String, GenericData) In structuredData.FieldData
                        Console.WriteLine()
                        Console.WriteLine("Field name: {0}", pair.Key)
                        ProcessGenericData(pair.Value, (maximumDepth - 1))
                    Next

                Case DataTypeKind.Union
                    Console.WriteLine("The generic data is union.")
                    Dim unionData = CType(genericData, UnionData)
                    Console.WriteLine("The name of current field is: {0}", unionData.FieldName)
                    Console.WriteLine("Current field value is: {0}", unionData.FieldValue)
            End Select

        End Sub
    End Class
End Namespace
// Shows how to process generic data type, displaying some of its properties, recursively

class procedure DataTypeKind1.Main;
var
  Client: _EasyUAClient;
  EndpointDescriptor: string;
  GenericObject: _UAGenericObject;
  NodeDescriptor: string;
begin
  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 := _UAGenericObject(IUnknown(Client.ReadValue(EndpointDescriptor, NodeDescriptor)));
  except
    on E: EOleException do
    begin
      WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
      Exit;
    end;
  end;

  // Process the generic data type. We will inspect some of its properties, and dump them.
  ProcessGenericData(GenericObject.GenericData, 2);
end;

Function VariantToBytes(Const Value: OleVariant): TBytes;
Var
  Size: Integer;
  pData: Pointer;
Begin
  Size := Succ(VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1));
  SetLength(Result, Size);
  pData := VarArrayLock(Value);
  Try
    Move(pData^, Pointer(Result)^, Size);
  Finally
    VarArrayUnlock(Value);
  End;
End;

class procedure DatatypeKind1.ProcessGenericData(GenericData: OpcLabs_BaseLib_TLB._GenericData; MaximumDepth: Cardinal);
var
  ByteArray: OleVariant;
  Count: Cardinal;
  Element: OleVariant;
  ElementEnumerator: IEnumVARIANT;
  EnumerationData: _EnumerationData;
  First: boolean;
  Keys: string;
  OpaqueData: _OpaqueData;
  PrimitiveData: _PrimitiveData;
  SequenceData: _SequenceData;
  StructuredData: _StructuredData;
  Value: OpcLabs_BaseLib_TLB._GenericData;
begin
  if MaximumDepth = 0 then
    Exit;

  WriteLn;
  WriteLn('genericData.DataType: ', GenericData.DataType.ToString);

  case GenericData.DataTypeKind of
    DataTypeKind_Enumeration:
      begin
        WriteLn('The generic data is an enumeration.');
        EnumerationData := GenericData as _EnumerationData;
        WriteLn(Format('Its value is %s.', [EnumerationData.Value.ToString]));
        // There is also a ValueName that you can inspect (if known).
      end;
    DataTypeKind_Opaque:
      begin
        WriteLn('The generic data is opaque.');
        OpaqueData := GenericData as _OpaqueData;
        WriteLn(Format('Its size is %d bits.', [OpaqueData.SizeInBits]));
        TVarData(ByteArray).VType := varArray;
        TVarData(ByteArray).VArray := PVarArray(OpaqueData.ByteArray);
        WriteLn(Format('The data bytes are %s.', [TEncoding.ANSI.GetString(VariantToBytes(ByteArray))]));
        // Use the Value property (a BitArray) if you need to access the value bit by bit.
      end;
    DataTypeKind_Primitive:
      begin
        WriteLn('The generic data is primitive.');
        PrimitiveData := GenericData as _PrimitiveData;
        WriteLn(Format('Its value is "%s".', [PrimitiveData.Value]));
      end;
    DataTypeKind_Sequence:
      begin
        WriteLn('The generic data is a sequence.');
        SequenceData := GenericData as _SequenceData;
        WriteLn(Format('It has %s elements.', [SequenceData.Elements.Count.ToString]));
        WriteLn('A dump of the elements follows.');
        ElementEnumerator := SequenceData.Elements.GetEnumerator;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          ProcessGenericData(IUnknown(Element) as OpcLabs_BaseLib_TLB._GenericData, MaximumDepth - 1);
        end;
      end;
    DataTypeKind_Structured:
      begin
        WriteLn('The generic data is structured.');
        StructuredData := GenericData as _StructuredData;
        WriteLn(Format('It has %s field data members.', [StructuredData.FieldData.Count.ToString]));
        ElementEnumerator := StructuredData.FieldData.GetEnumerator;
        Keys := '';
        First := True;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          if First then
            First := False
          else
            Keys := Keys + ', ';
          Keys := Keys + Element.Key;
        end;
        WriteLn(Format('The names of the fields are: %s.', [Keys]));

        WriteLn('A dump of each of the fields follows.');
        ElementEnumerator := StructuredData.FieldData.GetEnumerator;
        while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
        begin
          WriteLn;
          WriteLn(Format('Field name: %s', [Element.Key]));
          Value := IUnknown(Element.Value) as OpcLabs_BaseLib_TLB._GenericData;
          ProcessGenericData(Value, MaximumDepth - 1);
        end;
      end;
  end;

end;

Inheritance Hierarchy

System.Object
   OpcLabs.BaseLib.Object2
      OpcLabs.BaseLib.Info
         OpcLabs.BaseLib.DataTypeModel.GenericData
            OpcLabs.BaseLib.DataTypeModel.EnumerationData
            OpcLabs.BaseLib.DataTypeModel.OpaqueData
            OpcLabs.BaseLib.DataTypeModel.PrimitiveData
            OpcLabs.BaseLib.DataTypeModel.SequenceData
            OpcLabs.BaseLib.DataTypeModel.StructuredData
            OpcLabs.BaseLib.DataTypeModel.UnionData

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