![](dotnetdiagramimages/OpcLabs_BaseLib_OpcLabs_BaseLib_DataTypeModel_GenericDataCollection.png)
'Declaration
<ComDefaultInterfaceAttribute(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection)> <ComVisibleAttribute(True)> <GuidAttribute("9C514E81-3899-4E88-BA29-E200B2B3770A")> <TypeConverterAttribute(System.ComponentModel.CollectionConverter)> <DefaultMemberAttribute("Item")> <DebuggerTypeProxyAttribute(System.Collections.Generic.Mscorlib_CollectionDebugView`1)> <DebuggerDisplayAttribute("Count = {Count}")> <SerializableAttribute()> Public NotInheritable Class GenericDataCollection Inherits System.Collections.ObjectModel.Collection(Of GenericData) Implements OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection, System.Collections.Generic.ICollection(Of GenericData), System.Collections.Generic.IEnumerable(Of GenericData), System.Collections.Generic.IList(Of GenericData), System.Collections.Generic.IReadOnlyCollection(Of GenericData), System.Collections.Generic.IReadOnlyList(Of GenericData), System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
'Usage
Dim instance As GenericDataCollection
[ComDefaultInterface(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection)] [ComVisible(true)] [Guid("9C514E81-3899-4E88-BA29-E200B2B3770A")] [TypeConverter(System.ComponentModel.CollectionConverter)] [DefaultMember("Item")] [DebuggerTypeProxy(System.Collections.Generic.Mscorlib_CollectionDebugView`1)] [DebuggerDisplay("Count = {Count}")] [Serializable()] public sealed class GenericDataCollection : System.Collections.ObjectModel.Collection<GenericData>, OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection, System.Collections.Generic.ICollection<GenericData>, System.Collections.Generic.IEnumerable<GenericData>, System.Collections.Generic.IList<GenericData>, System.Collections.Generic.IReadOnlyCollection<GenericData>, System.Collections.Generic.IReadOnlyList<GenericData>, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
[ComDefaultInterface(OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection)] [ComVisible(true)] [Guid("9C514E81-3899-4E88-BA29-E200B2B3770A")] [TypeConverter(System.ComponentModel.CollectionConverter)] [DefaultMember("Item")] [DebuggerTypeProxy(System.Collections.Generic.Mscorlib_CollectionDebugView`1)] [DebuggerDisplay("Count = {Count}")] [Serializable()] public ref class GenericDataCollection sealed : public System.Collections.ObjectModel.Collection<GenericData>, OpcLabs.BaseLib.DataTypeModel.ComTypes._GenericDataCollection, System.Collections.Generic.ICollection<GenericData>, System.Collections.Generic.IEnumerable<GenericData>, System.Collections.Generic.IList<GenericData>, System.Collections.Generic.IReadOnlyCollection<GenericData>, System.Collections.Generic.IReadOnlyList<GenericData>, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
Relation of SequenceData and its constituents is shown on the following picture:
.
// Shows how to write 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 WriteValue { 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. // We know that this node returns complex data, so we can type cast to UAGenericObject. Console.WriteLine("Reading..."); UAGenericObject genericObject; try { genericObject = (UAGenericObject)client.ReadValue(endpointDescriptor, nodeDescriptor); } catch (UAException uaException) { Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message); return; } // Modify the data read. // This node returns one of the two data types, randomly (this is not common, usually the type is fixed). The // data types are sub-types of one common type which the data type of the node. We therefore use the data type // ID in the returned UAGenericObject to detect which data type has been returned. // For processing the internals of the data, refer to examples for GenericData and DataType classes. // We know how the data is structured, and have hard-coded a logic that modifies certain values inside. It is // also possible to discover the structure of the data type in the program, and write generic clients that can // cope with any kind of complex data. // // Note that the code below is not fully robust - it will throw an exception if the data is not as expected. Console.WriteLine("Modifying..."); Console.WriteLine(genericObject.DataTypeId); if (genericObject.DataTypeId.NodeDescriptor.Match("nsu=http://test.org/UA/Data/ ;i=9440")) // ScalarValueDataType { // Negate the byte in the "ByteValue" field. var structuredData = (StructuredData)genericObject.GenericData; var byteValue = (PrimitiveData)structuredData.FieldData["ByteValue"]; byteValue.Value = (Byte)~((Byte)byteValue.Value); Console.WriteLine(byteValue.Value); } else if (genericObject.DataTypeId.NodeDescriptor.Match("nsu=http://test.org/UA/Data/ ;i=9669")) // ArrayValueDataType { // Negate bytes at indexes 0 and 1 of the array in the "ByteValue" field. var structuredData = (StructuredData)genericObject.GenericData; var byteValue = (SequenceData)structuredData.FieldData["ByteValue"]; var element0 = (PrimitiveData)byteValue.Elements[0]; var element1 = (PrimitiveData)byteValue.Elements[1]; element0.Value = (Byte)~((Byte)element0.Value); element1.Value = (Byte)~((Byte)element1.Value); Console.WriteLine(element0.Value); Console.WriteLine(element1.Value); } // Write the modified complex data back to the node. // The data type ID in the UAGenericObject is borrowed without change from what we have read, so that the server // knows which data type we are writing. The data type ID not necessary if writing precisely the same data type // as the node has (not a subtype). Console.WriteLine("Writing..."); try { client.WriteValue(endpointDescriptor, nodeDescriptor, genericObject); } catch (UAException uaException) { Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message); } } } }
# Shows how to write 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. # 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() # Modify the data read. # This node returns one of the two data types, randomly (this is not common, usually the type is fixed). The # data types are sub-types of one common type which the data type of the node. We therefore use the data type # ID in the returned UAGenericObject to detect which data type has been returned. # # For processing the internals of the data, refer to examples for GenericData and DataType classes. # We know how the data is structured, and have hard-coded a logic that modifies certain values inside. It is # also possible to discover the structure of the data type in the program, and write generic clients that can # cope with any kind of complex data. # # Note that the code below is not fully robust - it will throw an exception if the data is not as expected. print ('Modifying...') print(genericObject.DataTypeId) if genericObject.DataTypeId.NodeDescriptor.Match(UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=9440')): # ScalarValueDataType # Negate the byte in the "ByteValue" field. structuredData = genericObject.GenericData byteValue = structuredData.FieldData.get_Item('ByteValue') # PrimitiveData byteValue.Value = (~byteValue.Value) & 0xFF print(byteValue.Value) elif genericObject.DataTypeId.NodeDescriptor.Match(UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=9669')): # ArrayValueDataType # Negate bytes at indexes 0 and 1 of the array in the "ByteValue" field. structuredData = genericObject.GenericData byteValue = structuredData.FieldData.get_Item('ByteValue') # SequenceData element0 = byteValue.Elements.get_Item(0) # PrimitiveData element1 = byteValue.Elements.get_Item(1) # PrimitiveData element0.Value = (~element0.Value) & 0xFF element1.Value = (~element1.Value) & 0xFF print(element0.Value) print(element1.Value) # Write the modified complex data back to the node. # The data type ID in the UAGenericObject is borrowed without change from what we have read, so that the server # knows which data type we are writing. The data type ID not necessary if writing precisely the same data type # as the node has (not a subtype). try: print('Writing...') IEasyUAClientExtension.WriteValue(client, endpointDescriptor, nodeDescriptor, genericObject) except UAException as uaException: print('*** Failure: ' + uaException.GetBaseException().Message) print() print('Finished.')
' Shows how to write complex data with OPC UA Complex Data plug-in. Imports System Imports OpcLabs.BaseLib.DataTypeModel Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.ComplexData Imports OpcLabs.EasyOpc.UA.OperationModel Namespace ComplexData._EasyUAClient Friend Class WriteValue 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. ' We know that this node returns complex data, so we can type cast to UAGenericObject. Console.WriteLine("Reading...") 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 ' Modify the data read. ' This node returns one of the two data types, randomly (this is not common, usually the type is fixed). The ' data types are sub-types of one common type which the data type of the node. We therefore use the data type ' ID in the returned UAGenericObject to detect which data type has been returned. ' For processing the internals of the data, refer to examples for GenericData and DataType classes. ' We know how the data is structured, and have hard-coded a logic that modifies certain values inside. It is ' also possible to discover the structure of the data type in the program, and write generic clients that can ' cope with any kind of complex data. ' ' Note that the code below is not fully robust - it will throw an exception if the data is not as expected. Console.WriteLine("Modifying...") Console.WriteLine(genericObject.DataTypeId) If genericObject.DataTypeId.NodeDescriptor.Match("nsu=http://test.org/UA/Data/ ;i=9440") Then ' ScalarValueDataType ' Negate the byte in the "ByteValue" field. Dim structuredData = CType(genericObject.GenericData, StructuredData) Dim byteValue = CType(structuredData.FieldData("ByteValue"), PrimitiveData) byteValue.Value = CType(Not CType(byteValue.Value, Byte), Byte) Console.WriteLine(byteValue.Value) ElseIf genericObject.DataTypeId.NodeDescriptor.Match("nsu=http://test.org/UA/Data/ ;i=9669") Then ' ArrayValueDataType ' Negate bytes at indexes 0 and 1 of the array in the "ByteValue" field. Dim structuredData = CType(genericObject.GenericData, StructuredData) Dim byteValue = CType(structuredData.FieldData("ByteValue"), SequenceData) Dim element0 = CType(byteValue.Elements(0), PrimitiveData) Dim element1 = CType(byteValue.Elements(1), PrimitiveData) element0.Value = CType(Not CType(element0.Value, Byte), Byte) element1.Value = CType(Not CType(element1.Value, Byte), Byte) Console.WriteLine(element0.Value) Console.WriteLine(element1.Value) End If ' Write the modified complex data back to the node. ' The data type ID in the UAGenericObject is borrowed without change from what we have read, so that the server ' knows which data type we are writing. The data type ID not necessary if writing precisely the same data type ' as the node has (not a subtype). Console.WriteLine("Writing...") Try client.WriteValue(endpointDescriptor, nodeDescriptor, genericObject) Catch uaException As UAException Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message) Exit Sub End Try End Sub End Class End Namespace
// Shows how to write complex data with OPC UA Complex Data plug-in. class procedure WriteValue.Main; var ArrayValueDataType: _UANodeDescriptor; ByteValue: _PrimitiveData; ByteValue2: _SequenceData; Client: _EasyUAClient; Element0, Element1: _PrimitiveData; EndpointDescriptor: string; GenericObject: _UAGenericObject; NodeDescriptor: string; ScalarValueDataType: _UANodeDescriptor; StructuredData: _StructuredData; 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. // We know that this node returns complex data, so we can type cast to UAGenericObject. WriteLn('Reading...'); try GenericObject := _UAGenericObject(IUnknown(Client.ReadValue(EndpointDescriptor, NodeDescriptor))); except on E: EOleException do begin WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message])); Exit; end; end; // Modify the data read. // This node returns one of the two data types, randomly (this is not common, usually the type is fixed). The // data types are sub-types of one common type which the data type of the node. We therefore use the data type // ID in the returned UAGenericObject to detect which data type has been returned. // For processing the internals of the data, refer to examples for GenericData and DataType classes. // We know how the data is structured, and have hard-coded a logic that modifies certain values inside. It is // also possible to discover the structure of the data type in the program, and write generic clients that can // cope with any kind of complex data. // // Note that the code below is not fully robust - it will throw an exception if the data is not as expected. WriteLn('Modifying...'); WriteLn(GenericObject.DataTypeId.ToString); ScalarValueDataType := CoUANodeDescriptor.Create; ScalarValueDataType.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=9440'; // ScalarValueDataType if GenericObject.DataTypeId.NodeDescriptor.Match(ScalarValueDataType) then begin // Negate the byte in the "ByteValue" field. StructuredData := IUnknown(GenericObject.GenericData) as _StructuredData; ByteValue := IUnknown(StructuredData.FieldData['ByteValue']) as _PrimitiveData; ByteValue.Value := Byte(not (Byte(byteValue.Value))); WriteLn(ByteValue.Value); end else begin ArrayValueDataType := CoUANodeDescriptor.Create; ArrayValueDataType.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=9669'; // ArrayValueDataType if GenericObject.DataTypeId.Nodedescriptor.Match(ArrayValueDataType) then begin // Negate bytes at indexes 0 and 1 of the array in the "ByteValue" field. StructuredData := IUnknown(GenericObject.GenericData) as _StructuredData; ByteValue2 := IUnknown(StructuredData.FieldData['ByteValue']) as _SequenceData; Element0 := IUnknown(ByteValue2.Elements[0]) as _PrimitiveData; Element1 := IUnknown(ByteValue2.Elements[1]) as _PrimitiveData; Element0.Value := Byte(not (Byte(element0.Value))); Element1.Value := Byte(not (Byte(element1.Value))); WriteLn(Element0.Value); WriteLn(Element1.Value); end; end; // Write the modified complex data back to the node. // The data type ID in the UAGenericObject is borrowed without change from what we have read, so that the server // knows which data type we are writing. The data type ID not necessary if writing precisely the same data type // as the node has (not a subtype). WriteLn('Writing...'); try Client.WriteValue(EndpointDescriptor, NodeDescriptor, GenericObject); except on E: EOleException do begin WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message])); Exit; end; end; end;
// Shows how to write 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. // We know that this node returns complex data, so we can type cast to UAGenericObject. printf("Reading...\n"); try { $GenericObject = $Client->ReadValue($EndpointDescriptor, $NodeDescriptor); } catch (com_exception $e) { printf("*** Failure: %s\n", $e->getMessage()); Exit(); } // Modify the data read. // This node returns one of the two data types, randomly (this is not common, usually the type is fixed). The // data types are sub-types of one common type which the data type of the node. We therefore use the data type // ID in the returned UAGenericObject to detect which data type has been returned. // For processing the internals of the data, refer to examples for GenericData and DataType classes. // We know how the data is structured, and have hard-coded a logic that modifies certain values inside. It is // also possible to discover the structure of the data type in the program, and write generic clients that can // cope with any kind of complex data. // // Note that the code below is not fully robust - it will throw an exception if the data is not as expected. printf("Modifying...\n"); printf("%s\n", $GenericObject->DataTypeId); $ScalarValueDataType = new COM("OpcLabs.EasyOpc.UA.UANodeDescriptor"); $ScalarValueDataType->NodeId->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=9440"; // ScalarValueDataType if ($GenericObject->DataTypeId->NodeDescriptor->Match($ScalarValueDataType)) { // Negate the byte in the "ByteValue" field. $StructuredData = $GenericObject->GenericData->AsStructuredData(); $ByteValue = $StructuredData->FieldData["ByteValue"]->AsPrimitiveData(); $ByteValue->Value = ~($ByteValue->Value) & 255; printf("%s\n", $ByteValue->Value); } else { $ArrayValueDataType = new COM("OpcLabs.EasyOpc.UA.UANodeDescriptor"); $ArrayValueDataType->NodeId->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=9669"; // ArrayValueDataType if ($GenericObject->DataTypeId->Nodedescriptor->Match($ArrayValueDataType)) { // Negate bytes at indexes 0 and 1 of the array in the "ByteValue" field. $StructuredData = $GenericObject->GenericData->AsStructuredData(); $ByteValue2 = $StructuredData->FieldData["ByteValue"]->AsSequenceData(); $Element0 = $ByteValue2->Elements[0]->AsPrimitiveData(); $Element1 = $ByteValue2->Elements[1]->AsPrimitiveData(); $Element0->Value = ~($Element0->Value) & 255; $Element1->Value = ~($Element1->Value) & 255; printf("%s\n", $Element0->Value); printf("%s\n", $Element1->Value); } } // Write the modified complex data back to the node. // The data type ID in the UAGenericObject is borrowed without change from what we have read, so that the server // knows which data type we are writing. The data type ID not necessary if writing precisely the same data type // as the node has (not a subtype). printf("Writing...\n"); try { $Client->WriteValue($EndpointDescriptor, $NodeDescriptor, $GenericObject); } catch (com_exception $e) { printf("Failure: %s\n", $e->getMessage()); Exit(); }
// 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;
System.Object
System.Collections.ObjectModel.Collection<T>
OpcLabs.BaseLib.DataTypeModel.GenericDataCollection