// Shows how to process a data type, displaying some of its properties, recursively.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
using System;
using System.Linq;
using OpcLabs.BaseLib.DataTypeModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.ComplexData;
using OpcLabs.EasyOpc.UA.OperationModel;
namespace UADocExamples.ComplexData._DataType
{
class Kind
{
public static void Main1()
{
// Define which server and node we will work with.
UAEndpointDescriptor endpointDescriptor =
"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
// or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
// or "https://opcua.demo-this.com:51212/UA/SampleServer/"
UANodeDescriptor nodeDescriptor =
"nsu=http://test.org/UA/Data/ ;i=10239"; // [ObjectsFolder]/Data.Static.Scalar.StructureValue
// Instantiate the client object.
var client = new EasyUAClient();
// Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
UAGenericObject genericObject;
try
{
genericObject = (UAGenericObject)client.ReadValue(endpointDescriptor, nodeDescriptor);
}
catch (UAException uaException)
{
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
return;
}
// The data type is in the GenericData.DataType property of the UAGenericObject.
DataType dataType = genericObject.GenericData.DataType;
// Process the data type. We will inspect some of its properties, and dump them.
ProcessDataType(dataType, maximumDepth: 3);
}
// Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with,
// it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
public static void ProcessDataType(DataType dataType, int maximumDepth)
{
if (maximumDepth == 0)
return;
Console.WriteLine();
Console.WriteLine("dataType.Name: {0}", dataType.Name);
switch (dataType.Kind)
{
case DataTypeKind.Enumeration:
Console.WriteLine("The data type is an enumeration.");
var enumerationDataType = (EnumerationDataType) dataType;
Console.WriteLine("It has {0} enumeration members.", enumerationDataType.EnumerationMembers.Count);
Console.WriteLine("The names of the enumeration members are: {0}.",
String.Join(", ", enumerationDataType.EnumerationMembers.Select(member => member.Name)));
// Here you can process the members, or inspect SizeInBits etc.
break;
case DataTypeKind.Opaque:
Console.WriteLine("The data type is opaque.");
var opaqueDataType = (OpaqueDataType) dataType;
Console.WriteLine("Its size is {0} bits.", opaqueDataType.SizeInBits);
// There isn't much more you can learn about an opaque data type (well, it may have Description and
// other common members). It is, after all, opaque...
break;
case DataTypeKind.Primitive:
Console.WriteLine("The data type is primitive.");
var primitiveDataType = (PrimitiveDataType) dataType;
Console.WriteLine("Its .NET value type is \"{0}\".", primitiveDataType.ValueType);
// There isn't much more you can learn about the primitive data type.
break;
case DataTypeKind.Sequence:
Console.WriteLine("The data type is a sequence.");
var sequenceDataType = (SequenceDataType) dataType;
Console.WriteLine("Its length is {0} (-1 means that the length can vary).", sequenceDataType.Length);
Console.WriteLine("A dump of the element data type follows.");
ProcessDataType(sequenceDataType.ElementDataType, maximumDepth - 1);
break;
case DataTypeKind.Structured:
Console.WriteLine("The data type is structured.");
var structuredDataType = (StructuredDataType) dataType;
Console.WriteLine("It has {0} data fields.", structuredDataType.DataFields.Count);
Console.WriteLine("The names of the data fields are: {0}.",
String.Join(", ", structuredDataType.DataFields.Select(field => field.Name)));
Console.WriteLine("A dump of each of the data fields follows.");
foreach (DataField dataField in structuredDataType.DataFields)
{
Console.WriteLine();
Console.WriteLine("dataField.Name: {0}", dataField.Name);
// Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
// be of interest, but we are not dumping them here.
ProcessDataType(dataField.DataType, maximumDepth - 1);
}
break;
case DataTypeKind.Union:
Console.WriteLine("The data type is union.");
var unionDataType = (UnionDataType)dataType;
Console.WriteLine("It has {0} data fields.", unionDataType.DataFields.Count);
Console.WriteLine("The names of the data fields are: {0}.",
String.Join(", ", unionDataType.DataFields.Select(field => field.Name)));
break;
}
}
}
}
' Shows how to process a data type, displaying some of its properties, recursively.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.
Imports System
Imports System.Linq
Imports OpcLabs.BaseLib.DataTypeModel
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.ComplexData
Imports OpcLabs.EasyOpc.UA.OperationModel
Namespace ComplexData._DataType
Friend Class Kind
Public Shared Sub Main1()
' Define which server we will work with.
Dim endpointDescriptor As UAEndpointDescriptor =
"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
' or "https://opcua.demo-this.com:51212/UA/SampleServer/"
' Define which node we will work with.
Dim nodeDescriptor As UANodeDescriptor = _
"nsu=http://test.org/UA/Data/ ;i=10239" ' [ObjectsFolder]/Data.Static.Scalar.StructureValue
' Instantiate the client object.
Dim client = New EasyUAClient
' Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
Dim genericObject As UAGenericObject
Try
genericObject = CType(client.ReadValue(endpointDescriptor, nodeDescriptor), UAGenericObject)
Catch uaException As UAException
Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
Exit Sub
End Try
' The data type is in the GenericData.DataType property of the UAGenericObject.
Dim dataType As DataType = genericObject.GenericData.DataType
' Process the data type. We will inspect some of its properties, and dump them.
ProcessDataType(dataType, maximumDepth:=2)
End Sub
' Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with,
' it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
Public Shared Sub ProcessDataType(dataType As DataType, ByVal maximumDepth As Integer)
If (maximumDepth = 0) Then
Return
End If
Console.WriteLine()
Console.WriteLine("dataType.Name: {0}", dataType.Name)
Select Case (dataType.Kind)
Case DataTypeKind.Enumeration
Console.WriteLine("The data type is an enumeration.")
Dim enumerationDataType = CType(dataType, EnumerationDataType)
Console.WriteLine("It has {0} enumeration members.", enumerationDataType.EnumerationMembers.Count)
Console.WriteLine("The names of the enumeration members are: {0}.", _
String.Join(", ", enumerationDataType.EnumerationMembers.Select(Function(member) member.Name)))
' Here you can process the members, or inspect SizeInBits etc.
Case DataTypeKind.Opaque
Console.WriteLine("The data type is opaque.")
Dim opaqueDataType = CType(dataType, OpaqueDataType)
Console.WriteLine("Its size is {0} bits.", opaqueDataType.SizeInBits)
' There isn't much more you can learn about an opaque data type (well, it may have Description and
' other common members). It is, after all, opaque...
Case DataTypeKind.Primitive
Console.WriteLine("The data type is primitive.")
Dim primitiveDataType = CType(dataType, PrimitiveDataType)
Console.WriteLine("Its .NET value type is ""{0}"".", primitiveDataType.ValueType)
' There isn't much more you can learn about the primitive data type.
Case DataTypeKind.Sequence
Console.WriteLine("The data type is a sequence.")
Dim sequenceDataType = CType(dataType, SequenceDataType)
Console.WriteLine("Its length is {0} (-1 means that the length can vary).", sequenceDataType.Length)
Console.WriteLine("A dump of the element data type follows.")
ProcessDataType(sequenceDataType.ElementDataType, (maximumDepth - 1))
Case DataTypeKind.Structured
Console.WriteLine("The data type is structured.")
Dim structuredDataType = CType(dataType, StructuredDataType)
Console.WriteLine("It has {0} data fields.", structuredDataType.DataFields.Count)
Console.WriteLine("The names of the data fields are: {0}.", _
String.Join(", ", structuredDataType.DataFields.Select(Function(field) field.Name)))
Console.WriteLine("A dump of each of the data fields follows.")
For Each dataField As DataField In structuredDataType.DataFields
Console.WriteLine()
Console.WriteLine("dataField.Name: {0}", dataField.Name)
' Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
' be of interest but we are not dumping them here.
ProcessDataType(dataField.DataType, (maximumDepth - 1))
Next
Case DataTypeKind.Union
Console.WriteLine("The data type is union.")
Dim unionDataType = CType(dataType, UnionDataType)
Console.WriteLine("It has {0} data fields.", unionDataType.DataFields.Count)
Console.WriteLine("The names of the data fields are: {0}.",
String.Join(", ", unionDataType.DataFields.Select(Function(field) field.Name)))
End Select
End Sub
End Class
End Namespace
// Shows how to process a data type, displaying some of its properties, recursively.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
class procedure Kind.Main;
var
Client: _EasyUAClient;
DataType: OpcLabs_BaseLib_TLB._DataType;
EndpointDescriptor: string;
GenericObject: _UAGenericObject;
NodeDescriptor: string;
begin
// Define which server and node we will work with.
EndpointDescriptor :=
//'http://opcua.demo-this.com:51211/UA/SampleServer';
//'https://opcua.demo-this.com:51212/UA/SampleServer/';
'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
NodeDescriptor := 'nsu=http://test.org/UA/Data/ ;i=10239'; // [ObjectsFolder]/Data.Static.Scalar.StructureValue
// Instantiate the client object
Client := CoEasyUAClient.Create;
// Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
try
GenericObject := IUnknown(Client.ReadValue(EndpointDescriptor, NodeDescriptor)) as _UAGenericObject;
except
on E: EOleException do
begin
WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
Exit;
end;
end;
// The data type is in the GenericData.DataType property of the UAGenericObject.
DataType := genericObject.GenericData.DataType;
// Process the data type. We will inspect some of its properties, and dump them.
ProcessDataType(DataType, 2);
end;
// Process the data type. It can be recursive in itself, so if you do not know the data type you are dealing with,
// it is recommended to make safeguards against infinite looping or recursion - here, the maximumDepth.
class procedure Kind.ProcessDataType(DataType: OpcLabs_BaseLib_TLB._DataType; MaximumDepth: Cardinal);
var
Count: Cardinal;
DataField: _DataField;
Element: OleVariant;
ElementEnumerator: IEnumVARIANT;
EnumerationMember: _EnumerationMember;
EnumerationDataType: _EnumerationDataType;
FieldNames: string;
First: boolean;
MemberNames: string;
OpaqueDataType: _OpaqueDataType;
PrimitiveDataType: _PrimitiveDataType;
SequenceDataType: _SequenceDataType;
StructuredDataType: _StructuredDataType;
TypeName: WideString;
begin
if MaximumDepth = 0 then
Exit;
WriteLn;
WriteLn('dataType.Name: ', DataType.Name);
case DataType.Kind of
DataTypeKind_Enumeration:
begin
WriteLn('The data type is an enumeration.');
EnumerationDataType := DataType as _EnumerationDataType;
WriteLn(Format('It has %s enumeration members.', [EnumerationDataType.EnumerationMembers.Count]));
ElementEnumerator := EnumerationDataType.EnumerationMembers.GetEnumerator;
MemberNames := '';
First := True;
while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
begin
EnumerationMember := IUnknown(Element) as _EnumerationMember;
if First then
First := False
else
MemberNames := MemberNames + ', ';
MemberNames := MemberNames + EnumerationMember.Name;
end;
WriteLn(Format('The names of the enumeration members are: %s.', [MemberNames]));
// Here you can process the members, or inspect SizeInBits etc.
end;
DataTypeKind_Opaque:
begin
WriteLn('The data type is opaque.');
OpaqueDataType := DataType as _OpaqueDataType;
WriteLn(Format('Its size is %s bits.', [OpaqueDataType.SizeInBits]));
// There isn't much more you can learn about an opaque data type (well, it may have Description and
// other common members). It is, after all, opaque...
end;
DataTypeKind_Primitive:
begin
WriteLn('The data type is primitive.');
PrimitiveDataType := DataType as _PrimitiveDataType;
PrimitiveDataType.ValueType.Get_ToString(TypeName);
WriteLn(Format('Its .NET value type is "%s".', [TypeName]));
// There isn't much more you can learn about the primitive data type.
end;
DataTypeKind_Sequence:
begin
WriteLn('The data type is a sequence.');
SequenceDataType := DataType as _SequenceDataType;
WriteLn(Format('Its length is %s (-1 means that the length can vary).', [SequenceDataType.Length.ToString]));
WriteLn('A dump of the element data type follows.');
ProcessDataType(SequenceDataType.ElementDataType, MaximumDepth - 1);
end;
DataTypeKind_Structured:
begin
WriteLn('The data type is structured.');
StructuredDataType := DataType as _StructuredDataType;
WriteLn(Format('It has %s data fields.', [StructuredDataType.DataFields.Count.ToString]));
ElementEnumerator := StructuredDataType.DataFields.GetEnumerator;
FieldNames := '';
First := True;
while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
begin
if First then
First := False
else
FieldNames := FieldNames + ', ';
FieldNames := FieldNames + Element.Name;
end;
WriteLn(Format('The names of the data fields are: %s.', [FieldNames]));
WriteLn('A dump of each of the data fields follows.');
ElementEnumerator := StructuredDataType.DataFields.GetEnumerator;
while (ElementEnumerator.Next(1, Element, Count) = S_OK) do
begin
DataField := IUnknown(Element) as _DataField;
WriteLn;
WriteLn(Format('dataField.Name: %s', [DataField.Name]));
// Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
// be of interest but we are not dumping them here.
ProcessDataType(DataField.DataType, MaximumDepth - 1);
end;
end;
end;
end;
# Shows how to process a data type, displaying some of its properties, recursively.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
# Import .NET namespaces.
from System import *
from OpcLabs.BaseLib.DataTypeModel import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *
def processDataType(dataType, maximumDepth):
if maximumDepth == 0:
print('* Reached maximum depth *')
return
print()
print('dataType.Name: ', dataType.Name, sep='')
if dataType.Kind == DataTypeKind.Enumeration:
print('The data type is an enumeration.')
enumerationDataType = dataType
print('It has ', enumerationDataType.EnumerationMembers.Count, ' enumeration members.', sep='')
print('The names of the enumeration members are: ', end='')
for i, member in enumerate(enumerationDataType.EnumerationMembers):
if i != 0:
print(', ', end='')
print(member.Name, end='')
print('.')
# Here you can process the members, or inspect SizeInBits etc.
elif dataType.Kind == DataTypeKind.Opaque:
print('The data type is opaque.')
opaqueDataType = dataType
print('Its size is ', opaqueDataType.SizeInBits, ' bits.', sep='')
# There isn't much more you can learn about an opaque data type (well, it may have Description and
# other common members). It is, after all, opaque...
elif dataType.Kind == DataTypeKind.Primitive:
print('The data type is primitive.')
primitiveDataType = dataType
print('Its .NET value type is "', primitiveDataType.ValueType, '".', sep='')
# There isn't much more you can learn about the primitive data type.
elif dataType.Kind == DataTypeKind.Sequence:
print('The data type is a sequence.')
sequenceDataType = dataType
print('Its length is ', sequenceDataType.Length, ' (-1 means that the length can vary).', sep='')
print('A dump of the element data type follows.')
processDataType(sequenceDataType.ElementDataType, maximumDepth - 1)
elif dataType.Kind == DataTypeKind.Structured:
print('The data type is structured.')
structuredDataType = dataType
print('It has ', structuredDataType.DataFields.Count, ' data fields.', sep='')
print('The names of the data fields are: ', end='')
for i, field in enumerate(structuredDataType.DataFields):
if i != 0:
print(', ', end='')
print(field.Name, end='')
print('.')
print('A dump of each of the data fields follows.')
for dataField in structuredDataType.DataFields:
print()
print('dataField.Name: ', dataField.Name, sep='')
# Note that every data field also has properties like IsLength, IsOptional, IsSwitch which might
# be of interest, but we are not dumping them here.
processDataType(dataField.DataType, maximumDepth - 1)
elif dataType.Kind == DataTypeKind.Union:
print('The data type is union.')
unionDataType = dataType
print('It has ', unionDataType.DataFields.Count, ' data fields.', sep='')
print('The names of the data fields are: ', end='')
for i, field in enumerate(unionDataType.DataFields):
if i != 0:
print(', ', end='')
print(field.Name, end='')
print('.')
# Define which server and node we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'
# [ObjectsFolder]/Data.Static.Scalar.StructureValue
nodeDescriptor = UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10239')
# Instantiate the client object.
client = EasyUAClient()
# Read a node. We know that this node returns complex data, so we can type cast to UAGenericObject.
try:
print('Reading...')
genericObject = IEasyUAClientExtension.ReadValue(client, endpointDescriptor, nodeDescriptor)
except UAException as uaException:
print('*** Failure: ' + uaException.GetBaseException().Message)
exit()
print('Reading successful.')
# The data type is in the GenericData.DataType property of the UAGenericObject.
dataType = genericObject.GenericData.DataType
# Process the data type. We will inspect some of its properties, and dump them.
processDataType(dataType, 3)
print()
print('Finished.')
// Shows how to obtain object describing the data type of complex data node with OPC UA Complex Data plug-in.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
using System;
using 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.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.
Imports System
Imports 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.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
class procedure 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.
Rem
Rem Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
Rem OPC client and subscriber examples in VBScript on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBScript .
Rem Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
Rem a commercial license in order to use Online Forums, and we reply to every post.
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 object describing the data type of complex data node with OPC UA Complex Data plug-in.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
# Import .NET namespaces.
from 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.')