This example shows you how to find OPC Unified Automation (UA) servers, connect to them, and browse their namespace to find nodes of interest.
OPC UA servers structure available data through one or more namespaces, consisting of multiple connected Nodes. OPC Toolbox exposes two types of OPC UA Nodes: Object nodes, which help to organise data, and Variable nodes which store data in their Value property. Variables nodes may contain other Variable nodes as children. Each namespace has an Index uniquely identifying that namespace.
All OPC servers must publish a Server node, containing information about the OPC UA server including capabilities of that server, available functionality of the server and other diagnostic information. The Server node must exist as namespace index 0, named 'Server'. This example will explore the ServerCapabilities node contained in the Server node of an example OPC UA server.
PREREQUISITES:
All OPC UA servers register with a Local DIscovery Service on their host. The Local Discovery Service (LDS) publishes all available servers, as well as their unique "address" (or URL) for connecting to that server.
You can discover OPC UA servers available on a host using opcuaserverinfo
. This example uses the local host.
serverList = opcuaserverinfo('localhost')
serverList = 1×2 OPC UA ServerInfo array: index Description Hostname Port ----- ----------------------------------- -------------- ----- 1 UA Sample Server TMOPTI02WIN764 51210 2 Quickstart Historical Access Server TMOPTI02WIN764 62550
The list of servers shows 3 available OPC UA servers, and the port number on which you can connect to the server. You can find a specific server by searching the Description of the servers. Find the server containing the word "Sample".
sampleServerInfo = findDescription(serverList, 'Sample')
sampleServerInfo = OPC UA ServerInfo 'UA Sample Server': Connection Information Hostname: 'TMOPTI02WIN764' Port: 51210
In order to browse the server namespace, you need to construct an OPC UA Client and connect that client to the server. You can construct the client directly from the opcuaserverinfo
results.
uaClient = opcua(sampleServerInfo);
Initially the client is disconnected from the server, and shows a brief summary of the client properties.
disp(uaClient)
OPC UA Client UA Sample Server: Hostname: TMOPTI02WIN764 Port: 51210 Timeout: 10 Status: Disconnected
You know that the client is disconnected by querying the Status property, or calling the isConnected
function.
disp(uaClient.Status) isConnected(uaClient)
Disconnected ans = 0
Once you connect the client to the server, additional properties from the server are displayed.
connect(uaClient) disp(uaClient)
OPC UA Client UA Sample Server: Hostname: TMOPTI02WIN764 Port: 51210 Timeout: 10 Status: Connected ServerState: Running MinSampleRate: 0 sec MaxHistoryReadNodes: 0 MaxHistoryValuesPerNode: 0 MaxReadNodes: 0 MaxWriteNodes: 0
The display shows that the client Status is now 'Connected', the server is in the 'Running' state, and the client stores information regarding server limits. In this case, all limits are set to zero, indicating that there is no server-wide limit for sample rates, maximum nodes or values for read operations on the Sample Server.
The server namespace is incrementally retrieved directly into the OPC UA Client variable in MATLAB. You access the top level of the server namespace using the Namespace
property. This property stores OPC UA Nodes. Each node can contain one or more Children, which are themselves nodes.
topNodes = uaClient.Namespace
topNodes = 1x4 OPC UA Node array: index Name NsInd Identifier NodeType Children ----- ------------- ----- ---------- -------- -------- 1 Server 0 2253 Object 10 2 Data 2 10157 Object 3 3 Boilers 4 1240 Object 2 4 MemoryBuffers 7 1025 Object 2
The node named 'Server'
contains 10 children.
You can search the namespace using indexing into the Children property of available nodes. For example, to find the ServerCapabilities node, you can query the CHildren of the Server node.
serverChildren = topNodes(1).Children
serverChildren = 1x10 OPC UA Node array: index Name NsInd Identifier NodeType Children ----- ------------------ ----- ---------- -------- -------- 1 ServerArray 0 2254 Variable 0 2 NamespaceArray 0 2255 Variable 0 3 ServerStatus 0 2256 Variable 6 4 ServiceLevel 0 2267 Variable 0 5 Auditing 0 2994 Variable 0 6 ServerCapabilities 0 2268 Object 14 7 ServerDiagnostics 0 2274 Object 4 8 VendorServerInfo 0 2295 Object 0 9 ServerRedundancy 0 2296 Object 4 10 Namespaces 0 11715 Object 0
The ServerCapabilities node is the sixth node in the list.
serverCapabilities = serverChildren(6)
serverCapabilities = OPC UA Node object: Name: ServerCapabilities Description: Describes capabilities supported by the server. NamespaceIndex: 0 Identifier: 2268 NodeType: Object Parent: Server Children: 14 nodes.
You can search for nodes from a Node variable, or from the Namespace property directly. To find the 'ServerCapabilities' node without indexing into the Namespace
property, use findNodeByName
. To avoid the search finding all instances of nodes containing the word 'ServerCapabilities' you use the '-once'
parameter.
serverCapabilities = findNodeByName(topNodes, 'ServerCapabilities', '-once')
serverCapabilities = OPC UA Node object: Name: ServerCapabilities Description: Describes capabilities supported by the server. NamespaceIndex: 0 Identifier: 2268 NodeType: Object Parent: Server Children: 14 nodes.
To find all nodes containing the word 'Double' in the Name, query all topNodes using the '-partial'
parameter. Note that this search will load the entire namespace into MATLAB, so use this search method with caution.
doubleNodes = findNodeByName(topNodes, 'Double', '-partial')
doubleNodes = 1x13 OPC UA Node array: index Name NsInd Identifier NodeType Children ----- ----------- ----- ---------- -------- -------- 1 Double 8 Double Object 101 2 DoubleValue 2 10226 Variable 0 3 DoubleValue 2 10310 Variable 0 4 DoubleValue 2 10394 Variable 0 5 DoubleValue 2 10473 Variable 0 6 DoubleValue 2 10596 Variable 1 7 DoubleValue 2 10731 Variable 1 8 DoubleValue 2 10854 Variable 0 9 DoubleValue 2 10938 Variable 0 10 DoubleValue 2 11022 Variable 0 11 DoubleValue 2 11101 Variable 0 12 DoubleValue 2 11224 Variable 1 13 DoubleValue 2 11359 Variable 1
Nodes have a NodeType which describes whether that node is simply an organisational unit (an Object NodeType) or contains data (a Variable NodeType). Variable NodeTypes may contain Children - A NodeType of Variable does not guarantee that the node contains no Children. In this example, doubleNodes
contains one Object node, and 12 Variable nodes.
allNodeTypes = {doubleNodes.NodeType}
allNodeTypes = Columns 1 through 5 'Object' 'Variable' 'Variable' 'Variable' 'Variable' Columns 6 through 10 'Variable' 'Variable' 'Variable' 'Variable' 'Variable' Columns 11 through 13 'Variable' 'Variable' 'Variable'
A Variable node has additional properties describing the data stored in the Variable node. To view these properties, display a Variable node.
doubleNodes(2)
ans = OPC UA Node object: Name: DoubleValue Description: NamespaceIndex: 2 Identifier: 10226 NodeType: Variable Parent: Scalar Children: 0 nodes. ServerDataType: Double AccessLevelCurrent: read/write AccessLevelHistory: none Historizing: 0
This node has a ServerDataType
of 'Double', and allows reading and writing of the Current value (AccessLevelCurrent
property) but supports no historical data reading (AccessLevelHistory
). The server is not Historizing this node, as evidenced by the Historizing
property.
Some properties, such as ServerValueRank
, and ServerArrayDimensions
are not shown in the display of a node, but can be queried through the respective property. See help on these properties for further information.
Nodes are defined uniquely by their NamespaceIndex and their Identifier. You can construct a known node without browsing the Namespace
property using the opcuanode
function. For example, to construct the ServerCapabilities node directly you can use the NamespaceIndex 0 and Identifier 2268 (all OPC UA servers must publish a ServerCapabilities node with this NamespaceIndex and Identifier).
capabilitiesNode = opcuanode(0, 2268, uaClient)
capabilitiesNode = OPC UA Node object: Name: ServerCapabilities Description: Describes capabilities supported by the server. NamespaceIndex: 0 Identifier: 2268 NodeType: Object Children: 14 nodes.
Note that nodes constructed using opcuanode
have no Parent property.
capabilitiesNode.Parent
ans = Empty OPC UA Node object.
However their Children are automatically retrieved if the node is associated with a connected OPC UA Client.
capabilitiesNode.Children
ans = 1x14 OPC UA Node array: index Name NsInd Identifier NodeType Children ----- ---------------------------- ----- ---------- -------- -------- 1 ServerProfileArray 0 2269 Variable 0 2 LocaleIdArray 0 2271 Variable 0 3 MinSupportedSampleRate 0 2272 Variable 0 4 MaxBrowseContinuationPoints 0 2735 Variable 0 5 MaxQueryContinuationPoints 0 2736 Variable 0 6 MaxHistoryContinuationPoints 0 2737 Variable 0 7 SoftwareCertificates 0 3704 Variable 0 8 MaxArrayLength 0 11702 Variable 0 9 MaxStringLength 0 11703 Variable 0 10 OperationLimits 0 11704 Object 12 11 ModellingRules 0 2996 Object 0 12 AggregateFunctions 0 2997 Object 37 13 HistoryServerCapabilities 0 11192 Object 15 14 HistoryServerCapabilities 6 15820059 Object 15
When you have finished communicating with the server, you should disconnect the client from the server. This is also automatically performed when the client variable goes out of scope in MATLAB.
disconnect(uaClient);