Skip to main content

Exploring the OPC UA Address Space

This tutorial shows you how to use the Explore node to discover and navigate the structure of an OPC UA server's address space. The Explore node helps you understand what data is available on a server and how it's organized.

Prerequisites

  • An active connection to an OPC UA server (see Create a connection)
  • Basic understanding of OPC UA address space concepts

What is Address Space Exploration?

The OPC UA address space is a hierarchical structure of nodes representing:

  • Objects: Equipment, systems, folders
  • Variables: Data points, measurements, parameters
  • Methods: Callable functions
  • Types: Data type definitions

The Explore node traverses this structure and returns it as a JSON object, making it easy to understand what's available on the server.

Basic Configuration

Explore Node Setup

  1. Name: Descriptive name for the node
  2. Endpoint: Select your OPC UA server connection
  3. NodeId: Starting point for exploration (optional - can be injected)
  4. Output Type: What to return for leaf nodes (Value, NodeId, etc.)
  5. Follow Organizes: Whether to follow folder references

Example: Explore Server Status

Explore the standard Server Status structure:

[
{
"id": "inject1",
"type": "inject",
"name": "Explore Server Status",
"topic": "/Server/ServerStatus",
"payload": ""
},
{
"id": "explore1",
"type": "OpcUa-Explore",
"name": "Explore",
"endpoint": "opcua_endpoint1",
"outputType": "Value"
},
{
"id": "debug1",
"type": "debug",
"name": "Show Structure"
}
]

Output:

{
"payload": {
"StartTime": "2024-11-24T10:00:00.000Z",
"CurrentTime": "2024-11-24T10:30:45.123Z",
"State": 0,
"BuildInfo": {
"ProductUri": "urn:MyServer",
"ManufacturerName": "ACME Corp",
"ProductName": "MyServer",
"SoftwareVersion": "1.0.0",
"BuildNumber": "12345",
"BuildDate": "2024-01-01T00:00:00.000Z"
},
"SecondsTillShutdown": 0,
"ShutdownReason": {}
}
}

NodeId Specification Methods

Method 1: Static Configuration

Configure the NodeId directly in the Explore node:

// In node configuration
nodeId: "ns=1;s=Equipment.Reactor1"

Method 2: Inject via Topic

Send the NodeId in msg.topic:

{
"topic": "ns=1;s=Equipment.Reactor1"
}

Method 3: Inject via NodeId Property

Send the NodeId in msg.nodeId:

{
"nodeId": "ns=1;s=Equipment.Reactor1"
}

Method 4: Browse Path

Use a browse path starting from /Objects:

{
"topic": "/Server/ServerStatus/BuildInfo"
}

Priority Order:

  1. msg.nodeId (highest)
  2. msg.topic
  3. Configured NodeId (lowest)

Output Types

Control what the Explore node returns for leaf nodes (variables) using msg.outputType or the node configuration:

Value (Default)

Returns the actual value of variables:

{
"topic": "/Server/ServerStatus",
"outputType": "Value"
}

Output:

{
"StartTime": "2024-11-24T10:00:00.000Z",
"CurrentTime": "2024-11-24T10:30:45.123Z",
"State": 0
}

NodeId

Returns NodeIds instead of values - useful for monitoring or reading later:

{
"topic": "/Server/ServerStatus",
"outputType": "NodeId"
}

Output:

{
"StartTime": "ns=0;i=2257",
"CurrentTime": "ns=0;i=2258",
"State": "ns=0;i=2259",
"BuildInfo": "ns=0;i=2260"
}
tip

Use NodeId output type with the Monitor node to automatically monitor entire subtrees!

DataValue

Returns complete DataValue with metadata:

{
"topic": "ns=1;s=Temperature",
"outputType": "DataValue"
}

Output:

{
"Temperature": {
"value": 23.5,
"statusCode": {"value": 0, "description": "Good"},
"sourceTimestamp": "2024-11-24T10:30:45.123Z",
"serverTimestamp": "2024-11-24T10:30:45.125Z"
}
}

BrowsePath

Returns browse paths for each variable:

{
"topic": "/Server/ServerStatus/BuildInfo",
"outputType": "BrowsePath"
}

Output:

{
"ProductUri": "/0:Server/0:ServerStatus/0:BuildInfo/0:ProductUri",
"ManufacturerName": "/0:Server/0:ServerStatus/0:BuildInfo/0:ManufacturerName",
"ProductName": "/0:Server/0:ServerStatus/0:BuildInfo/0:ProductName"
}

AliasedBrowsePath

Returns browse paths with aliased namespaces:

{
"topic": "/Server/ServerStatus/BuildInfo",
"outputType": "AliasedBrowsePath"
}

Output:

{
"ProductUri": "/Server.ServerStatus.BuildInfo.ProductUri",
"ManufacturerName": "/Server.ServerStatus.BuildInfo.ManufacturerName",
"ProductName": "/Server.ServerStatus.BuildInfo.ProductName"
}

Output Type Comparison

Output TypeUse CaseExample
ValueGet actual data23.5
NodeIdFor monitoring/reading"ns=1;i=1001"
DataValueNeed timestamps/quality{value: 23.5, timestamp: "..."}
BrowsePathHuman-readable paths"/Server/ServerStatus/State"
AliasedBrowsePathSimplified paths"/Server.ServerStatus.State"
StatusCodeCheck data quality{value: 0, description: "Good"}

Example: Explore Equipment

Explore a piece of equipment to understand its structure:

[
{
"id": "inject1",
"type": "inject",
"name": "Explore Reactor",
"topic": "ns=2;s=Equipment.Reactor1"
},
{
"id": "explore1",
"type": "OpcUa-Explore",
"name": "Explore",
"endpoint": "opcua_endpoint1",
"outputType": "Value",
"followOrganizes": true
},
{
"id": "function1",
"type": "function",
"name": "Process Structure",
"func": `
// Count how many variables were found
function countVariables(obj) {
let count = 0;
for (const value of Object.values(obj)) {
if (typeof value === 'object' && value !== null) {
count += countVariables(value);
} else {
count++;
}
}
return count;
}

const varCount = countVariables(msg.payload);
node.log(\`Found \${varCount} variables\`);

return msg;
`
},
{
"id": "debug1",
"type": "debug"
}
]

Output Structure:

{
"payload": {
"Process": {
"Temperature": 85.3,
"Pressure": 2.5,
"pH": 7.2
},
"Cooling": {
"InletTemp": 15.0,
"OutletTemp": 22.5,
"FlowRate": 120.0
},
"Status": {
"Running": true,
"Mode": "Auto"
}
}
}

Follow Organizes Reference

The followOrganizes flag controls which references to follow:

When True (Default)

Follows all organizational references:

  • Organizes: Folder structures
  • HasComponent: Equipment components
  • HasProperty: Properties

Use for: Complete exploration of equipment and folders

When False

Only follows:

  • HasComponent: Direct components
  • HasProperty: Direct properties

Use for: Exploring only the direct children of a node

Example:

// Explore complete folder structure
msg.followOrganizes = true;

// Explore only direct properties
msg.followOrganizes = false;

Exclude Empty Nodes

Remove empty folders from the output:

{
"nodeId": "ns=2;s=Equipment",
"excludeEmpty": true
}

Before (excludeEmpty: false):

{
"Reactor1": {
"Temperature": 85.3
},
"Reactor2": {},
"Reactor3": {}
}

After (excludeEmpty: true):

{
"Reactor1": {
"Temperature": 85.3
}
}

Example: Discover Available Data

Explore the Objects folder to see all available equipment:

// Function node: Discover structure
msg.nodeId = "i=85"; // Objects folder
msg.outputType = "NodeId";
msg.followOrganizes = true;

return msg;

Process the result:

// Function node: List all equipment
function listNodes(obj, path = '', result = []) {
for (const [key, value] of Object.entries(obj)) {
const currentPath = path ? `${path}.${key}` : key;

if (typeof value === 'string') {
result.push({
path: currentPath,
nodeId: value
});
} else if (typeof value === 'object') {
listNodes(value, currentPath, result);
}
}
return result;
}

const nodeList = listNodes(msg.payload);
msg.payload = {
total: nodeList.length,
nodes: nodeList
};

return msg;

Limiting Exploration Depth

Control how deep to explore:

{
"nodeId": "ns=2;s=Equipment"
}

Exploration:

  • Explores the full hierarchy under the specified node
  • Use more specific NodeIds to limit scope
  • 3-5: Typical equipment structures
  • 10: Default maximum
  • > 10: Very deep structures (use with caution)

Tips & Best Practices

For comprehensive best practices and optimization techniques, see:

👉 Tips & Best Practices

Key topics covered:

  • Starting with appropriate scope
  • Choosing the right output type
  • Caching exploration results
  • Validation before use
  • Common use cases and patterns

Troubleshooting

For detailed troubleshooting guidance and solutions to common problems, see:

👉 Troubleshooting Exploration

Common issues covered:

  • No results returned
  • Too much data
  • Missing variables
  • Incorrect output format
  • Performance issues
  • Error messages

Next Steps

See Also