Step 1: Create New Project
Set up a console application.
Windows:
Create a new project. Use the following settings:
- Win32 Console Application
- No precompiled headers
- Empty project.
Add Files to the Project
Add the following new source files to your project:
- sampleclient.h
- sampleclient.cpp
- The class SampleClient encapsulates OPC UA functionality and it is used to call OPC UA services.
- client_cpp_sdk_tutorial.cpp
- Instantiates the class SampleClient and initiates actions on it, like connect, disconnect etc.
Add Include Directories
Add the following include paths to your application:
[SDK Installation Directory]\include\uastack
[SDK Installation Directory]\include\uabase
[SDK Installation Directory]\include\uaclient
[SDK Installation Directory]\include\uapki
[SDK Installation Directory]\include\xmlparser
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\openssl\inc32
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\libxml2\include
[SDK Installation Directory]\examples\utilities
Linux:
[SDK Installation Directory]/examples/utilities/linux
For more information see LibraryOverview.
Add Linker Settings
Windows:
For Additional Library Directories enter the following values:
[SDK Installation Directory]\lib
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\libxml2\out32dll.dbg (Debug)
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\libxml2\out32dll (Release)
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\openssl\out32dll.dbg (Debug)
[SDK Installation Directory]\third-party\win32\[VisualStudioVersion]\openssl\out32dll (Release)
For Additional Dependencies (Debug) enter:
uastackd.lib
uabased.lib
uapkid.lib
uaclientd.lib
crypt32.lib
libeay32d.lib
ws2_32.lib
rpcrt4.lib
xmlparserd.lib
libxml2d.lib
For Additional Dependencies (Release) enter:
uastack.lib
uabase.lib
uapki.lib
uaclient.lib
crypt32.lib
libeay32.lib
ws2_32.lib
rpcrt4.lib
xmlparser.lib
libxml2.lib
Linux:
For Additional Library Directories enter the following values:
-L[SDK Installation Directory]/lib
For Additional Dependencies (Debug) enter:
-luastackd -luaclientd -luabased -luapkid -lpthread -lrt -lssl
For Additional Dependencies (Release) enter:
-luastack -luaclient -luabase -luapki -lpthread -lrt -lssl
Add Preprocessor Defines
Add:
_UA_STACK_USE_DLL
Additional defines for Windows:
UNICODE
_UNICODE
_CRT_SECURE_NO_WARNINGS
_CRT_SECURE_NO_DEPRECATE
Set Output Path
Set output path to bin where the config file resides.
Windows:
Enter these values:
- Output Directory
- [SDK Installation Directory]\bin
- Intermediate Directory
- obj\$(Configuration)
Step 2: Introducing UaSession and UaSessionCallback
Add the following code to the file sampleclient.h:
#ifndef SAMPLECLIENT_H
#define SAMPLECLIENT_H
#include "uabase.h"
#include "uaclientsdk.h"
{
UA_DISABLE_COPY(SampleClient);
public:
SampleClient();
virtual ~SampleClient();
private:
};
#endif // SAMPLECLIENT_H
The code snippet above declares a pointer to UaSession. This class manages a UA client side application session. It is the main class for connecting to any OPC UA server. It provides all non-Subscription related Services. In addition, the class manages the connection to an OPC UA server and the application session established with the server.
UaSessionCallback defines the callback interface for UaSession. This interface must be implemented by the user of UaSession to receive connection status change callbacks from the Client SDK.
Add the following code to sampleclient.cpp
#include "sampleclient.h"
#include "uasession.h"
SampleClient::SampleClient()
{
}
SampleClient::~SampleClient()
{
if (m_pSession)
{
delete m_pSession;
m_pSession = NULL;
}
}
We implement the method connectionStatusChanged to monitor the connection state using UaSessionCallback.
void SampleClient::connectionStatusChanged(
OpcUa_UInt32 clientConnectionId,
UaClient::ServerStatus serverStatus)
{
OpcUa_ReferenceParameter(clientConnectionId);
printf("-------------------------------------------------------------\n");
switch (serverStatus)
{
case UaClient::Disconnected:
printf("Connection status changed to Disconnected\n");
break;
case UaClient::Connected:
printf("Connection status changed to Connected\n");
break;
case UaClient::ConnectionWarningWatchdogTimeout:
printf("Connection status changed to ConnectionWarningWatchdogTimeout\n");
break;
case UaClient::ConnectionErrorApiReconnect:
printf("Connection status changed to ConnectionErrorApiReconnect\n");
break;
case UaClient::ServerShutdown:
printf("Connection status changed to ServerShutdown\n");
break;
case UaClient::NewSessionCreated:
printf("Connection status changed to NewSessionCreated\n");
break;
}
printf("-------------------------------------------------------------\n");
}
Step 3: Initializing UA Stack and Create Instance of SampleClient
The UA Stack platform layer has to be initialized before calling any Stack or SDK function.
After creating an instance of SampleClient we are prepared to connect to the server.
Add the following code to client_cpp_sdk_tutorial.cpp:
#include "uaplatformlayer.h"
#include "sampleclient.h"
#ifdef _WIN32_WCE
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPWSTR, int)
#else
int main(int, char*[])
#endif
{
SampleClient* pMyClient = new SampleClient();
printf("\nPress Enter to close\n");
getchar();
delete pMyClient;
pMyClient = NULL;
return 0;
}
Step 4: Connect and Disconnect
Add connect()
Add connect() to the header file:
class SampleClient : public UaSessionCallback
{
...
virtual void connectionStatusChanged(OpcUa_UInt32 clientConnectionId, UaClient::ServerStatus serverStatus);
...
};
and the source file:
See SessionConnectInfo for a parameter description.
{
UaString sURL(
"opc.tcp://localhost:48010");
SessionConnectInfo sessionConnectInfo;
char szHostName[256];
if (0 == UA_GetHostname(szHostName, 256))
{
sNodeName = szHostName;
}
sessionConnectInfo.sApplicationName = "Unified Automation Getting Started Client";
sessionConnectInfo.sApplicationUri =
UaString(
"urn:%1:UnifiedAutomation:GettingStartedClient").
arg(sNodeName);
sessionConnectInfo.sProductUri = "urn:UnifiedAutomation:GettingStartedClient";
sessionConnectInfo.sSessionName = sessionConnectInfo.sApplicationUri;
SessionSecurityInfo sessionSecurityInfo;
printf("\nConnecting to %s\n", sURL.toUtf8());
result = m_pSession->connect(
sURL,
sessionConnectInfo,
sessionSecurityInfo,
this);
if (result.isGood())
{
printf("Connect succeeded\n");
}
else
{
printf("Connect failed with status %s\n", result.toString().toUtf8());
}
return result;
}
Add disconnect()
Now we add disconnect() to header file:
and the source file:
{
ServiceSettings serviceSettings;
printf("\nDisconnecting ...\n");
result = m_pSession->disconnect(
serviceSettings,
OpcUa_True);
{
printf("Disconnect succeeded\n");
}
else
{
printf(
"Disconnect failed with status %s\n", result.
toString().
toUtf8());
}
return result;
}
We complete the destructor of SampleClient:
SampleClient::~SampleClient()
{
if (m_pSession)
{
if (m_pSession->isConnected() != OpcUa_False)
{
ServiceSettings serviceSettings;
m_pSession->disconnect(serviceSettings, OpcUa_True);
}
delete m_pSession;
m_pSession = NULL;
}
}
Now we are able to connect to a server and disconnect. Add the following code to main:
...
SampleClient* pMyClient = new SampleClient();
status = pMyClient->connect();
{
printf("\nPress Enter to disconnect\n");
getchar();
status = pMyClient->disconnect();
}
printf("\nPress Enter to close\n");
getchar();
...
Step 5: Read
In the last step of this lesson the client is enabled to read the value attribute of a variable using UaSession::read.
Add read() to the header
and the source file:
{
ServiceSettings serviceSettings;
UaDiagnosticInfos diagnosticInfos;
nodeToRead[0].AttributeId = OpcUa_Attributes_Value;
nodeToRead[0].NodeId.Identifier.Numeric = OpcUaId_Server_ServerStatus_CurrentTime;
printf("\nReading ...\n");
result = m_pSession->read(
serviceSettings,
0,
nodeToRead,
values,
diagnosticInfos);
{
if (OpcUa_IsGood(values[0].StatusCode))
{
printf(
"ServerStatusCurrentTime: %s\n",
UaVariant(values[0].Value).toString().toUtf8());
}
else
{
printf(
"Read failed for item[0] with status %s\n",
UaStatus(values[0].StatusCode).toString().toUtf8());
}
}
else
{
}
return result;
}
Now we are able to call read from main. Add the following code to client_cpp_sdk_tutorial.cpp:
...
{
status = pMyClient->read();
printf("\nPress Enter to disconnect\n");
getchar();
...