UA Server SDK C++ Bundle  1.3.2.200
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
Lesson 3: Browsing the Model

Content:

Step 1: Adding browse()

Add browse() and exploreAddressSpace()

Add the following code to header,

/* OPC UA service calls */
void browse();

and source file, rsp.:

/*============================================================================
exploreAddressSpace - Browse address space recursively
*===========================================================================*/
void exploreAddressSpace(const UaNodeId& startingNode, unsigned int level)
{
UaStatus status;
UaByteString continuationPoint;
UaReferenceDescriptions referenceDescriptions;
ServiceSettings serviceSettings;
BrowseContext browseContext;
/*********************************************************************
Browse Server
**********************************************************************/
status = g_pUaSession->browse(
serviceSettings,
startingNode,
browseContext,
continuationPoint,
referenceDescriptions);
/*********************************************************************/
if ( status.isBad() )
{
printf("** Error: UaSession::browse of NodeId = %s failed [ret=%s] *********\n",
startingNode.toFullString().toUtf8(), status.toString().toUtf8());
return;
}
else
{
OpcUa_UInt32 i, j;
for (i=0; i<referenceDescriptions.length(); i++)
{
printf("node: ");
for (j=0; j<level; j++) printf(" ");
UaNodeId referenceTypeId(referenceDescriptions[i].ReferenceTypeId);
printf("[Ref=%s] ", referenceTypeId.toString().toUtf8() );
UaQualifiedName browseName(referenceDescriptions[i].BrowseName);
printf("%s ( ", browseName.toString().toUtf8() );
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Object) printf("Object ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Variable) printf("Variable ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Method) printf("Method ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_ObjectType) printf("ObjectType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_VariableType) printf("VariableType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_ReferenceType) printf("ReferenceType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_DataType) printf("DataType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_View) printf("View ");
UaNodeId nodeId(referenceDescriptions[i].NodeId.NodeId);
printf("[NodeId=%s] ", nodeId.toFullString().toUtf8() );
printf(")\n");
exploreAddressSpace(referenceDescriptions[i].NodeId.NodeId, level+1 );
}
// Check if the continuation point was set -> call browseNext
while ( continuationPoint.length() > 0 )
{
/*********************************************************************
Browse remaining nodes in the Server
**********************************************************************/
status = g_pUaSession->browseNext(
serviceSettings,
OpcUa_False,
continuationPoint,
referenceDescriptions);
/*********************************************************************/
if ( status.isBad() )
{
printf("** Error: UaSession::browse of NodeId = %s failed [ret=%s] *********\n",
startingNode.toFullString().toUtf8(), status.toString().toUtf8());
return;
}
else
{
for (i=0; i<referenceDescriptions.length(); i++)
{
printf("node: ");
for (j=0; j<level; j++) printf(" ");
UaNodeId referenceTypeId(referenceDescriptions[i].ReferenceTypeId);
printf("[Ref=%s] ", referenceTypeId.toString().toUtf8() );
UaQualifiedName browseName(referenceDescriptions[i].BrowseName);
printf("%s ( ", browseName.toString().toUtf8() );
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Object) printf("Object ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Variable) printf("Variable ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_Method) printf("Method ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_ObjectType) printf("ObjectType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_VariableType) printf("VariableType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_ReferenceType) printf("ReferenceType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_DataType) printf("DataType ");
if (referenceDescriptions[i].NodeClass & OpcUa_NodeClass_View) printf("View ");
UaNodeId nodeId(referenceDescriptions[i].NodeId.NodeId);
printf("[NodeId=%s] ", nodeId.toFullString().toUtf8() );
printf(")\n");
exploreAddressSpace(referenceDescriptions[i].NodeId.NodeId, level+1 );
}
}
}
}
return;
}
/*============================================================================
browse - Browse address space
*===========================================================================*/
void browse()
{
printf("\n\n****************************************************************\n");
printf("** Try to call browse on root\n");
if ( g_pUaSession == NULL )
{
printf("** Error: Server not connected\n");
printf("****************************************************************\n");
return;
}
// Root as starting node for recursive browsing
UaNodeId startingNode(OpcUaId_RootFolder);
// Start recursive browsing
exploreAddressSpace(startingNode, 1);
}

browse() itself starts the recursive browsing which is implemented by exploreAddressSpace(). The latter calls UaSession::browse() UaSession::browseNext() in order to discover the Address Space.

A client uses the Browse Service of UA by passing a starting Node and browse filters. The server, however, returns the list of referenced nodes matching the filter criteria. The Browse Service takes a list of starting Nodes and returns a list of connected Nodes for each starting Node. Nevertheless, most clients will only pass one starting Node for the main purpose of building a tree hierarchy. UaSession::browse() takes the parameters listed below:

  • serviceSettings: the general service settings like timeout,
  • nodeToBrowse: NodeId of the starting Node,
  • browseContext: filter settings for the browse call,
  • continuationPoint: A continuation point is returned when the server was not able to deliver all results in the Browse response. The limitation can be set by the client in the request or by the server during Browse processing. The continuation point can be passed to browseNext to get the remaining results,
  • referenceDescriptions: List of references and target Node information for the Nodes passing the filter criteria set in the request.

UaSession::browseNext() is used to continue a browse started with the browse method if not all results could be returned by the browse or a following browseNext call. The number of Nodes to return can be limited by the client in the browse request or by the Server during processing the Browse Service call. UaSession::browseNext() takes the following parameters:

  • serviceSettings: the general service settings like timeout,
  • releaseContinuationPoint: indicates if the method is called only for releasing the memory associated with the continuation point,
  • continuationPoint: Continuation points returned from a previous browse or browseNext call. A continuation point is returned when the server was not able to deliver all results in the BrowseNext response. The limitation can be set by the client in the browse or by the server during BrowseNext processing. The continuation point can be passed to browseNext to get the remaining results,
  • referenceDescriptions: List of references and target Node information for the Nodes passing the filter criteria set in the request.

Complete main()

Finally add between connect() and disconnect()

/*********************************************************************
Browse OPC UA Server
**********************************************************************/
browse();
/*********************************************************************/

to main().