Common Fundamentals > Identifying Information in OPC UA Client-Server > OPC UA Node IDs |
Node ID is an identifier for a node in an OPC server’s address space.
OPC Unified Architecture allows the OPC server to choose one or more types of node IDs for representation of its nodes. Node IDs can be numeric (a 32-bit integer), string, a GUID (globally unique identifier, 128 bits), or opaque (a binary data blob).
OPC UA node ID is *not*, by itself, a string. It is primarily a structure, containing the namespace (URI, index or both), and the identifier. OPC UA Node Id *has* a string representation, but the string representation is not the Node ID itself. The very same OPC UA node ID can be represented by multiple strings. You should not assume that two strings that appear different represent different node IDs. For example, "ns=1;s=SomeNode", and "ns=1;SomeNode" are strings that represent precisely the same node ID, because the "s=" prefix (for string identifiers) is optional. Or, "ns=0;s=Objects" may be the same as simply "s=Objects", because the default parsing context assumes the namespace index zero (when missing from the string).
There are methods available to parse strings into node IDs, and to format node IDs into strings.
OPC Studio products work with so-called expanded node IDs, which contain the node’s identifier together with a complete namespace URI. A single server may contain nodes in multiple namespaces, and the server maintains a namespace table where each namespace can be identified by an index. During a communication session with an OPC client, nodes are identified using indices into the namespace table. The namespace table contents and order of elements may, however, change between sessions.
QuickOPC-UA does not expose node IDs with indices into a namespace table alone. Instead, it always passes around the complete URI string of a namespace with a node ID. Because this expanded form of a node ID is used, a Node ID in QuickOPC-UA is stable between sessions, and can also be persistent (stored) and later used without a complexity of additional index remapping.
Depending on the type of Node ID, the expanded node ID string may have one of the following forms:
(for forms of node IDs that include "ns=", see Namespace indices in Node Ids).
In QuickOPC-UA, an expanded node ID corresponds to UANodeId object that you create and pass to various methods. An implicit conversion from a string containing the expanded text of Node ID exists. It is therefore common to specify UANodeId-s simply as strings, relying on the implicit conversion. Also note that UANodeId is usually a part of UANodeDescriptor and can be (implicitly) converted to it easily.
When the UANodeId object contains no data, it is considered a null Node Id, and its IsNull property is true. Beware that this is different from having a null reference to a UANodeId (which, in most places, is not allowed).
In OPC Studio products, when formatting the expanded text of OPC UA Node IDs and qualified names, the namespace URI (the text after "nsu=") is separated with an additional space from the following semicolon, allowing the URI be easily separated by tools that are not aware of the specific syntax of OPC UA Node IDs and qualified names. Similarly, any trailing whitespace in the namespace URI part (the text after "nsu=") is ignored when parsing the OPC UA Node IDs and qualified names.
Note: During browsing, the OPC server provides so-called browse names (browse IDs), which can be combined into browse paths. The browse names (browse IDs) usually “look” more user- friendly and you may be tempted to think that they would be more appropriate for node identification. The purpose of browse names (browse IDs) is, however, different, and using them alone for node identification would be inefficient, and sometimes ambiguous.
There are many ways in which you can construct node IDs, depending on which information you have available.
Following examples are intended to show you many of the options that exist for constructing the node IDs.
// This example shows different ways of constructing OPC UA node IDs. // // Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . using System; using OpcLabs.BaseLib; using OpcLabs.EasyOpc.UA; using OpcLabs.EasyOpc.UA.AddressSpace; using OpcLabs.EasyOpc.UA.AddressSpace.Parsing; using OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions; using OpcLabs.EasyOpc.UA.AddressSpace.Standard; using OpcLabs.EasyOpc.UA.OperationModel; namespace UADocExamples._UANodeId { class _Construction { // A node ID specifies a namespace (either by an URI or by an index), and an identifier. // The identifier can be numeric (an integer), string, GUID, or opaque. public static void Main1() { // A node ID can be specified in string form (so-called expanded text). // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). UANodeId nodeId1 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853"); Console.WriteLine(nodeId1); // Similarly, with a string identifier (s=...). UANodeId nodeId2 = new UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier"); Console.WriteLine(nodeId2); // Actually, "s=" can be omitted (not recommended, though). UANodeId nodeId3 = new UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier"); Console.WriteLine(nodeId3); // Notice that the output is normalized - the "s=" is added again. // Similarly, with a GUID identifier (g=...). UANodeId nodeId4 = new UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10"); Console.WriteLine(nodeId4); // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc. // Similarly, with an opaque identifier (b=..., in Base64 encoding). UANodeId nodeId5 = new UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8="); Console.WriteLine(nodeId5); // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of // namespace indices, and rather use the namespace URIs whenever possible. UANodeId nodeId6 = new UANodeId("ns=2;i=10853"); Console.WriteLine(nodeId6); // Namespace index can be also specified together with namespace URI. This is still safe, but may be // a bit quicker to perform, because the client can just verify the namespace URI instead of looking // it up. UANodeId nodeId7 = new UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853"); Console.WriteLine(nodeId7); // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. UANodeId nodeId8 = new UANodeId("i=2254"); Console.WriteLine(nodeId8); // If you attempt to pass in a string that does not conform to the syntax rules, // a UANodeIdFormatException is thrown. try { UANodeId nodeId9 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger"); Console.WriteLine(nodeId9); } catch (UANodeIdFormatException nodeIdFormatException) { Console.WriteLine($"*** Failure {nodeIdFormatException.Message}"); } // There is a parser object that can be used to parse the expanded texts of node IDs. UANodeIdParser nodeIdParser10 = new UANodeIdParser(); UANodeId nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853"); Console.WriteLine(nodeId10); // The parser can be used if you want to parse the expanded text of the node ID but do not want // exceptions be thrown. UANodeIdParser nodeIdParser11 = new UANodeIdParser(); IStringParsingError stringParsingError = nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", out UANodeId nodeId11); if (stringParsingError is null) Console.WriteLine(nodeId11); else Console.WriteLine($"*** Failure: {stringParsingError.Message}"); // You can also use the parser if you have node IDs where you want the default namespace be different // from the standard "http://opcfoundation.org/UA/". UANodeIdParser nodeIdParser12 = new UANodeIdParser("http://test.org/UA/Data/"); UANodeId nodeId12 = nodeIdParser12.Parse("i=10853"); Console.WriteLine(nodeId12); // The namespace URI string (or the namespace index, or both) and the identifier can be passed to the // constructor separately. UANodeId nodeId13 = new UANodeId("http://test.org/UA/Data/", 10853); Console.WriteLine(nodeId13); // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but // is useful as a placeholder or as a starting point for further modifications of its properties. UANodeId nodeId14 = new UANodeId(); Console.WriteLine(nodeId14); // Properties of a node ID can be modified individually. The advantage of this approach is that you do // not have to care about syntax of the node ID expanded text. UANodeId nodeId15 = new UANodeId(); nodeId15.NamespaceUriString = "http://test.org/UA/Data/"; nodeId15.Identifier = 10853; Console.WriteLine(nodeId15); // The same as above, but using an object initializer list. UANodeId nodeId16 = new UANodeId { NamespaceUriString = "http://test.org/UA/Data/", Identifier = 10853 }; Console.WriteLine(nodeId16); // If you know the type of the identifier upfront, it is safer to use typed properties that correspond // to specific types of identifier. Here, with an integer identifier. UANodeId nodeId17 = new UANodeId(); nodeId17.NamespaceUriString = "http://test.org/UA/Data/"; nodeId17.NumericIdentifier = 10853; Console.WriteLine(nodeId17); // Similarly, with a string identifier. UANodeId nodeId18 = new UANodeId(); nodeId18.NamespaceUriString = "http://test.org/UA/Data/"; nodeId18.StringIdentifier = "someIdentifier"; Console.WriteLine(nodeId18); // Similarly, with a GUID identifier. UANodeId nodeId19 = new UANodeId(); nodeId19.NamespaceUriString = "http://test.org/UA/Data/"; nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10"); Console.WriteLine(nodeId19); // If you have GUID in its string form, the node ID object can parse it for you. UANodeId nodeId20 = new UANodeId(); nodeId20.NamespaceUriString = "http://test.org/UA/Data/"; nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"; Console.WriteLine(nodeId20); // And, with an opaque identifier. UANodeId nodeId21 = new UANodeId(); nodeId21.NamespaceUriString = "http://test.org/UA/Data/"; nodeId21.OpaqueIdentifier = new byte[] {0x00, 0xFF}; Console.WriteLine(nodeId21); // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding // properties accordingly. UANodeId nodeId22 = new UANodeId(); nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"; Console.WriteLine(nodeId22); // There is an implicit conversion from a string (representing the expanded text) to a node ID. // You can therefore use the expanded text (string) in place of any node ID object directly. UANodeId nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853"; Console.WriteLine(nodeId23); // There is a copy constructor as well, creating a clone of an existing node ID. UANodeId nodeId24a = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853"); Console.WriteLine(nodeId24a); UANodeId nodeId24b = new UANodeId(nodeId24a); Console.WriteLine(nodeId24b); // We have provided static classes with properties that correspond to all standard nodes specified by // OPC UA. You can simply refer to these node IDs in your code. // The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, // UAVariableIds and UAVariableTypeIds. UANodeId nodeId25 = UAObjectIds.TypesFolder; Console.WriteLine(nodeId25); // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard // name only. // You can also refer to any standard node using its name (in a string form). // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. UANodeId nodeId26 = new UANodeId(); nodeId26.StandardName = "TypesFolder"; Console.WriteLine(nodeId26); // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that // you can use further. var client27 = new EasyUAClient(); try { UANodeElementCollection nodeElementCollection27 = client27.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References })); if (nodeElementCollection27.Count != 0) { UANodeId nodeId27 = nodeElementCollection27[0].NodeId; Console.WriteLine(nodeId27); } } catch (UAException uaException) { Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message); } // As above, but using a constructor that takes a node element as an input. var client28 = new EasyUAClient(); try { UANodeElementCollection nodeElementCollection28 = client28.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References })); if (nodeElementCollection28.Count != 0) { UANodeId nodeId28 = new UANodeId(nodeElementCollection28[0]); Console.WriteLine(nodeId28); } } catch (UAException uaException) { Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message); } // Or, there is an explicit conversion from a node descriptor as well. var client29 = new EasyUAClient(); try { UANodeElementCollection nodeElementCollection29 = client29.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References })); if (nodeElementCollection29.Count != 0) { UANodeId nodeId29 = (UANodeId) nodeElementCollection29[0]; Console.WriteLine(nodeId29); } } catch (UAException uaException) { Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message); } } } }
# This example shows different ways of constructing OPC UA node IDs. # # 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.EasyOpc.UA import * from OpcLabs.EasyOpc.UA.AddressSpace import * from OpcLabs.EasyOpc.UA.AddressSpace.Parsing import * from OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions import * from OpcLabs.EasyOpc.UA.AddressSpace.Standard import * # A node ID specifies a namespace (either by an URI or by an index), and an identifier. # The identifier can be numeric (an integer), string, GUID, or opaque. # # A node ID can be specified in string form (so-called expanded text). # The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). nodeId1 = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853') print(nodeId1) # Similarly, with a string identifier (s=...). nodeId2 = UANodeId('nsu=http://test.org/UA/Data/ ;s=someIdentifier') print(nodeId2) # Actually, "s=" can be omitted (not recommended, though). nodeId3 = UANodeId('nsu=http://test.org/UA/Data/ ;someIdentifier') print(nodeId3) # Similarly, with a GUID identifier (g=...). nodeId4 = UANodeId('nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10') print(nodeId4) # Similarly, with an opaque identifier (b=..., in Base64 encoding). nodeId5 = UANodeId('nsu=http://test.org/UA/Data/ ;b=AP8=') print(nodeId5) # Namespace index can be used instead of namespace URI. The server is allowed to change the namespace # indices between sessions (except for namespace 0), and for this reason, you should avoid the use of # namespace indices, and rather use the namespace URIs whenever possible. nodeId6 = UANodeId('ns=2;i=10853') print(nodeId6) # Namespace index can be also specified together with namespace URI. This is still safe, but may be # a bit quicker to perform, because the client can just verify the namespace URI instead of looking # it up. nodeId7 = UANodeId('nsu=http://test.org/UA/Data/ ;ns=2;i=10853') print(nodeId7) # When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace # with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are # many standard nodes that live in this reserved namespace, but no nodes specific to your servers will # be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. nodeId8 = UANodeId('i=2254') print(nodeId8) # If you attempt to pass in a string that does not conform to the syntax rules, # a UANodeIdFormatException is thrown. try: nodeId9 = UANodeId('nsu=http://test.org/UA/Data/ ;i=notAnInteger') except UANodeIdFormatException as nodeIdFormatException: print('*** Failure: ', nodeIdFormatException.Message, sep='') # There is a parser object that can be used to parse the expanded texts of node IDs. nodeIdParser10 = UANodeIdParser() nodeId10 = IUANodeIdParserExtension.Parse(nodeIdParser10, 'nsu=http://test.org/UA/Data/ ;i=10853') print(nodeId10) # The parser can be used if you want to parse the expanded text of the node ID but do not want # exceptions be thrown. nodeIdParser11 = UANodeIdParser() stringParsingError, nodeId11 = IUANodeIdParserExtension.TryParse(nodeIdParser11, 'nsu=http://test.org/UA/Data/ ;i=notAnInteger', UANodeId()) # placeholder for 'out' if stringParsingError is None: print(nodeId11) else: print('*** Failure: ', stringParsingError.Message, sep='') # You can also use the parser if you have node IDs where you want the default namespace be different # from the standard "http://opcfoundation.org/UA/". nodeIdParser12 = UANodeIdParser('http://test.org/UA/Data/') nodeId12 = IUANodeIdParserExtension.Parse(nodeIdParser12, 'i=10853') print(nodeId12) # The namespace URI string (or the namespace index, or both) and the identifier can be passed to the # constructor separately. nodeId13 = UANodeId('http://test.org/UA/Data/', 10853) print(nodeId13) # You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but # is useful as a placeholder or as a starting point for further modifications of its properties. nodeId14 = UANodeId() print(nodeId14) # Properties of a node ID can be modified individually. The advantage of this approach is that you do # not have to care about syntax of the node ID expanded text. nodeId15 = UANodeId() nodeId15.NamespaceUriString = 'http://test.org/UA/Data/' nodeId15.Identifier = 10853 print(nodeId15) # If you know the type of the identifier upfront, it is safer to use typed properties that correspond # to specific types of identifier. Here, with an integer identifier. nodeId17 = UANodeId() nodeId17.NamespaceUriString = 'http://test.org/UA/Data/' nodeId17.NumericIdentifier = 10853 print(nodeId17) # Similarly, with a string identifier. nodeId18 = UANodeId() nodeId18.NamespaceUriString = 'http://test.org/UA/Data/' nodeId18.StringIdentifier = 'someIdentifier' print(nodeId18) # Similarly, with a GUID identifier. nodeId19 = UANodeId() nodeId19.NamespaceUriString = 'http://test.org/UA/Data/' nodeId19.GuidIdentifier = Guid.Parse('BAEAF004-1E43-4A06-9EF0-E52010D5CD10') print(nodeId19) # If you have GUID in its string form, the node ID object can parse it for you. nodeId20 = UANodeId() nodeId20.NamespaceUriString = 'http://test.org/UA/Data/' nodeId20.GuidIdentifierString = 'BAEAF004-1E43-4A06-9EF0-E52010D5CD10' print(nodeId20) # And, with an opaque identifier. nodeId21 = UANodeId() nodeId21.NamespaceUriString = 'http://test.org/UA/Data/' nodeId21.OpaqueIdentifier = [0x00, 0xFF] print(nodeId21) # Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding # properties accordingly. nodeId22 = UANodeId() nodeId22.ExpandedText = 'nsu=http://test.org/UA/Data/ ;i=10853' print(nodeId22) # There is a copy constructor as well, creating a clone of an existing node ID. nodeId24a = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853') print(nodeId24a) nodeId24b = UANodeId(nodeId24a) print(nodeId24b) # We have provided static classes with properties that correspond to all standard nodes specified by # OPC UA. You can simply refer to these node IDs in your code. # The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, # UAVariableIds and UAVariableTypeIds. nodeId25 = UAObjectIds.TypesFolder print(nodeId25) # When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard # name only. # You can also refer to any standard node using its name (in a string form). # Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. nodeId26 = UANodeId() nodeId26.StandardName = "TypesFolder" print(nodeId26) # When you browse for nodes in the OPC UA server, every returned node element contains a node ID that # you can use further. client27 = EasyUAClient() try: nodeElementCollection27 = IEasyUAClientExtension.Browse(client27, UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'), UANodeDescriptor(UAObjectIds.Server), UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References)) if nodeElementCollection27.Count != 0: nodeId27 = nodeElementCollection27.get_Item(0).NodeId print(nodeId27) except UAException as uaException: print('*** Failure: ', uaException.GetBaseException().Message, sep='') # As above, but using a constructor that takes a node element as an input. client28 = EasyUAClient() try: nodeElementCollection28 = IEasyUAClientExtension.Browse(client28, UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'), UANodeDescriptor(UAObjectIds.Server), UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References)) if nodeElementCollection28.Count != 0: nodeId28 = UANodeId(nodeElementCollection28.get_Item(0)) print(nodeId28) except UAException as uaException: print('*** Failure: ', uaException.GetBaseException().Message, sep='') # Or, there is an explicit conversion from a node descriptor as well. client29 = EasyUAClient() try: nodeElementCollection29 = IEasyUAClientExtension.Browse(client29, UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'), UANodeDescriptor(UAObjectIds.Server), UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References)) if nodeElementCollection29.Count != 0: # FromUANodeDescriptor can be used instead of op_Explicit, too. nodeId29 = UANodeId.op_Explicit(UANodeDescriptor(nodeElementCollection29.get_Item(0))) print(nodeId29) except UAException as uaException: print('*** Failure: ', uaException.GetBaseException().Message, sep='') print() print('Finished.')
' This example shows different ways of constructing OPC UA node IDs. ' ' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Imports System Imports OpcLabs.BaseLib Imports OpcLabs.EasyOpc.UA Imports OpcLabs.EasyOpc.UA.AddressSpace Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard Namespace _UANodeId Friend Class _Construction Public Shared Sub Main1() ' A node ID can be specified in string form (so-called expanded text). ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). Dim nodeId1 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853") Console.WriteLine(nodeId1) ' Similarly, with a string identifier (s=...). Dim nodeId2 = New UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier") Console.WriteLine(nodeId2) ' Actually, "s=" can be omitted (not recommended, though) Dim nodeId3 = New UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier") Console.WriteLine(nodeId3) ' Similarly, with a GUID identifier (g=...) Dim nodeId4 = New UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10") Console.WriteLine(nodeId4) ' Similarly, with an opaque identifier (b=..., in Base64 encoding). Dim nodeId5 = New UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8=") Console.WriteLine(nodeId5) ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace ' indices between sessions, and for this reason, you should avoid the use of namespace indices, and ' rather use the namespace URIs whenever possible. Dim nodeId6 = New UANodeId("ns=2;i=10853") Console.WriteLine(nodeId6) ' Namespace index can be also specified together with namespace URI. This is still safe, but may be ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking ' it up. Dim nodeId7 = New UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853") Console.WriteLine(nodeId7) ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. Dim nodeId8 = New UANodeId("i=2254") Console.WriteLine(nodeId8) ' If you attempt to pass in a string that does not conform to the syntax rules, ' a UANodeIdFormatException is thrown. Try Dim nodeId9 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger") Console.WriteLine(nodeId9) Catch nodeIdFormatException As UANodeIdFormatException Console.WriteLine(nodeIdFormatException.Message) End Try ' There is a parser object that can be used to parse the expanded textx of node IDs. Dim nodeIdParser10 = New UANodeIdParser() Dim nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853") Console.WriteLine(nodeId10) ' The parser can be used if you want to parse the expanded text of the node ID but do not want ' exceptions be thrown. Dim nodeIdParser11 = New UANodeIdParser() Dim nodeId11 As UANodeId = Nothing Dim stringParsingError As IStringParsingError = nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", nodeId11) If stringParsingError Is Nothing Then Console.WriteLine(nodeId11) Else Console.WriteLine(stringParsingError.Message) End If ' You can also use the parser if you have node IDs where you want the default namespace be different ' from the standard "http://opcfoundation.org/UA/". Dim nodeIdParser12 = New UANodeIdParser("http://test.org/UA/Data/") Dim nodeId12 = nodeIdParser12.Parse("i=10853") Console.WriteLine(nodeId12) ' The namespace URI string (or the namespace index, or both) and the identifier can be passed to the ' constructor separately. Dim nodeId13 = New UANodeId("http://test.org/UA/Data/", 10853) Console.WriteLine(nodeId13) ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but ' is useful as a placeholder or as a starting point for further modifications of its properties. Dim nodeId14 = New UANodeId() Console.WriteLine(nodeId14) ' Properties of a node ID can be modified individually. The advantage of this approach is that you do ' not have to care about syntax of the node ID expanded text. Dim nodeId15 = New UANodeId() nodeId15.NamespaceUriString = "http://test.org/UA/Data/" nodeId15.Identifier = 10853 Console.WriteLine(nodeId15) ' The same as above, but using an object initializer list. Dim nodeId16 = New UANodeId With { .NamespaceUriString = "http://test.org/UA/Data/", .Identifier = 10853 } Console.WriteLine(nodeId16) ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond ' to specific types of identifier. Here, with an integer identifier. Dim nodeId17 = New UANodeId() nodeId17.NamespaceUriString = "http://test.org/UA/Data/" nodeId17.NumericIdentifier = 10853 Console.WriteLine(nodeId17) ' Similarly, with a string identifier. Dim nodeId18 = New UANodeId() nodeId18.NamespaceUriString = "http://test.org/UA/Data/" nodeId18.StringIdentifier = "someIdentifier" Console.WriteLine(nodeId18) ' Similarly, with a GUID identifier. Dim nodeId19 = New UANodeId() nodeId19.NamespaceUriString = "http://test.org/UA/Data/" nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10") Console.WriteLine(nodeId19) ' If you have GUID in its string form, the node ID object can parse it for you. Dim nodeId20 = New UANodeId() nodeId20.NamespaceUriString = "http://test.org/UA/Data/" nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10" Console.WriteLine(nodeId20) ' And, with an opaque identifier. Dim nodeId21 = New UANodeId() nodeId21.NamespaceUriString = "http://test.org/UA/Data/" nodeId21.OpaqueIdentifier = {&H0, &HFF} Console.WriteLine(nodeId21) ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding ' properties accordingly. Dim nodeId22 = New UANodeId() nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853" Console.WriteLine(nodeId22) ' There is an implicit conversion from a string (representing the expanded text) to a node ID. ' You can therefore use the expanded text (string) in place of any node ID object directly. Dim nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853" Console.WriteLine(nodeId23) ' There is a copy constructor as well, creating a clone of an existing node ID. Dim nodeId24a = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853") Console.WriteLine(nodeId24a) Dim nodeId24b = New UANodeId(nodeId24a) Console.WriteLine(nodeId24b) ' We have provided static classes with properties that correspond to all standard nodes specified by ' OPC UA. You can simply refer to these node IDs in your code. ' The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, ' UAVariableIds and UAVariableTypeIds. Dim nodeId25 = UAObjectIds.TypesFolder Console.WriteLine(nodeId25) ' You can also refer to any standard node using its name (in a string form). ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. Dim nodeId26 = New UANodeId() nodeId26.StandardName = "TypesFolder" Console.WriteLine(nodeId26) ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that ' you can use further. Dim client27 = New EasyUAClient() Dim nodeElementCollection27 = client27.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References})) Dim nodeId27 = nodeElementCollection27(0).NodeId Console.WriteLine(nodeId27) ' As above, but using a constructor that takes a node element as an input. Dim client28 = New EasyUAClient() Dim nodeElementCollection28 = client28.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References})) Dim nodeId28 = New UANodeId(nodeElementCollection28(0)) Console.WriteLine(nodeId28) ' Or, there is an explicit conversion from a node element as well. Dim client29 = New EasyUAClient() Dim nodeElementCollection29 = client29.Browse( "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", UAObjectIds.Server, New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References})) Dim nodeId29 = CType(nodeElementCollection29(0), UANodeId) Console.WriteLine(nodeId29) End Sub End Class End Namespace
// This example shows different ways of constructing OPC UA node IDs. // // Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . class procedure _Construction.Main; var BrowseParameters: _UABrowseParameters; Client27: _EasyUAClient; EndpointDescriptor: _UAEndpointDescriptor; NodeId1, NodeId2, NodeId3, NodeId4, NodeId5, NodeId6, NodeId7, NodeId8, NodeId9, NodeId10, NodeId11, NodeId12, NodeId14, NodeId15, NodeId17, NodeId18, NodeId20, NodeId21, NodeId26, NodeId27, ServerNodeId, ReferencesNodeId: OpcLabs_EasyOpcUA_TLB._UANodeId; NodeId11Result: OleVariant; NodeIdParser10, NodeIdParser11, NodeIdParser12: _UANodeIdParser; NodeElements27: _UANodeElementCollection; OpaqueIdentifier21: Variant; ServerNodeDescriptor: _UANodeDescriptor; StringParsingError: _StringParsingError; begin // A node ID specifies a namespace (either by an URI or by an index), and an identifier. // The identifier can be numeric (an integer), string, GUID, or opaque. // A node ID can be specified in string form (so-called expanded text). // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding // properties accordingly. NodeId1 := CoUANodeId.Create; NodeId1.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10853'; WriteLn(NodeId1.ToString); // Similarly, with a string identifier (s=...). NodeId2 := CoUANodeId.Create; NodeId2.ExpandedText := 'nsu=http://test.org/UA/Data/ ;s=someIdentifier'; WriteLn(NodeId2.ToString); // Actually, "s=" can be omitted (not recommended, though) NodeId3 := CoUANodeId.Create; NodeId3.ExpandedText := 'nsu=http://test.org/UA/Data/ ;someIdentifier'; WriteLn(NodeId3.ToString); // Notice that the output is normalized - the "s=" is added again. // Similarly, with a GUID identifier (g=...) NodeId4 := CoUANodeId.Create; NodeId4.ExpandedText := 'nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10'; WriteLn(NodeId4.ToString); // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc. // Similarly, with an opaque identifier (b=..., in Base64 encoding). NodeId5 := CoUANodeId.Create; NodeId5.ExpandedText := 'nsu=http://test.org/UA/Data/ ;b=AP8='; WriteLn(NodeId5.ToString); // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of // namespace indices, and rather use the namespace URIs whenever possible. NodeId6 := CoUANodeId.Create; NodeId6.ExpandedText := 'ns=2;i=10853'; WriteLn(NodeId6.ToString); // Namespace index can be also specified together with namespace URI. This is still safe, but may be // a bit quicker to perform, because the client can just verify the namespace URI instead of looking // it up. NodeId7 := CoUANodeId.Create; NodeId7.ExpandedText := 'nsu=http://test.org/UA/Data/ ;ns=2;i=10853'; WriteLn(NodeId7.ToString); // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. NodeId8 := CoUANodeId.Create; NodeId8.ExpandedText := 'i=2254'; WriteLn(NodeId8.ToString); // If you attempt to pass in a string that does not conform to the syntax rules, // a UANodeIdFormatException is thrown. NodeId9 := CoUANodeId.Create; try NodeId9.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=notAnInteger'; WriteLn(NodeId9.ToString); except on E: EOleException do begin WriteLn(Format('*** Failure: %s', [E.BaseException.Message])); end; end; // There is a parser object that can be used to parse the expanded texts of node IDs. NodeIdParser10 := CoUANodeIdParser.Create; NodeId10 := NodeIdParser10.Parse('nsu=http://test.org/UA/Data/ ;i=10853', False); WriteLn(NodeId10.ToString); // The parser can be used if you want to parse the expanded text of the node ID but do not want // exceptions be thrown. NodeIdParser11 := CoUANodeIdParser.Create; StringParsingError := NodeIdParser11.TryParse('nsu=http://test.org/UA/Data/ ;i=notAnInteger', False, NodeId11Result); if StringParsingError = nil then begin NodeId11 := IUnknown(NodeId11Result) as OpcLabs_EasyOpcUA_TLB._UANodeId; WriteLn(NodeId11.ToString); end else WriteLn(Format('*** Failure: %s', [StringParsingError.Message])); // You can also use the parser if you have node IDs where you want the default namespace be different // from the standard "http://opcfoundation.org/UA/". NodeIdParser12 := CoUANodeIdParser.Create; NodeIdParser12.DefaultNamespaceUriString := 'http://test.org/UA/Data/'; NodeId12 := NodeIdParser12.Parse('i=10853', False); WriteLn(NodeId12.ToString); // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but // is useful as a placeholder or as a starting point for further modifications of its properties. NodeId14 := CoUANodeId.Create; WriteLn(NodeId14.ToString); // Properties of a node ID can be modified individually. The advantage of this approach is that you do // not have to care about syntax of the node ID expanded text. NodeId15 := CoUANodeId.Create; NodeId15.NamespaceUriString := 'http://test.org/UA/Data/'; NodeId15.Identifier := 10853; WriteLn(NodeId15.ToString); // If you know the type of the identifier upfront, it is safer to use typed properties that correspond // to specific types of identifier. Here, with an integer identifier. NodeId17 := CoUANodeId.Create; NodeId17.NamespaceUriString := 'http://test.org/UA/Data/'; NodeId17.NumericIdentifier := 10853; WriteLn(NodeId17.ToString); // Similarly, with a string identifier. NodeId18 := CoUANodeId.Create; NodeId18.NamespaceUriString := 'http://test.org/UA/Data/'; NodeId18.StringIdentifier := 'someIdentifier'; WriteLn(NodeId18.ToString); // If you have GUID in its string form, the node ID object can parse it for you. NodeId20 := CoUANodeId.Create; NodeId20.NamespaceUriString := 'http://test.org/UA/Data/'; NodeId20.GuidIdentifierString := 'BAEAF004-1E43-4A06-9EF0-E52010D5CD10'; WriteLn(NodeId20.ToString); // And, with an opaque identifier. NodeId21 := CoUANodeId.Create; NodeId21.NamespaceUriString := 'http://test.org/UA/Data/'; // OpaqueIdentifier21 := VarArrayCreate ([0, 1], varByte); OpaqueIdentifier21 := VarArrayCreate ([0, 1], varVariant); OpaqueIdentifier21[0] := $00; OpaqueIdentifier21[1] := $FF; NodeId21.OpaqueIdentifier := PSafeArray (TVarData (OpaqueIdentifier21).VArray); WriteLn(NodeId21.ToString); // We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code. // You can refer to any standard node using its name (in a string form). // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. NodeId26 := CoUANodeId.Create; NodeId26.StandardName := 'TypesFolder'; WriteLn(NodeId26.ToString); // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only. // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that // you can use further. Client27 := CoEasyUAClient.Create; EndpointDescriptor := CoUAEndpointDescriptor.Create; EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer'; // Browse from the Server node. ServerNodeId := CoUANodeId.Create; ServerNodeId.StandardName := 'Server'; ServerNodeDescriptor := CoUANodeDescriptor.Create; ServerNodeDescriptor.NodeId := ServerNodeId; // Browse all References. ReferencesNodeId := CoUANodeId.Create; ReferencesNodeId.StandardName := 'References'; BrowseParameters := CoUABrowseParameters.Create; BrowseParameters.NodeClasses := UANodeClass_All; // this is the default, anyway BrowseParameters.ReferenceTypeIds.Add(ReferencesNodeId); try NodeElements27 := Client27.Browse(EndpointDescriptor, ServerNodeDescriptor, BrowseParameters); if NodeElements27.Count <> 0 then begin NodeId27 := NodeElements27[0].NodeId; WriteLn(NodeId27.ToString); end; except on E: EOleException do begin WriteLn(Format('*** Failure: %s', [E.BaseException.Message])); end; end; end;
// This example shows different ways of constructing OPC UA node IDs. // // A node ID specifies a namespace (either by an URI or by an index), and an identifier. // The identifier can be numeric (an integer), string, GUID, or opaque. // // Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . const UANodeClass_All = 255; // A node ID can be specified in string form (so-called expanded text). // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding // properties accordingly. $NodeId1 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId1->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"; printf("%s\n", $NodeId1); // Similarly, with a string identifier (s=...). $NodeId2 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId2->ExpandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier"; printf("%s\n", $NodeId2); // Actually, "s=" can be omitted (not recommended, though) $NodeId3 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId3->ExpandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier"; printf("%s\n", $NodeId3); // Notice that the output is normalized - the "s=" is added again. // Similarly, with a GUID identifier (g=...) $NodeId4 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId4->ExpandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10"; printf("%s\n", $NodeId4); // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc. // Similarly, with an opaque identifier (b=..., in Base64 encoding). $NodeId5 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId5->ExpandedText = "nsu=http://test.org/UA/Data/ ;b=AP8="; printf("%s\n", $NodeId5); // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of // namespace indices, and rather use the namespace URIs whenever possible. $NodeId6 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId6->ExpandedText = "ns=2;i=10853"; printf("%s\n", $NodeId6); // Namespace index can be also specified together with namespace URI. This is still safe, but may be // a bit quicker to perform, because the client can just verify the namespace URI instead of looking // it up. $NodeId7 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId7->ExpandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853"; printf("%s\n", $NodeId7); // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. $NodeId8 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId8->ExpandedText = "i=2254"; printf("%s\n", $NodeId8); // If you attempt to pass in a string that does not conform to the syntax rules, // a UANodeIdFormatException is thrown. $NodeId9 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); try { $NodeId9->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger"; printf("%s\n", $NodeId9); } catch (com_exception $e) { printf("*** Failure: %s\n", $e->getMessage()); } // There is a parser object that can be used to parse the expanded texts of node IDs. $NodeIdParser10 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser"); $NodeId10 = $NodeIdParser10->Parse("nsu=http://test.org/UA/Data/ ;i=10853", False); printf("%s\n", $NodeId10); // The parser can be used if you want to parse the expanded text of the node ID but do not want // exceptions be thrown. $NodeId11 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeIdParser11 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser"); $StringParsingError = $NodeIdParser11->TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, $NodeId11); if (is_null($StringParsingError)) printf("%s\n", $NodeId11); else printf("*** Failure: %s\n", $StringParsingError->Message); // You can also use the parser if you have node IDs where you want the default namespace be different // from the standard "http://opcfoundation.org/UA/". $NodeIdParser12 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser"); $NodeIdParser12->DefaultNamespaceUriString = "http://test.org/UA/Data/"; $NodeId12 = $NodeIdParser12->Parse("i=10853", False); printf("%s\n", $NodeId12); // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but // is useful as a placeholder or as a starting point for further modifications of its properties. $NodeId14 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); printf("%s\n", $NodeId14); // Properties of a node ID can be modified individually. The advantage of this approach is that you do // not have to care about syntax of the node ID expanded text. $NodeId15 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId15->NamespaceUriString = "http://test.org/UA/Data/"; $NodeId15->Identifier = 10853; printf("%s\n", $NodeId15); // If you know the type of the identifier upfront, it is safer to use typed properties that correspond // to specific types of identifier. Here, with an integer identifier. $NodeId17 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId17->NamespaceUriString = "http://test.org/UA/Data/"; $NodeId17->NumericIdentifier = 10853; printf("%s\n", $NodeId17); // Similarly, with a string identifier. $NodeId18 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId18->NamespaceUriString = "http://test.org/UA/Data/"; $NodeId18->StringIdentifier = "someIdentifier"; printf("%s\n", $NodeId18); // If you have GUID in its string form, the node ID object can parse it for you. $NodeId20 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId20->NamespaceUriString = "http://test.org/UA/Data/"; $NodeId20->GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"; printf("%s\n", $NodeId20); // And, with an opaque identifier. $NodeId21 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId21->NamespaceUriString = "http://test.org/UA/Data/"; $OpaqueIdentifier21[0] = 0x00; $OpaqueIdentifier21[1] = 0xFF; $NodeId21->OpaqueIdentifier = $OpaqueIdentifier21; printf("%s\n", $NodeId21); // We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code. // You can refer to any standard node using its name (in a string form). // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. $NodeId26 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $NodeId26->StandardName = "TypesFolder"; printf("%s\n", $NodeId26); // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only. // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that // you can use further. $Client27 = new COM("OpcLabs.EasyOpc.UA.EasyUAClient"); $EndpointDescriptor = new COM("OpcLabs.EasyOpc.UA.UAEndpointDescriptor"); $EndpointDescriptor->UrlString = "http://opcua.demo-this.com:51211/UA/SampleServer"; // Browse from the Server node. $ServerNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $ServerNodeId->StandardName = "Server"; $ServerNodeDescriptor = new COM("OpcLabs.EasyOpc.UA.UANodeDescriptor"); $ServerNodeDescriptor->NodeId = $ServerNodeId; // Browse all References. $ReferencesNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId"); $ReferencesNodeId->StandardName = "References"; $BrowseParameters = new COM("OpcLabs.EasyOpc.UA.UABrowseParameters"); $BrowseParameters->NodeClasses = UANodeClass_All; // this is the default, anyway $BrowseParameters->ReferenceTypeIds->Add($ReferencesNodeId); try { $NodeElements27 = $Client27->Browse($EndpointDescriptor, $ServerNodeDescriptor, $BrowseParameters); if ($NodeElements27->Count != 0) { $NodeId27 = $NodeElements27[0]->NodeId; printf("%s\n", $NodeId27); } } catch (com_exception $e) { printf("*** Failure: %s\n", $e->getMessage()); exit(); }
REM This example shows different ways of constructing OPC UA node IDs. REM REM Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Private Sub Construction_Main_Command_Click() OutputText = "" ' A node ID specifies a namespace (either by an URI or by an index), and an identifier. ' The identifier can be numeric (an integer), string, GUID, or opaque. ' A node ID can be specified in string form (so-called expanded text). ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding ' properties accordingly. Dim nodeId1 As New UANodeId nodeId1.expandedText = "nsu=http://test.org/UA/Data/ ;i=10853" OutputText = OutputText & nodeId1 & vbCrLf ' Similarly, with a string identifier (s=...). Dim nodeId2 As New UANodeId nodeId2.expandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier" OutputText = OutputText & nodeId2 & vbCrLf ' Actually, "s=" can be omitted (not recommended, though) Dim nodeId3 As New UANodeId nodeId3.expandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier" OutputText = OutputText & nodeId3 & vbCrLf ' Notice that the output is normalized - the "s=" is added again. ' Similarly, with a GUID identifier (g=...) Dim nodeId4 As New UANodeId nodeId4.expandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10" OutputText = OutputText & nodeId4 & vbCrLf ' Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc. ' Similarly, with an opaque identifier (b=..., in Base64 encoding). Dim nodeId5 As New UANodeId nodeId5.expandedText = "nsu=http://test.org/UA/Data/ ;b=AP8=" OutputText = OutputText & nodeId5 & vbCrLf ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace ' indices between sessions (except for namespace 0), and for this reason, you should avoid the use of ' namespace indices, and rather use the namespace URIs whenever possible. Dim nodeId6 As New UANodeId nodeId6.expandedText = "ns=2;i=10853" OutputText = OutputText & nodeId6 & vbCrLf ' Namespace index can be also specified together with namespace URI. This is still safe, but may be ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking ' it up. Dim nodeId7 As New UANodeId nodeId7.expandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853" OutputText = OutputText & nodeId7 & vbCrLf ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. Dim nodeId8 As New UANodeId nodeId8.expandedText = "i=2254" OutputText = OutputText & nodeId8 & vbCrLf ' If you attempt to pass in a string that does not conform to the syntax rules, ' a UANodeIdFormatException is thrown. Dim nodeId9 As New UANodeId On Error Resume Next nodeId9.expandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger" OutputText = OutputText & nodeId9 & vbCrLf If Err.Number <> 0 Then OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf End If On Error GoTo 0 ' There is a parser object that can be used to parse the expanded texts of node IDs. Dim nodeIdParser10 As New UANodeIdParser Dim nodeId10 As UANodeId Set nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853", False) OutputText = OutputText & nodeId10 & vbCrLf ' The parser can be used if you want to parse the expanded text of the node ID but do not want ' exceptions be thrown. Dim nodeIdParser11 As New UANodeIdParser Dim stringParsingError As stringParsingError Dim nodeId11 As UANodeId Set stringParsingError = nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, nodeId11) If stringParsingError Is Nothing Then OutputText = OutputText & nodeId11 & vbCrLf Else OutputText = OutputText & "*** Failure: " & stringParsingError.Message & vbCrLf End If ' You can also use the parser if you have node IDs where you want the default namespace be different ' from the standard "http://opcfoundation.org/UA/". Dim nodeIdParser12 As New UANodeIdParser nodeIdParser12.DefaultNamespaceUriString = "http://test.org/UA/Data/" Dim nodeId12 As UANodeId Set nodeId12 = nodeIdParser12.Parse("i=10853", False) OutputText = OutputText & nodeId12 & vbCrLf ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but ' is useful as a placeholder or as a starting point for further modifications of its properties. Dim nodeId14 As New UANodeId OutputText = OutputText & nodeId14 & vbCrLf ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond ' to specific types of identifier. Here, with an integer identifier. Dim nodeId17 As New UANodeId nodeId17.NamespaceUriString = "http://test.org/UA/Data/" nodeId17.NumericIdentifier = 10853 OutputText = OutputText & nodeId17 & vbCrLf ' Similarly, with a string identifier. Dim nodeId18 As New UANodeId nodeId18.NamespaceUriString = "http://test.org/UA/Data/" nodeId18.StringIdentifier = "someIdentifier" OutputText = OutputText & nodeId18 & vbCrLf ' If you have GUID in its string form, the node ID object can parse it for you. Dim nodeId20 As New UANodeId nodeId20.NamespaceUriString = "http://test.org/UA/Data/" nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10" OutputText = OutputText & nodeId20 & vbCrLf ' And, with an opaque identifier. Dim nodeId21 As New UANodeId nodeId21.NamespaceUriString = "http://test.org/UA/Data/" Dim opaqueIdentifier21(1) As Byte opaqueIdentifier21(0) = &H0& opaqueIdentifier21(1) = &HFF& nodeId21.SetOpaqueIdentifier opaqueIdentifier21 OutputText = OutputText & nodeId21 & vbCrLf ' We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code. ' You can refer to any standard node using its name (in a string form). ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. Dim nodeId26 As New UANodeId nodeId26.StandardName = "TypesFolder" OutputText = OutputText & nodeId26 & vbCrLf ' When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only. ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that ' you can use further. Dim client27 As New EasyUAClient Dim endpointDescriptor As New UAEndpointDescriptor endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' Browse from the Server node. Dim serverNodeId As New UANodeId serverNodeId.StandardName = "Server" Dim serverNodedescriptor As New UANodeDescriptor Set serverNodedescriptor.NodeId = serverNodeId ' Browse all References. Dim referencesNodeId As New UANodeId referencesNodeId.StandardName = "References" Dim browseParameters As New UABrowseParameters browseParameters.NodeClasses = UANodeClass_All ' this is the default, anyway browseParameters.ReferenceTypeIds.Add referencesNodeId On Error Resume Next Dim nodeElements27 As UANodeElementCollection Set nodeElements27 = client27.Browse(endpointDescriptor, serverNodedescriptor, browseParameters) If Err.Number <> 0 Then OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf Exit Sub End If On Error GoTo 0 If nodeElements27.Count <> 0 Then Dim nodeId27 As UANodeId Set nodeId27 = nodeElements27(0).NodeId OutputText = OutputText & nodeId27 & vbCrLf End If End Sub
Rem This example shows different ways of constructing OPC UA node IDs. Rem Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html . Option Explicit ' A node ID specifies a namespace (either by an URI or by an index), and an identifier. ' The identifier can be numeric (an integer), string, GUID, or opaque. Const UANodeClass_All = 255 ' A node ID can be specified in string form (so-called expanded text). ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...). ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding ' properties accordingly. Dim NodeId1: Set NodeId1 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId1.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853" WScript.Echo NodeId1 ' Similarly, with a string identifier (s=...). Dim NodeId2: Set NodeId2 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId2.ExpandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier" WScript.Echo NodeId2 ' Actually, "s=" can be omitted (not recommended, though) Dim NodeId3: Set NodeId3 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId3.ExpandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier" WScript.Echo NodeId3 ' Notice that the output is normalized - the "s=" is added again. ' Similarly, with a GUID identifier (g=...) Dim NodeId4: Set NodeId4 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId4.ExpandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10" WScript.Echo NodeId4 ' Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc. ' Similarly, with an opaque identifier (b=..., in Base64 encoding). Dim NodeId5: Set NodeId5 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId5.ExpandedText = "nsu=http://test.org/UA/Data/ ;b=AP8=" WScript.Echo NodeId5 ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace ' indices between sessions (except for namespace 0), and for this reason, you should avoid the use of ' namespace indices, and rather use the namespace URIs whenever possible. Dim NodeId6: Set NodeId6 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId6.ExpandedText = "ns=2;i=10853" WScript.Echo NodeId6 ' Namespace index can be also specified together with namespace URI. This is still safe, but may be ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking ' it up. Dim NodeId7: Set NodeId7 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId7.ExpandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853" WScript.Echo NodeId7 ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes. Dim NodeId8: Set NodeId8 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId8.ExpandedText = "i=2254" WScript.Echo NodeId8 ' If you attempt to pass in a string that does not conform to the syntax rules, ' a UANodeIdFormatException is thrown. Dim NodeId9: Set NodeId9 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") On Error Resume Next NodeId9.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger" If Err.Number = 0 Then WScript.Echo NodeId9 Else WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description End If On Error Goto 0 ' There is a parser object that can be used to parse the expanded texts of node IDs. Dim NodeIdParser10: Set NodeIdParser10 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser") Dim NodeId10: Set NodeId10 = NodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853", False) WScript.Echo NodeId10 ' The parser can be used if you want to parse the expanded text of the node ID but do not want ' exceptions be thrown. Dim NodeIdParser11: Set NodeIdParser11 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser") Dim NodeId11 Dim StringParsingError: Set StringParsingError = NodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, NodeId11) If StringParsingError Is Nothing Then WScript.Echo NodeId11 Else WScript.Echo "*** Failure: " & StringParsingError.Message End If ' You can also use the parser if you have node IDs where you want the default namespace be different ' from the standard "http://opcfoundation.org/UA/". Dim NodeIdParser12: Set NodeIdParser12 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser") NodeIdParser12.DefaultNamespaceUriString = "http://test.org/UA/Data/" Dim NodeId12: Set NodeId12 = NodeIdParser12.Parse("i=10853", False) WScript.Echo NodeId12 ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but ' is useful as a placeholder or as a starting point for further modifications of its properties. Dim NodeId14: Set NodeId14 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") WScript.Echo NodeId14 ' Properties of a node ID can be modified individually. The advantage of this approach is that you do ' not have to care about syntax of the node ID expanded text. Dim NodeId15: Set NodeId15 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId15.NamespaceUriString = "http://test.org/UA/Data/" NodeId15.Identifier = 10853 WScript.Echo NodeId15 ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond ' to specific types of identifier. Here, with an integer identifier. Dim NodeId17: Set NodeId17 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId17.NamespaceUriString = "http://test.org/UA/Data/" NodeId17.NumericIdentifier = 10853 WScript.Echo NodeId17 ' Similarly, with a string identifier. Dim NodeId18: Set NodeId18 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId18.NamespaceUriString = "http://test.org/UA/Data/" NodeId18.StringIdentifier = "someIdentifier" WScript.Echo NodeId18 ' If you have GUID in its string form, the node ID object can parse it for you. Dim NodeId20: Set NodeId20 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId20.NamespaceUriString = "http://test.org/UA/Data/" NodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10" WScript.Echo NodeId20 ' And, with an opaque identifier. Dim NodeId21: Set NodeId21 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId21.NamespaceUriString = "http://test.org/UA/Data/" NodeId21.OpaqueIdentifier = Array(&H00, &HFF) WScript.Echo NodeId21 ' We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code. ' You can refer to any standard node using its name (in a string form). ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException. Dim NodeId26: Set NodeId26 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") NodeId26.StandardName = "TypesFolder" WScript.Echo NodeId26 ' When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only. ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that ' you can use further. Dim Client27: Set Client27 = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient") Dim EndpointDescriptor: Set EndpointDescriptor = CreateObject("OpcLabs.EasyOpc.UA.UAEndpointDescriptor") EndpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer" ' Browse from the Server node. Dim ServerNodeId: Set ServerNodeId = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") ServerNodeId.StandardName = "Server" Dim ServerNodeDescriptor: Set ServerNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.UANodeDescriptor") ServerNodeDescriptor.NodeId = ServerNodeId ' Browse all References. Dim ReferencesNodeId: Set ReferencesNodeId = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId") ReferencesNodeId.StandardName = "References" ' Dim BrowseParameters: Set BrowseParameters = CreateObject("OpcLabs.EasyOpc.UA.UABrowseParameters") BrowseParameters.NodeClasses = UANodeClass_All ' this is the default, anyway BrowseParameters.ReferenceTypeIds.Add ReferencesNodeId ' On Error Resume Next Dim NodeElementCollection27: Set NodeElementCollection27 = Client27.Browse( _ EndpointDescriptor, ServerNodeDescriptor, BrowseParameters) If Err.Number = 0 Then If NodeElementCollection27.Count <> 0 Then Dim NodeId27: Set NodeId27 = NodeElementCollection27(0).NodeId WScript.Echo NodeId27 End If Else WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description End If On Error Goto 0
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.