ANSI C UA Server SDK  1.5.1.313
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Modules Pages
democlient.c
/*****************************************************************************
* *
* Copyright (c) 2006-2015 Unified Automation GmbH. All rights reserved. *
* *
* Software License Agreement ("SLA") Version 2.5 *
* *
* Unless explicitly acquired and licensed from Licensor under another *
* license, the contents of this file are subject to the Software License *
* Agreement ("SLA") Version 2.5, or subsequent versions as allowed by the *
* SLA, and You may not copy or use this file in either source code or *
* executable form, except in compliance with the terms and conditions of *
* the SLA. *
* *
* All software distributed under the SLA is provided strictly on an "AS *
* IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, *
* AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT *
* LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR *
* PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the SLA for specific *
* language governing rights and limitations under the SLA. *
* *
* The complete license agreement can be found here: *
* http://unifiedautomation.com/License/SLA/2.5/ *
* *
* Project: Unified Automation ANSI C based OPC UA Server SDK *
* *
*****************************************************************************/
/*============================================================================
* Includes
*===========================================================================*/
#include "democlient.h"
#include <opcua_memory.h>
#include <opcua_datetime.h>
#include <opcua_string.h>
#include <opcua_proxystub.h>
#include <opcua_trace.h>
#include <opcua_pkifactory.h>
#include <uaclient_module.h>
#include <uaclient_discovery.h>
#include <uaclient_session.h>
#include <uaclient_subscription.h>
#include <uabase_p_filesystem.h>
#if OPCUA_SUPPORT_PKI && UABASE_USE_FILESYSTEM
# include <uabase_pki.h>
#endif /* OPCUA_SUPPORT_PKI && UABASE_USE_FILESYSTEM */
/*============================================================================
* Includes End
*===========================================================================*/
#define UACLIENT_APPLICATION_NAME "UaClientC@[gethostname]"
#define UACLIENT_APPLICATION_URI "urn:[gethostname]:UnifiedAutomation:UaDemoClientAnsiC"
#define UACLIENT_PRODUCT_NAME "ANSI C SDK UA Sample Client"
#define UACLIENT_PRODUCT_URI "urn:UnifiedAutomation:UaDemoClientAnsiC"
/*============================================================================
* Global Variables
*===========================================================================*/
/* The UA Stack platform layer instance */
static OpcUa_Handle g_hProxyStubPlatformLayer = OpcUa_Null;
static UaClient g_UaClient;
/*============================================================================
* Global Variables End
*===========================================================================*/
#ifdef WIN32
#include <conio.h>
#else
#include <termios.h>
#include <unistd.h> /* for read() */
static struct termios initial_settings, new_settings;
static int peek_character = -1;
void init_keyboard()
{
printf("Initializing keyboard.\n");
tcgetattr(0,&initial_settings);
new_settings = initial_settings;
new_settings.c_lflag &= ~ICANON;
new_settings.c_lflag &= ~ECHO;
new_settings.c_lflag &= ~ISIG;
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &new_settings);
}
void close_keyboard()
{
printf("Restoring keyboard settings.\n");
tcsetattr(0, TCSANOW, &initial_settings);
}
int _kbhit()
{
unsigned char ch;
int nread;
if (peek_character != -1) return 1;
new_settings.c_cc[VMIN]=0;
tcsetattr(0, TCSANOW, &new_settings);
nread = read(0,&ch,1);
new_settings.c_cc[VMIN]=1;
tcsetattr(0, TCSANOW, &new_settings);
if (nread == 1)
{
peek_character = ch;
return 1;
}
return 0;
}
int _getch()
{
char ch = 0;
ssize_t ret;
if (peek_character != -1)
{
ch = peek_character;
peek_character = -1;
return ch;
}
ret = read(0,&ch,1);
OpcUa_ReferenceParameter(ret);
return ch;
}
#endif
int InitializeOpcUaStack(OpcUa_UInt32 uTraceLevel)
{
OpcUa_StatusCode uStatus;
OpcUa_ProxyStubConfiguration proxyStubConfiguration;
/* Initialize Stack */
printf( "UA Client: Initializing Stack...\n" );
/* Default values can be changed here */
proxyStubConfiguration.bProxyStub_Trace_Enabled = OpcUa_True;
proxyStubConfiguration.uProxyStub_Trace_Level = uTraceLevel;
uStatus = UaBase_Module_InitializeUaStack( &g_hProxyStubPlatformLayer, &proxyStubConfiguration );
return uStatus;
}
void CleanupOpcUaStack()
{
/* Clean Up UA Stack */
UaBase_Module_ClearUaStack( &g_hProxyStubPlatformLayer );
}
#if OPCUA_SUPPORT_PKI && UABASE_USE_FILESYSTEM
void SetupPKIInfrastructure(UaBase_Settings *pSettings, const char *szHostname)
{
OpcUa_Int iRet;
OpcUa_StatusCode uStatus = OpcUa_Good;
UaBase_File *pFile = OpcUa_Null;
OpcUa_Boolean bGenerateCertificate = OpcUa_False;
OpcUa_Boolean bCertAvailable = OpcUa_True;
char szCertificateFile[UABASE_PATH_MAX];
char szCertificateKeyFile[UABASE_PATH_MAX];
char szTrustListPath[UABASE_PATH_MAX];
char szCRLPath[UABASE_PATH_MAX];
char szIssuerTrustListPath[UABASE_PATH_MAX];
char szIssuerCRLPath[UABASE_PATH_MAX];
UaBase_Settings_BeginGroup(pSettings, "PKIStore");
UaBase_Settings_ReadBool(pSettings, "GenerateCertificate", &bGenerateCertificate, OpcUa_False);
UaBase_Settings_ReadString(pSettings, "CertificateFile", szCertificateFile, sizeof(szCertificateFile), "");
UaBase_Settings_ReadString(pSettings, "CertificateKeyFile", szCertificateKeyFile, sizeof(szCertificateKeyFile), "");
UaBase_Settings_ReadString(pSettings, "TrustListPath", szTrustListPath, sizeof(szTrustListPath), "");
UaBase_Settings_ReadString(pSettings, "CRLPath", szCRLPath, sizeof(szCRLPath), "");
UaBase_Settings_ReadString(pSettings, "IssuerTrustListPath", szIssuerTrustListPath, sizeof(szIssuerTrustListPath), "");
UaBase_Settings_ReadString(pSettings, "IssuerCRLPath", szIssuerCRLPath, sizeof(szIssuerCRLPath), "");
iRet = UaBase_MkPath(szTrustListPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create trust list path (ret=%i)\n", iRet);}
iRet = UaBase_MkPath(szCRLPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create CRL path (ret=%i)\n", iRet);}
iRet = UaBase_MkPath(szIssuerTrustListPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create issuer trust list path (ret=%i)\n", iRet);}
iRet = UaBase_MkPath(szIssuerCRLPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create issuer CRL path (ret=%i)\n", iRet);}
if (bGenerateCertificate == OpcUa_False)
{
return;
}
/* check if certificate and private key exist and create new ones if not */
pFile = UaBase_Fopen( szCertificateFile, "r" );
if ( pFile != NULL )
{
UaBase_Fclose( pFile );
}
else
{
bCertAvailable = OpcUa_False;
}
pFile = UaBase_Fopen( szCertificateKeyFile, "r" );
if ( pFile != NULL )
{
UaBase_Fclose( pFile );
}
else
{
bCertAvailable = OpcUa_False;
}
pFile = NULL;
if ( bCertAvailable == OpcUa_False )
{
OpcUa_PkiCertificate *pCertificate = OpcUa_Null;
OpcUa_PkiRsaKeyPair *pSubjectKeyPair = OpcUa_Null;
OpcUa_PkiCertificateInfo certificateInfo;
char szPath[UABASE_PATH_MAX];
char szCommonName[UABASE_PATH_MAX];
char szOrganization[UABASE_PATH_MAX];
char szOrganizationUnit[UABASE_PATH_MAX];
char szLocality[UABASE_PATH_MAX];
char szState[UABASE_PATH_MAX];
char szCountry[UABASE_PATH_MAX];
char szApplicationName[UABASE_PATH_MAX] = UACLIENT_APPLICATION_NAME;
char szApplicationURI[UABASE_PATH_MAX] = UACLIENT_APPLICATION_URI;
OpcUa_UInt iYearsValidFor = 0;
OpcUa_UInt iKeyLength = 0;
UaBase_Settings_ReplaceString(szApplicationURI, sizeof(szApplicationURI), "[gethostname]", szHostname);
UaBase_Settings_ReadString(pSettings, "CommonName", szCommonName, sizeof(szCommonName), "");
UaBase_Settings_ReplaceString(szApplicationName, sizeof(szApplicationName), "[gethostname]", szHostname);
UaBase_Settings_ReplaceString(szCommonName, sizeof(szCommonName), "[ApplicationName]", szApplicationName);
UaBase_Settings_ReadString(pSettings, "Organization", szOrganization, sizeof(szOrganization), "");
UaBase_Settings_ReadString(pSettings, "OrganizationUnit", szOrganizationUnit, sizeof(szOrganizationUnit), "");
UaBase_Settings_ReadString(pSettings, "Locality", szLocality, sizeof(szLocality), "");
UaBase_Settings_ReadString(pSettings, "State", szState, sizeof(szState), "");
UaBase_Settings_ReadString(pSettings, "Country", szCountry, sizeof(szCountry), "");
UaBase_Settings_ReadUInt(pSettings, "YearsValidFor", &iYearsValidFor, 5);
UaBase_Settings_ReadUInt(pSettings, "KeyLength", &iKeyLength, 2048);
uStatus = UaBase_PkiRsaKeyPair_Create( &pSubjectKeyPair, iKeyLength );
if (OpcUa_IsNotGood(uStatus)) {printf("UaClient_PkiRsaKeyPair_Create failed (ret=0x%08x)\n", uStatus);}
certificateInfo.sURI = szApplicationURI;
certificateInfo.sIP = "";
certificateInfo.sDNS = (OpcUa_StringA)szHostname;
certificateInfo.sEMail = "";
certificateInfo.validTime = 3600 * 24 * 365 * iYearsValidFor;
subject.sCommonName = szCommonName;
subject.sOrganization = szOrganization;
subject.sOrganizationUnit = szOrganizationUnit;
subject.sLocality = szLocality;
subject.sState = szState;
subject.sCountry = szCountry;
subject.sDomainComponent = "";
&pCertificate,
certificateInfo,
subject,
*pSubjectKeyPair,
subject,
*pSubjectKeyPair );
if (OpcUa_IsNotGood(uStatus)) {printf("UaClient_PkiCertificate_Create failed (ret=0x%08x)\n", uStatus);}
/* create path for server certificate */
UaBase_strlcpy(szPath, szCertificateFile, sizeof(szPath));
UaBase_DirName(szPath);
iRet = UaBase_MkPath(szPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create certificate path (ret=%i)\n", iRet);}
/* create server certificate */
uStatus = UaBase_PkiCertificate_ToDERFile( pCertificate, szCertificateFile );
if (OpcUa_IsNotGood(uStatus)) {printf("UaClient_PkiCertificate_ToDERFile failed (ret=0x%08x)\n", uStatus);}
/* create path for server key */
UaBase_strlcpy(szPath, szCertificateKeyFile, sizeof(szPath));
UaBase_DirName(szPath);
iRet = UaBase_MkPath(szPath);
if (iRet != UABASE_SUCCESS) {printf("Could not create private key path (ret=%i)\n", iRet);}
/* create server key */
uStatus = UaBase_PkiRsaKeyPair_ToPEMFile( pSubjectKeyPair, szCertificateKeyFile );
if (OpcUa_IsNotGood(uStatus)) {printf("UaClient_PkiRsaKeyPair_ToPEMFile failed (ret=0x%08x)\n", uStatus);}
UaBase_PkiCertificate_Delete( &pCertificate );
UaBase_PkiRsaKeyPair_Delete( &pSubjectKeyPair );
}
}
#endif /* OPCUA_SUPPORT_PKI && UABASE_USE_FILESYSTEM */
void PrintActions()
{
printf("\n");
printf("-------------------------------------------------------\n");
printf("- Press x to close client -\n");
printf("-------------------------------------------------------\n");
printf("- Press 0 to start discovery -\n");
printf("- Press 1 to connect to server -\n");
printf("- Press 2 to connect to server w. AutomaticReconnect -\n");
printf("- Press 3 to disconnect from server -\n");
//printf("- Press 4 to browse server -\n");
printf("- Press 4 to read values -\n");
//printf("- Press 6 to write values -\n");
//printf("- Press 7 to register nodes -\n");
//printf("- Press 8 to unregister nodes -\n");
printf("- Press 5 to create a subscription -\n");
printf("- Press 6 to modify a subscription -\n");
printf("- Press 7 to delete a subscription -\n");
printf("- Press 8 to create monitored items -\n");
//printf("- Press e to modify monitored items -\n");
printf("- Press 9 to delete monitored items -\n");
//printf("- Press 9 to subscribe for alarms -\n");
//printf("- Press a to call a method -\n");
//printf("- Press b to translate browse path to nodeId -\n");
//printf("- Press c to transfer subscription -\n");
//printf("- Press d to history read raw data -\n");
//printf("- Press e to history read processed data -\n");
//printf("- Press f to history read data at timestamps -\n");
//printf("- Press g to history update data -\n");
//printf("- Press h to history delete data -\n");
//printf("- Press i to history read event -\n");
//printf("- Press j to history update event -\n");
//printf("- Press k to history delete event -\n");
printf("-------------------------------------------------------\n");
printf("\n");
}
typedef struct _Demo_Discovery
{
OpcUa_String DiscoveryUrl;
UaClient_Discovery *pDiscovery;
OpcUa_List lstDiscoveryUrls;
OpcUa_List lstEndpoints;
} Demo_Discovery;
OpcUa_Void Demo_FindServers_CB(const UaClient_Discovery *a_pDiscovery,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfServers,
OpcUa_Void *a_pUserData)
{
Demo_Discovery *pDemoDiscovery = (Demo_Discovery*)a_pUserData;
OpcUa_ReferenceParameter(a_pDiscovery);
if (OpcUa_IsGood(a_pResponseHeader->ServiceResult))
{
OpcUa_Int32 i, j;
printf("Demo_FindServers_CB result (0x%08x):\n", a_pResponseHeader->ServiceResult);
for (i = 0; i < a_NoOfServers; i++)
{
printf("[%i] %s:\n", i, OpcUa_String_GetRawString(&a_pServers[i].ApplicationName.Text));
for (j = 0; j < a_pServers[i].NoOfDiscoveryUrls; j++)
{
OpcUa_String *pCopy = OpcUa_Alloc(sizeof(OpcUa_String));
*pCopy = a_pServers[i].DiscoveryUrls[j];
OpcUa_String_Initialize(&a_pServers[i].DiscoveryUrls[j]);
OpcUa_List_AddElementToEnd(&pDemoDiscovery->lstDiscoveryUrls, pCopy);
printf(" %s\n", OpcUa_String_GetRawString(pCopy));
}
}
}
else
{
printf("Demo_FindServers_CB: bad status (0x%08x)\n", a_pResponseHeader->ServiceResult);
PrintActions();
}
}
OpcUa_Void Demo_GetEndpoints_CB(const UaClient_Discovery *a_pDiscovery,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfEndpoints,
OpcUa_Void *a_pUserData)
{
Demo_Discovery *pDemoDiscovery = (Demo_Discovery*)a_pUserData;
OpcUa_ReferenceParameter(a_pDiscovery);
if (OpcUa_IsGood(a_pResponseHeader->ServiceResult))
{
OpcUa_Int32 i;
printf("Demo_GetEndpoints_CB result (0x%08x):\n", a_pResponseHeader->ServiceResult);
for (i = 0; i < a_NoOfEndpoints; i++)
{
*pCopy = a_pEndpoints[i];
OpcUa_EndpointDescription_Initialize(&a_pEndpoints[i]);
OpcUa_List_AddElementToEnd(&pDemoDiscovery->lstEndpoints, pCopy);
printf("[%i]: %s\n", i, OpcUa_String_GetRawString(&pCopy->EndpointUrl));
}
}
else
{
printf("Demo_GetEndpoints_CB: bad status (0x%08x)\n", a_pResponseHeader->ServiceResult);
PrintActions();
}
}
OpcUa_Void Demo_ConnectionStatusChanged_CB(UaClient_Session *a_pSession,
{
const char *pStatus = "INVALID";
OpcUa_ReferenceParameter(a_pSession);
switch (a_status)
{
case UaClient_ConnectionStatus_Disconnected: pStatus = "Disconnected"; PrintActions(); break;
case UaClient_ConnectionStatus_Connecting: pStatus = "Connecting"; PrintActions(); break;
case UaClient_ConnectionStatus_Connected: pStatus = "Connected"; PrintActions(); break;
case UaClient_ConnectionStatus_ConnectionWarningWatchdogTimeout: pStatus = "ConnectionWarningWatchdogTimeout"; break;
case UaClient_ConnectionStatus_ConnectionErrorClientReconnect: pStatus = "ConnectionErrorClientReconnect"; break;
case UaClient_ConnectionStatus_SessionAutomaticallyRecreated: pStatus = "SessionAutomaticallyRecreated"; break;
default: break;
}
printf("\n--> Demo_ConnectionStatusChanged_CB: %s\n\n", pStatus);
}
OpcUa_Boolean Demo_ConnectError_CB(UaClient_Session *a_pSession,
OpcUa_StatusCode a_error,
OpcUa_Boolean a_clientSideError)
{
const char *pServiceType = "INVALID";
OpcUa_ReferenceParameter(a_pSession);
switch (a_serviceType)
{
case UaClient_ConnectServiceType_CertificateValidation: pServiceType = "CertificateValidation"; break;
case UaClient_ConnectServiceType_OpenSecureChannel: pServiceType = "OpenSecureChannel"; break;
case UaClient_ConnectServiceType_CreateSession: pServiceType = "CreateSession"; break;
case UaClient_ConnectServiceType_ActivateSession: pServiceType = "ActivateSession"; break;
default: break;
}
printf("Demo_ConnectError_CB:\n");
printf(" ServiceType: %s\n", pServiceType);
printf(" Error: 0x%08x\n", a_error);
printf(" ClientSideError: %s\n", a_clientSideError == OpcUa_False ? "false" : "true");
return OpcUa_False;
}
OpcUa_Void Demo_Read_CB(const UaClient_Session *a_pSession,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfResults,
OpcUa_DataValue *a_pResults,
OpcUa_Int32 a_NoOfDiagnosticInfos,
OpcUa_DiagnosticInfo *a_pDiagnosticInfos,
OpcUa_Void *a_pUserData)
{
OpcUa_ReferenceParameter(a_pSession);
OpcUa_ReferenceParameter(a_NoOfDiagnosticInfos);
OpcUa_ReferenceParameter(a_pDiagnosticInfos);
OpcUa_ReferenceParameter(a_pUserData);
if (OpcUa_IsGood(a_pResponseHeader->ServiceResult))
{
OpcUa_Int32 i;
printf("Demo_Read_CB:\n");
for (i = 0; i < a_NoOfResults; i++)
{
char szSourceTimestamp[64] = {0};
char szServerTimestamp[64] = {0};
OpcUa_DateTime_GetStringFromDateTime(a_pResults[i].SourceTimestamp, szSourceTimestamp, sizeof(szSourceTimestamp));
OpcUa_DateTime_GetStringFromDateTime(a_pResults[i].ServerTimestamp, szServerTimestamp, sizeof(szServerTimestamp));
printf(" [%i]:\n", i);
printf(" Status: 0x%08x\n", a_pResults[i].StatusCode);
printf(" SourceTimestamp: %s\n", szSourceTimestamp);
printf(" ServerTimestamp: %s\n", szServerTimestamp);
printf(" Value: %i\n", a_pResults[i].Value.Value.Int32);
}
}
else
{
printf("Demo_Read_CB failed (0x%08x)\n", a_pResponseHeader->ServiceResult);
}
PrintActions();
}
OpcUa_StatusCode Demo_Read(UaClient_Session *pSession)
{
OpcUa_ReadValueId nodeToRead;
OpcUa_ReadValueId_Initialize(&nodeToRead);
nodeToRead.AttributeId = OpcUa_Attributes_Value;
nodeToRead.NodeId.NamespaceIndex = 0;
nodeToRead.NodeId.IdentifierType = OpcUa_IdentifierType_Numeric;
nodeToRead.NodeId.Identifier.Numeric = OpcUaId_Server_ServerStatus_State;
return UaClient_Session_BeginRead(pSession,
OpcUa_Null,
0,
1,
&nodeToRead,
Demo_Read_CB,
OpcUa_Null);
}
OpcUa_Void Demo_CreateSubscription_CB(UaClient_Subscription *a_pUaSubscription,
OpcUa_StatusCode a_status,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Void *a_pUserData)
{
OpcUa_ReferenceParameter(a_pResponseHeader);
OpcUa_ReferenceParameter(a_pUserData);
if (OpcUa_IsGood(a_status))
{
printf("Demo_CreateSubscription_CB succeeded (0x%08x)\n", a_status);
printf(" Revised PublishingInterval: %f\n", a_pUaSubscription->RevisedPublishingInterval);
printf(" Revised LifetimeCount: %u\n", a_pUaSubscription->RevisedLifetimeCount);
printf(" Revised MaxKeepAliveCount: %u\n", a_pUaSubscription->RevisedMaxKeepAliveCount);
}
else
{
printf("Demo_CreateSubscription_CB failed (0x%08x)\n", a_status);
}
PrintActions();
}
OpcUa_Void Demo_ModifySubscription_CB(UaClient_Subscription *a_pUaSubscription,
OpcUa_StatusCode a_status,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Void *a_pUserData)
{
OpcUa_ReferenceParameter(a_pResponseHeader);
OpcUa_ReferenceParameter(a_pUserData);
if (OpcUa_IsGood(a_status))
{
printf("Demo_ModifySubscription_CB succeeded (0x%08x)\n", a_status);
printf(" Revised PublishingInterval: %f\n", a_pUaSubscription->RevisedPublishingInterval);
printf(" Revised LifetimeCount: %u\n", a_pUaSubscription->RevisedLifetimeCount);
printf(" Revised MaxKeepAliveCount: %u\n", a_pUaSubscription->RevisedMaxKeepAliveCount);
}
else
{
printf("Demo_ModifySubscription_CB failed (0x%08x)\n", a_status);
}
PrintActions();
}
OpcUa_Void Demo_DeleteSubscription_CB(UaClient_Subscription *a_pUaSubscription,
OpcUa_StatusCode a_status,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Void *a_pUserData)
{
OpcUa_ReferenceParameter(a_pUaSubscription);
OpcUa_ReferenceParameter(a_pResponseHeader);
OpcUa_ReferenceParameter(a_pUserData);
if (OpcUa_IsGood(a_status))
{
printf("Demo_DeleteSubscription_CB succeeded (0x%08x)\n", a_status);
}
else
{
printf("Demo_DeleteSubscription_CB failed (0x%08x)\n", a_status);
}
PrintActions();
}
OpcUa_Void Demo_CreateMonitoredItems_CB(const UaClient_Subscription *a_pSubscription,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfResults,
OpcUa_Int32 a_NoOfDiagnosticInfos,
OpcUa_DiagnosticInfo *a_pDiagnosticInfos,
OpcUa_Void *a_pUserData)
{
OpcUa_StatusCode uStatus;
OpcUa_UInt32 *pMonitoredItemId = a_pUserData;
OpcUa_ReferenceParameter(a_pSubscription);
OpcUa_ReferenceParameter(a_NoOfDiagnosticInfos);
OpcUa_ReferenceParameter(a_pDiagnosticInfos);
OpcUa_ReferenceParameter(a_pUserData);
uStatus = a_pResponseHeader->ServiceResult;
if (OpcUa_IsGood(uStatus))
{
uStatus = a_pResults[0].StatusCode;
}
if (OpcUa_IsGood(uStatus) && a_NoOfResults == 1)
{
printf("Demo_CreateMonitoredItems_CB succeeded (0x%08x)\n", uStatus);
printf(" MonitoredItemId: %u\n", a_pResults[0].MonitoredItemId);
printf(" RevisedSamplingInterval: %f\n", a_pResults[0].RevisedSamplingInterval);
printf(" RevisedQueueSize: %u\n", a_pResults[0].RevisedQueueSize);
*pMonitoredItemId = a_pResults[0].MonitoredItemId;
}
else
{
printf("Demo_CreateMonitoredItems_CB failed (0x%08x)\n", uStatus);
}
PrintActions();
}
OpcUa_Void Demo_DeleteMonitoredItems_CB(const UaClient_Subscription *a_pSubscription,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfResults,
OpcUa_StatusCode *a_pResults,
OpcUa_Int32 a_NoOfDiagnosticInfos,
OpcUa_DiagnosticInfo *a_pDiagnosticInfos,
OpcUa_Void *a_pUserData)
{
OpcUa_StatusCode uStatus;
OpcUa_ReferenceParameter(a_pSubscription);
OpcUa_ReferenceParameter(a_NoOfDiagnosticInfos);
OpcUa_ReferenceParameter(a_pDiagnosticInfos);
OpcUa_ReferenceParameter(a_pUserData);
uStatus = a_pResponseHeader->ServiceResult;
if (OpcUa_IsGood(uStatus))
{
uStatus = a_pResults[0];
}
if (OpcUa_IsGood(uStatus) && a_NoOfResults == 1)
{
printf("Demo_DeleteMonitoredItems_CB succeeded (0x%08x)\n", uStatus);
}
else
{
printf("Demo_DeleteMonitoredItems_CB failed (0x%08x)\n", uStatus);
}
PrintActions();
}
OpcUa_Void Demo_Subscription_StatusChanged_CB(UaClient_Subscription *a_pSubscription,
OpcUa_StatusCode a_status)
{
OpcUa_ReferenceParameter(a_pSubscription);
printf("Demo_Subscription_StatusChanged_CB (0x%08x)\n", a_status);
}
OpcUa_Void Demo_Subscription_KeepAlive_CB(UaClient_Subscription *a_pSubscription)
{
OpcUa_ReferenceParameter(a_pSubscription);
printf("Demo_Subscription_KeepAlive_CB\n");
}
OpcUa_Void Demo_Subscription_NotificationsMissing_CB(UaClient_Subscription *a_pSubscription,
OpcUa_UInt32 a_previousSequenceNumber,
OpcUa_UInt32 a_newSequenceNumber)
{
OpcUa_ReferenceParameter(a_pSubscription);
printf("Demo_Subscription_NotificationsMissing_CB\n");
printf(" PreviousSequenceNumber: %u\n", a_previousSequenceNumber);
printf(" NewSequenceNumber: %u\n", a_newSequenceNumber);
}
OpcUa_Void Demo_Subscription_DataChange_CB(UaClient_Subscription *a_pSubscription,
OpcUa_Int32 a_noOfMonitoredItems,
OpcUa_MonitoredItemNotification *a_pMonitoredItems,
OpcUa_Int32 a_noOfDiagnosticInfos,
OpcUa_DiagnosticInfo *a_pDiagnosticInfos)
{
OpcUa_Int32 i;
OpcUa_ReferenceParameter(a_pSubscription);
OpcUa_ReferenceParameter(a_pDiagnosticInfos);
printf("Demo_Subscription_DataChange_CB\n");
printf(" noOfMonitoredItems: %i\n", a_noOfMonitoredItems);
for (i = 0; i < a_noOfMonitoredItems; i++)
{
OpcUa_CharA szDateTime[64] = {0};
printf(" [%i]:\n", i);
printf(" ClientHandle: %u\n", a_pMonitoredItems[i].ClientHandle);
printf(" StatusCode: 0x%08x\n", a_pMonitoredItems[i].Value.StatusCode);
if (OpcUa_IsGood(a_pMonitoredItems[i].Value.StatusCode))
{
OpcUa_DateTime_GetStringFromDateTime(a_pMonitoredItems[i].Value.SourceTimestamp, szDateTime, sizeof(szDateTime));
printf(" SourceTimestamp: %s\n", szDateTime);
OpcUa_DateTime_GetStringFromDateTime(a_pMonitoredItems[i].Value.ServerTimestamp, szDateTime, sizeof(szDateTime));
printf(" ServerTimestamp: %s\n", szDateTime);
OpcUa_DateTime_GetStringFromDateTime(a_pMonitoredItems[i].Value.Value.Value.DateTime, szDateTime, sizeof(szDateTime));
printf(" Value: %s\n", szDateTime);
}
}
printf(" noOfDiagnosticInfos: %i\n", a_noOfDiagnosticInfos);
}
OpcUa_Void Demo_Subscription_NewEvents_CB(UaClient_Subscription *a_pSubscription,
OpcUa_Int32 a_noOfEvents,
OpcUa_EventFieldList *a_pEvents)
{
OpcUa_ReferenceParameter(a_pSubscription);
OpcUa_ReferenceParameter(a_pEvents);
printf("Demo_Subscription_NewEvents_CB\n");
printf(" noOfEvents: %i\n", a_noOfEvents);
}
int ClientMain(UaBase_Settings *pSettings, const char *szHostname, const char *szUrl)
{
OpcUa_StatusCode uStatus = OpcUa_Good;
OpcUa_Boolean bClientInitialized = OpcUa_False;
UaClient_Configuration *pClientConfiguration = OpcUa_Null;
OpcUa_Boolean bShutdown = OpcUa_False;
UaClient_Session *pSession = OpcUa_Null;
UaClient_Session_Callback sessionCallback;
UaClient_Subscription *pSubscription = OpcUa_Null;
UaClient_Subscription_Callback subscriptionCallback;
Demo_Discovery demoDiscovery;
OpcUa_String *pDiscoveryUrl;
char szValue[UABASE_PATH_MAX] = {0};
OpcUa_UInt32 monitoredItemId = 0;
OpcUa_DeclareErrorTraceModule( OpcUa_Module_Client );
OpcUa_ReferenceParameter(pSettings);
/* Initialize the Client SDK */
uStatus = UaClient_Initialize(&g_UaClient);
OpcUa_GotoErrorIfBad( uStatus );
bClientInitialized = OpcUa_True;
pClientConfiguration = UaClient_GetConfiguration();
uStatus = UaClient_Settings_GetConfigurationFromSettings(pSettings, pClientConfiguration);
OpcUa_GotoErrorIfBad( uStatus );
/* ApplicationDescription and BuildInfo are not set by UaClient_Settings_GetConfigurationFromSettings,
the application has to set those manually */
/* ApplicationDescription */
OpcUa_String_AttachReadOnly(&pClientConfiguration->ApplicationDescription.ApplicationUri, UACLIENT_APPLICATION_URI);
OpcUa_String_AttachReadOnly(&pClientConfiguration->ApplicationDescription.ProductUri, UACLIENT_PRODUCT_URI);
OpcUa_String_AttachReadOnly(&pClientConfiguration->ApplicationDescription.ApplicationName.Text, UACLIENT_APPLICATION_NAME);
/* Replace [gethostname] in ApplicationName and ApplicationUri */
UaBase_Settings_ReplaceUaString(&pClientConfiguration->ApplicationDescription.ApplicationName.Text, "[gethostname]", szHostname);
UaBase_Settings_ReplaceUaString(&pClientConfiguration->ApplicationDescription.ApplicationUri, "[gethostname]", szHostname);
/* Configure discovery and session for using in loop */
uStatus = UaClient_Discovery_Create(&demoDiscovery.pDiscovery);
OpcUa_GotoErrorIfBad(uStatus);
OpcUa_List_Initialize(&demoDiscovery.lstDiscoveryUrls);
OpcUa_List_Initialize(&demoDiscovery.lstEndpoints);
OpcUa_MemSet(&sessionCallback, 0, sizeof(sessionCallback));
sessionCallback.pfConnectionStatusChanged_CB = Demo_ConnectionStatusChanged_CB;
sessionCallback.pfConnectError_CB = Demo_ConnectError_CB;
OpcUa_MemSet(&subscriptionCallback, 0, sizeof(subscriptionCallback));
subscriptionCallback.pfStatusChanged_CB = Demo_Subscription_StatusChanged_CB;
subscriptionCallback.pfKeepAlive_CB = Demo_Subscription_KeepAlive_CB;
subscriptionCallback.pfNotificationsMissing_CB = Demo_Subscription_NotificationsMissing_CB;
subscriptionCallback.pfDataChange_CB = Demo_Subscription_DataChange_CB;
subscriptionCallback.pfNewEvents_CB = Demo_Subscription_NewEvents_CB;
uStatus = UaClient_Session_Create(&sessionCallback, &pSession);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaClient_Subscription_Create(pSession, &subscriptionCallback, &pSubscription);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaBase_Settings_BeginGroup(pSettings, "SampleClient");
OpcUa_GotoErrorIfBad(uStatus);
if (szUrl == OpcUa_Null || OpcUa_StrLenA(szUrl) <= 0)
{
uStatus = UaBase_Settings_ReadUaString(pSettings, "DiscoveryURL", &demoDiscovery.DiscoveryUrl, "opc.tcp://localhost:48020");
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaBase_Settings_ReadUaString(pSettings, "EndpointURL", &pSession->EndpointDescription.EndpointUrl, "");
OpcUa_GotoErrorIfBad(uStatus);
if (uStatus == OpcUa_UncertainSubstituteValue)
{
uStatus = UaBase_Settings_ReadUaString(pSettings, "DiscoveryURL", &pSession->EndpointDescription.EndpointUrl, "opc.tcp://localhost:48020");
OpcUa_GotoErrorIfBad(uStatus);
}
}
else
{
uStatus = OpcUa_String_AttachCopy(&demoDiscovery.DiscoveryUrl, szUrl);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = OpcUa_String_AttachCopy(&pSession->EndpointDescription.EndpointUrl, szUrl);
OpcUa_GotoErrorIfBad(uStatus);
}
uStatus = UaBase_Settings_ReadString(pSettings, "UserTokenType", szValue, sizeof(szValue), "Anonymous");
OpcUa_GotoErrorIfBad(uStatus);
if (OpcUa_StrCmpA(szValue, "Anonymous") == 0)
{
pSession->UserToken.TokenType = OpcUa_UserTokenType_Anonymous;
}
else if (OpcUa_StrCmpA(szValue, "UserName") == 0)
{
pSession->UserToken.TokenType = OpcUa_UserTokenType_UserName;
OpcUa_String_Initialize(&pSession->UserToken.Token.UserName.User);
OpcUa_String_Initialize(&pSession->UserToken.Token.UserName.Password);
uStatus = UaBase_Settings_ReadUaString(pSettings, "User", &pSession->UserToken.Token.UserName.User, "");
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaBase_Settings_ReadUaString(pSettings, "Password", &pSession->UserToken.Token.UserName.Password, "");
OpcUa_GotoErrorIfBad(uStatus);
}
else if (OpcUa_StrCmpA(szValue, "Certificate") == 0)
{
OpcUa_PKIProvider PKIProvider;
OpcUa_CertificateStoreConfiguration PKIConfig;
OpcUa_Handle hCertificateStore = OpcUa_Null;
OpcUa_MemSet(&PKIProvider, 0, sizeof(PKIProvider));
OpcUa_CertificateStoreConfiguration_Initialize(&PKIConfig);
pSession->UserToken.TokenType = OpcUa_UserTokenType_Certificate;
OpcUa_ByteString_Initialize(&pSession->UserToken.Token.X509.UserCertificate);
OpcUa_ByteString_Initialize(&pSession->UserToken.Token.X509.UserPrivateKey);
PKIConfig.strPkiType = (char*)OPCUA_P_PKI_TYPE_OPENSSL;
uStatus = UaBase_Settings_ReadString(pSettings, "UserCertificateLocation", szValue, sizeof(szValue), "");
OpcUa_GotoErrorIfBad(uStatus);
PKIConfig.strTrustedCertificateListLocation = szValue;
uStatus = OpcUa_PKIProvider_Create(&PKIConfig, &PKIProvider);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = PKIProvider.OpenCertificateStore(&PKIProvider,
&hCertificateStore);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = PKIProvider.LoadCertificate(&PKIProvider,
szValue,
hCertificateStore,
&pSession->UserToken.Token.X509.UserCertificate);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = UaBase_Settings_ReadString(pSettings, "UserPrivateKeyLocation", szValue, sizeof(szValue), "");
OpcUa_GotoErrorIfBad(uStatus);
uStatus = PKIProvider.LoadPrivateKeyFromFile(szValue,
OpcUa_Crypto_Encoding_PEM,
OpcUa_Null,
&pSession->UserToken.Token.X509.UserPrivateKey);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = PKIProvider.CloseCertificateStore(&PKIProvider, &hCertificateStore);
OpcUa_GotoErrorIfBad(uStatus);
}
/* StartUp Client */
uStatus = UaClient_StartUp( &g_UaClient );
OpcUa_GotoErrorIfBad( uStatus );
#ifndef WIN32
init_keyboard();
#endif
PrintActions();
/******************************************************************************/
/* Serve! */
while ( OpcUa_IsGood( uStatus ) )
{
if (bShutdown == OpcUa_False)
{
/* Call GetEndpoints for each server returned by FindServers */
OpcUa_UInt32 uNoOfDiscoveryUrls = 0, uNoOfEndpoints = 0;
OpcUa_List_GetNumberOfElements(&demoDiscovery.lstDiscoveryUrls, &uNoOfDiscoveryUrls);
OpcUa_List_GetNumberOfElements(&demoDiscovery.lstEndpoints, &uNoOfEndpoints);
if (uNoOfDiscoveryUrls > 0 && demoDiscovery.pDiscovery->Connected == OpcUa_False)
{
pDiscoveryUrl = OpcUa_List_RemoveFirstElement(&demoDiscovery.lstDiscoveryUrls);
OpcUa_String_Clear(&demoDiscovery.DiscoveryUrl);
demoDiscovery.DiscoveryUrl = *pDiscoveryUrl;
OpcUa_Free(pDiscoveryUrl);
uStatus = UaClient_Discovery_BeginGetEndpoints(demoDiscovery.pDiscovery,
OpcUa_Null,
&demoDiscovery.DiscoveryUrl,
0,
OpcUa_Null,
0,
OpcUa_Null,
Demo_GetEndpoints_CB,
&demoDiscovery);
OpcUa_GotoErrorIfBad(uStatus);
}
/* Let user choose an endpoint */
else if (uNoOfDiscoveryUrls == 0 && uNoOfEndpoints > 0 && demoDiscovery.pDiscovery->Connected == OpcUa_False)
{
OpcUa_UInt32 i = 0;
int iChosen = -1;
printf("Select one of the following endpoints by pressing the according key:\n");
OpcUa_List_ResetCurrent(&demoDiscovery.lstEndpoints);
pEndpoint = OpcUa_List_GetCurrentElement(&demoDiscovery.lstEndpoints);
while (pEndpoint)
{
const char *szSecurityMode = pEndpoint->SecurityMode == OpcUa_MessageSecurityMode_None ? "None" :
pEndpoint->SecurityMode == OpcUa_MessageSecurityMode_SignAndEncrypt ? "SignAndEncrypt" : "Invalid";
printf("[%i]:\n", i);
printf(" EndpointUrl: %s\n", OpcUa_String_GetRawString(&pEndpoint->EndpointUrl));
printf(" SecurityMode: %s\n", szSecurityMode);
printf(" SecurityMode: %s\n", OpcUa_String_GetRawString(&pEndpoint->SecurityPolicyUri));
pEndpoint = OpcUa_List_GetNextElement(&demoDiscovery.lstEndpoints);
i++;
}
while (iChosen == -1)
{
iChosen = _getch() - '0';
if (iChosen >= 0 && iChosen < (int)uNoOfEndpoints)
{
i = 0;
OpcUa_List_ResetCurrent(&demoDiscovery.lstEndpoints);
pEndpoint = OpcUa_List_GetCurrentElement(&demoDiscovery.lstEndpoints);
while (pEndpoint)
{
if (i == (OpcUa_UInt32)iChosen)
{
OpcUa_String sUrl;
OpcUa_String_Initialize(&sUrl);
printf("Using endpoint #%i\n", i);
/* Set session connect info */
OpcUa_EndpointDescription_Clear(&pSession->EndpointDescription);
pSession->EndpointDescription = *pEndpoint;
OpcUa_EndpointDescription_Initialize(pEndpoint);
#if OPCUA_SUPPORT_PKI
if (OpcUa_String_StrnCmp(&pSession->EndpointDescription.SecurityPolicyUri,
OpcUa_String_FromCString(OpcUa_SecurityPolicy_None),
OPCUA_STRING_LENDONTCARE,
OpcUa_False) != 0)
{
/* Check if certificate is trusted */
if (OpcUa_IsBad(uStatus))
{
printf("\nThe server's certificate is not trusted yet.\n");
printf("Press 1 to add certificate to trust list\n");
printf("Press any other key to do nothing\n");
iChosen = _getch() - '0';
if (iChosen == 1)
{
UaClient_TrustCertificate(&pClientConfiguration->PkiConfig,
printf("\n");
printf("Stored server certificate in the client trust list\n");
printf("Make sure the client certificate is in server trust list\n\n");
}
}
}
#endif
/* If EndpointURL is set in settings, use it instead of the
URL returned in the endpoint. */
uStatus = UaBase_Settings_ReadUaString(pSettings, "EndpointURL", &sUrl, "");
OpcUa_GotoErrorIfBad(uStatus);
if (uStatus != OpcUa_UncertainSubstituteValue && OpcUa_String_StrLen(&sUrl) > 0)
{
OpcUa_String_Clear(&pSession->EndpointDescription.EndpointUrl);
pSession->EndpointDescription.EndpointUrl = sUrl;
OpcUa_String_Initialize(&sUrl);
}
OpcUa_String_Clear(&sUrl);
}
else
{
OpcUa_EndpointDescription_Clear(pEndpoint);
}
OpcUa_Free(pEndpoint);
pEndpoint = OpcUa_List_GetNextElement(&demoDiscovery.lstEndpoints);
i++;
}
OpcUa_List_Clear(&demoDiscovery.lstEndpoints);
PrintActions();
}
else
{
printf("Invalid choice, please try again\n");
iChosen = -1;
}
}
}
/* Display action menu */
else if (_kbhit())
{
int iChar = _getch();
switch (iChar)
{
case '0':
uStatus = UaClient_Discovery_BeginFindServers(demoDiscovery.pDiscovery,
OpcUa_Null,
&demoDiscovery.DiscoveryUrl,
0,
OpcUa_Null,
0,
OpcUa_Null,
Demo_FindServers_CB,
&demoDiscovery);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
break;
case '1':
pSession->AutomaticReconnect = OpcUa_False;
uStatus = UaClient_Session_BeginConnect(pSession);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
break;
case '2':
pSession->AutomaticReconnect = OpcUa_True;
uStatus = UaClient_Session_BeginConnect(pSession);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
break;
case '3':
if (pSubscription->IsValid != OpcUa_False)
{
/* Delete the subscription first, Disconnect will be called from Demo_DeleteSubscription_CB */
OpcUa_Null,
Demo_DeleteSubscription_CB,
OpcUa_Null);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
uStatus = UaClient_Session_BeginDisconnect(pSession, OpcUa_True);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
break;
case '4':
uStatus = Demo_Read(pSession);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
break;
case '5':
if (pSubscription->IsValid == OpcUa_False)
{
OpcUa_Null,
Demo_CreateSubscription_CB,
&pSubscription);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
else
{
printf("Subscription already exists!\n");
}
break;
case '6':
if (pSubscription->IsValid != OpcUa_False)
{
OpcUa_Null,
Demo_ModifySubscription_CB,
OpcUa_Null);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
else
{
printf("Subscription does not exist!\n");
}
break;
case '7':
if (pSubscription->IsValid != OpcUa_False)
{
OpcUa_Null,
Demo_DeleteSubscription_CB,
OpcUa_Null);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
else
{
printf("Subscription does not exist!\n");
}
break;
case '8':
if (pSubscription->IsValid == OpcUa_False)
{
printf("Subscription does not exist!\n");
}
else if (monitoredItemId != 0)
{
printf("MonitoredItem already created!\n");
}
else
{
OpcUa_MonitoredItemCreateRequest_Initialize(&createRequest);
createRequest.ItemToMonitor.NodeId.Identifier.Numeric = OpcUaId_Server_ServerStatus_CurrentTime;
createRequest.ItemToMonitor.AttributeId = OpcUa_Attributes_Value;
createRequest.RequestedParameters.ClientHandle = 0;
createRequest.RequestedParameters.SamplingInterval = 100.0;
createRequest.RequestedParameters.QueueSize = 10;
createRequest.RequestedParameters.DiscardOldest = OpcUa_True;
OpcUa_Null,
1,
&createRequest,
Demo_CreateMonitoredItems_CB,
&monitoredItemId);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
break;
case '9':
if (pSubscription->IsValid == OpcUa_False)
{
printf("Subscription does not exist!\n");
}
else if (monitoredItemId == 0)
{
printf("MonitoredItem not created!\n");
}
else
{
OpcUa_Null,
1,
&monitoredItemId,
Demo_DeleteMonitoredItems_CB,
OpcUa_Null);
monitoredItemId = 0;
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
}
break;
case 'x':
uStatus = UaClient_Session_BeginDisconnect(pSession, OpcUa_True);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) {OpcUa_GotoError;}
bShutdown = OpcUa_True;
break;
default:
printf("Unrecognized command '%c'\n", iChar);
PrintActions();
break;
}
}
}
else if (bShutdown != OpcUa_False && pSession->ConnectionStatus == UaClient_ConnectionStatus_Disconnected)
{
break;
}
uStatus = UaClient_DoCom();
}
/******************************************************************************/
#ifndef WIN32
close_keyboard();
#endif
uStatus = UaBase_Settings_EndGroup(pSettings);
OpcUa_GotoErrorIfBad(uStatus);
UaClient_Discovery_Delete(&demoDiscovery.pDiscovery);
OpcUa_List_Clear(&demoDiscovery.lstDiscoveryUrls);
OpcUa_List_Clear(&demoDiscovery.lstEndpoints);
OpcUa_String_Clear(&demoDiscovery.DiscoveryUrl);
/* Clean Up Client */
printf( "UA Client: Main stopped successfully.\n" );
return ( int )uStatus;
Error:
if ( bClientInitialized != OpcUa_False )
{
/* Clean up Base */
}
printf( "UA Client: Main stopped due ERROR! (0x%X)\nPress Enter to close Window!\n", ( unsigned int )uStatus );
getchar();
return ( int )uStatus;
}
/* Helper function to output stack version info.
* The stack returns a token list seperated by '\\'
*/
static void PrintStackInfo(const char *szParamName, const char *szParamList)
{
char szTmp[512];
char *pszToken;
/* we need to copy the string, because parsing will modify it. */
UaBase_strlcpy( szTmp, szParamList, sizeof(szTmp) );
szTmp[511] = '\0';
printf( "%s:\n", szParamName );
pszToken = strtok( szTmp, "\\" ); /* get first token */
while ( pszToken )
{
printf( " %s\n", pszToken );
pszToken = strtok( 0, "\\" ); /* get next token */
}
}
void PrintVersionInfo()
{
printf( "Sample Client of OPC UA SDK ANSI C %u.%u.%u (Build %u)\n", UASDK_MAJOR_VERSION, UASDK_MINOR_VERSION, UASDK_PATCH_VERSION, UASDK_BUILD_VERSION );
printf( "Copyright (C) 2015, Unified Automation GmbH\n" );
PrintStackInfo( "UaStack Version", OpcUa_ProxyStub_GetVersion() );
PrintStackInfo( "UaStack StaticConfigString", OpcUa_ProxyStub_GetStaticConfigString() );
PrintStackInfo( "UaStack Platform Layer Version", OpcUa_P_GetVersion() );
PrintStackInfo( "UaStack Platform Layer ConfigString", OpcUa_P_GetConfigString() );
}