The following example shows how a data type can be processed.
// 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 . 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 Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python . # 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 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 . 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 . 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;
Copyright © 2004-2024 CODE Consulting and Development, s.r.o., Plzen. All rights reserved. Web page: www.opclabs.com
Send Documentation Feedback. Resources: Knowledge Base, Product Downloads. Technical support: Online Forums, FAQ.Missing some example? Ask us for it on our Online Forums! You do not have to own a commercial license in order to use Online Forums, and we reply to every post.