UA Server SDK C++ Bundle  1.3.2.200
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
Supplement B: Using OPC UA Discovery Service

Content:

For the sake of completeness this supplement introduces the use of the Discovery Service. Clients use this Service to find existing OPC UA servers and the according EndPoints, rsp.

Step 1: Implementing setup

Add the following code to header,

/* OPC UA service calls */
void startDiscovery(UaString& sUrl, SessionSecurityInfo& sessionSecurityInfo);

and source file, rsp.:

/*============================================================================
startDiscovery - Find available Endpoints
*===========================================================================*/
void startDiscovery(UaString& sUrl, SessionSecurityInfo& sessionSecurityInfo)
{
UaStatus status;
UaString sTempUrl;
UaApplicationDescriptions applicationDescriptions;
UaObjectArray<UaByteString> arrayServerCertificates;
UaObjectArray<UaString> arraySecurityPolicies;
UaUInt32Array arraySecurityMode;
UaEndpointDescriptions endpointDescriptions;
OpcUa_UInt32 endpointCount = 0;
UaString sTemp;
ServiceSettings serviceSettings;
arrayUrls.create(10);
arrayServerCertificates.create(10);
arraySecurityPolicies.create(10);
arraySecurityMode.create(10);
/******************************************************************************/
// Begin Discovery
printf("\n\n");
printf("****************************************************************\n");
printf("** Call findServers and getEndpoints for each Server\n");
UaDiscovery * pUaDiscovery = new UaDiscovery();
sTempUrl = "opc.tcp://localhost:4841";
/*********************************************************************
Find available servers
**********************************************************************/
status = pUaDiscovery->findServers(
serviceSettings, // Use default settings
sTempUrl, // Discovery Server Url
sessionSecurityInfo, // Use general settings for client
applicationDescriptions);
/*********************************************************************/
if ( status.isBad() )
{
printf("** Error: UaDiscovery::findServers failed [ret=0x%lx] *********\n", status.statusCode());
return;
}
for ( OpcUa_UInt32 i=0; i<applicationDescriptions.length(); i++ )
{
for ( OpcUa_Int32 j=0; j<applicationDescriptions[i].NoOfDiscoveryUrls; j++ )
{
sTempUrl = &applicationDescriptions[i].DiscoveryUrls[j];
const char* psUrl = sTempUrl.toUtf8();
if ( sTempUrl.length() > 10 && psUrl[0] == 'o' && psUrl[1] == 'p' && psUrl[2] == 'c' && psUrl[3] == '.' &&
psUrl[4] == 't' && psUrl[5] == 'c' && psUrl[6] == 'p' )
{
/*********************************************************************
Get Endpoints from Server
**********************************************************************/
status = pUaDiscovery->getEndpoints(
serviceSettings, // Use default settings
sTempUrl, // Discovery URL of the found Server
sessionSecurityInfo, // Use general settings for client
endpointDescriptions); // Return
/*********************************************************************/
if ( status.isBad() )
{
printf("** Error: UaDiscovery::getEndpoints failed [ret=0x%lx] *********\n", status.statusCode());
return;
}
for ( OpcUa_UInt32 k=0; k<endpointDescriptions.length(); k++ )
{
sTempUrl = &endpointDescriptions[k].EndpointUrl;
const char* psUrl = sTempUrl.toUtf8();
if ( sTempUrl.length() > 10 && psUrl[0] == 'o' && psUrl[1] == 'p' && psUrl[2] == 'c' && psUrl[3] == '.' &&
psUrl[4] == 't' && psUrl[5] == 'c' && psUrl[6] == 'p' )
{
if ( endpointCount >= 10 )
{
// We can select only 10 endpoints
break;
}
// Store settings necessary to connect for selection
arrayUrls[endpointCount] = &endpointDescriptions[k].EndpointUrl;
arrayServerCertificates[endpointCount] = endpointDescriptions[k].ServerCertificate;
arraySecurityPolicies[endpointCount] = &endpointDescriptions[k].SecurityPolicyUri;
arraySecurityMode[endpointCount] = endpointDescriptions[k].SecurityMode;
printf("** Endpoint[%d] *************************************************\n", endpointCount);
sTemp = &applicationDescriptions[i].ApplicationUri;
printf(" Server Uri %s\n", sTemp.toUtf8());
sTemp = &applicationDescriptions[i].ApplicationName.Text;
printf(" Server Name %s\n", sTemp.toUtf8());
sTemp = &endpointDescriptions[k].EndpointUrl;
printf(" Endpoint URL %s\n", sTemp.toUtf8());
sTemp = &endpointDescriptions[k].SecurityPolicyUri;
printf(" Security Policy %s\n", sTemp.toUtf8());
sTemp = "Invalid";
if ( endpointDescriptions[k].SecurityMode == OpcUa_MessageSecurityMode_None )
{
sTemp = "None";
}
if ( endpointDescriptions[k].SecurityMode == OpcUa_MessageSecurityMode_Sign )
{
sTemp = "Sign";
}
if ( endpointDescriptions[k].SecurityMode == OpcUa_MessageSecurityMode_SignAndEncrypt )
{
sTemp = "SignAndEncrypt";
}
printf(" Security Mode %s\n", sTemp.toUtf8());
printf("****************************************************************\n");
endpointCount++;
}
}
}
}
}
delete pUaDiscovery;
// END Discovery
/******************************************************************************/
printf("- Press index of endpoint you want to connect to -\n");
printf("-------------------------------------------------------\n");
/******************************************************************************/
/* Wait for user command to execute next action. */
int action;
while(!WaitForKeypress(action))
{
if ( action >= 0 && action < (int)endpointCount )
{
sUrl = arrayUrls[action];
sessionSecurityInfo.serverCertificate = arrayServerCertificates[action];
sessionSecurityInfo.sSecurityPolicy = arraySecurityPolicies[action];
sessionSecurityInfo.messageSecurityMode = (OpcUa_MessageSecurityMode)arraySecurityMode[action];
break;
}
Sleep(100);
}
}

startDiscovery() calls

  • findServers() in order to find existing OPC UA servers and their address by sending a FindServers request,and then
  • getEndpoints() in order to get the descriptions of the available EndPoints.

Finally call startDiscovery() in main() :

// Initialize the UA Stack platform layer
/* Setup security */
status = setupSecurity(sessionSecurityInfo);
// ++
/* Find servers and endpoints */
startDiscovery(sUrl, sessionSecurityInfo);
// ++
/* Connect / disconnect */
void connect(sUrl, sessionSecurityInfo);