ANSI C UA Server SDK  1.6.0.341
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Modules Pages
democlient.c
/*****************************************************************************
* *
* Copyright (c) 2006-2016 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 <uabase_utilities.h>
#include <uaclient_module.h>
#include <uaclient_discovery.h>
#include <uaclient_session.h>
#include <uaclient_subscription.h>
#if OPCUA_SUPPORT_PKI && UABASE_USE_FILESYSTEM
# include <uabase_p_filesystem.h>
# 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;
/* Allow suppressing client side errors in Demo_ConnectError_CB */
OpcUa_Boolean g_bAllowSuppressErrors = OpcUa_True;
/*============================================================================
* Global Variables End
*===========================================================================*/
#if defined(WIN32) && !defined(_WIN32_WCE)
#include <conio.h>
#elif !defined(EUROS_VERSION) && !defined(_WIN32_WCE)
#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;
}
#else
int _kbhit()
{
return 0;
}
int _getch()
{
return 0;
}
#endif
int InitializeOpcUaStack(OpcUa_UInt32 uTraceLevel)
{
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;
OpcUa_CharA szString[UABASE_PATH_MAX];
OpcUa_CharA szCertificateFile[UABASE_PATH_MAX];
OpcUa_CharA szCertificateKeyFile[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", szString, sizeof(szString), "");
iRet = UaBase_MkPath(szString);
if (iRet != UABASE_SUCCESS) { printf("Could not create trust list path (ret=%i)\n", iRet); }
UaBase_Settings_ReadString(pSettings, "CRLPath", szString, sizeof(szString), "");
iRet = UaBase_MkPath(szString);
if (iRet != UABASE_SUCCESS) { printf("Could not create CRL path (ret=%i)\n", iRet); }
UaBase_Settings_ReadString(pSettings, "IssuerTrustListPath", szString, sizeof(szString), "");
iRet = UaBase_MkPath(szString);
if (iRet != UABASE_SUCCESS) { printf("Could not create issuer trust list path (ret=%i)\n", iRet); }
UaBase_Settings_ReadString(pSettings, "IssuerCRLPath", szString, sizeof(szString), "");
iRet = UaBase_MkPath(szString);
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;
OpcUa_CharA szCommonName[64];
OpcUa_CharA szOrganization[64];
OpcUa_CharA szOrganizationUnit[64];
OpcUa_CharA szLocality[64];
OpcUa_CharA szState[64];
OpcUa_CharA szCountry[3];
OpcUa_CharA szApplicationUri[128] = UACLIENT_APPLICATION_URI;
OpcUa_UInt iYearsValidFor = 0;
OpcUa_UInt iKeyLength = 0;
OpcUa_CharA szSignatureAlgorithm[8] = "";
OpcUa_X509SignatureAlgorithm signatureAlgorithm = OpcUa_X509SignatureAlgorithm_Sha256;
OpcUa_StringA_snprintf(szString, sizeof(szString), "%s", UACLIENT_APPLICATION_NAME);
UaBase_Settings_ReplaceString(szString, sizeof(szString), "[gethostname]", szHostname);
UaBase_Settings_ReadString(pSettings, "CommonName", szCommonName, sizeof(szCommonName), "");
UaBase_Settings_ReplaceString(szCommonName, sizeof(szCommonName), "[ApplicationName]", szString);
subject.sCommonName = szCommonName;
UaBase_Settings_ReadString(pSettings, "Organization", szOrganization, sizeof(szOrganization), "");
subject.sOrganization = szOrganization;
UaBase_Settings_ReadString(pSettings, "OrganizationUnit", szOrganizationUnit, sizeof(szOrganizationUnit), "");
subject.sOrganizationUnit = szOrganizationUnit;
UaBase_Settings_ReadString(pSettings, "Locality", szLocality, sizeof(szLocality), "");
subject.sLocality = szLocality;
UaBase_Settings_ReadString(pSettings, "State", szState, sizeof(szState), "");
subject.sState = szState;
UaBase_Settings_ReadString(pSettings, "Country", szCountry, sizeof(szCountry), "");
subject.sCountry = szCountry;
subject.sDomainComponent = "";
UaBase_Settings_ReplaceString(szApplicationUri, sizeof(szApplicationUri), "[gethostname]", szHostname);
certificateInfo.sURI = szApplicationUri;
certificateInfo.sIP = "";
certificateInfo.sDNS = (OpcUa_StringA)szHostname;
certificateInfo.sEMail = "";
UaBase_Settings_ReadUInt(pSettings, "YearsValidFor", &iYearsValidFor, 5);
certificateInfo.validTime = 3600 * 24 * 365 * iYearsValidFor;
UaBase_Settings_ReadUInt(pSettings, "KeyLength", &iKeyLength, 2048);
UaBase_Settings_ReadString(pSettings, "SignatureAlgorithm", szSignatureAlgorithm, sizeof(szSignatureAlgorithm), "Sha256");
uStatus = UaBase_PkiRsaKeyPair_Create(&pSubjectKeyPair, iKeyLength);
if (OpcUa_IsNotGood(uStatus)) { printf("UaBase_PkiRsaKeyPair_Create failed (ret=0x%08x)\n", uStatus); }
if (szSignatureAlgorithm[0] != '\0')
{
if (OpcUa_StrCmpA(szSignatureAlgorithm, "Sha1") == 0) signatureAlgorithm = OpcUa_X509SignatureAlgorithm_Sha1;
else if (OpcUa_StrCmpA(szSignatureAlgorithm, "Sha256") == 0) signatureAlgorithm = OpcUa_X509SignatureAlgorithm_Sha256;
}
&pCertificate,
certificateInfo,
subject,
*pSubjectKeyPair,
subject,
*pSubjectKeyPair,
signatureAlgorithm);
if (OpcUa_IsNotGood(uStatus)) { printf("UaBase_PkiCertificate_Create failed (ret=0x%08x)\n", uStatus); }
/* create path for server certificate */
OpcUa_StrlCpyA(szString, szCertificateFile, sizeof(szString));
UaBase_DirName(szString);
iRet = UaBase_MkPath(szString);
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("UaBase_PkiCertificate_ToDERFile failed (ret=0x%08x)\n", uStatus); }
/* create path for server key */
OpcUa_StrlCpyA(szString, szCertificateKeyFile, sizeof(szString));
UaBase_DirName(szString);
iRet = UaBase_MkPath(szString);
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("UaBase_PkiRsaKeyPair_ToPEMFile failed (ret=0x%08x)\n", uStatus); }
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 5 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 6 to create a subscription -\n");
printf("- Press 7 to modify a subscription -\n");
printf("- Press 8 to delete a subscription -\n");
printf("- Press 9 to create monitored items -\n");
//printf("- Press e to modify monitored items -\n");
printf("- Press a to delete monitored items -\n");
//printf("- Press 9 to subscribe for alarms -\n");
printf("- Press b 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 InitialDiscoveryUrl;
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_Boolean a_clientSideError)
{
OpcUa_Boolean bRet = OpcUa_False;
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_UserIdentityToken: pServiceType = "UserIdentityToken"; 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");
if (a_clientSideError != OpcUa_False && g_bAllowSuppressErrors != OpcUa_False)
{
int iChosen = -1;
printf("\n");
printf("Do you want to ignore this error? (y/n)\n");
while (iChosen == -1)
{
iChosen = _getch();
switch (iChosen)
{
case 'y': bRet = OpcUa_True; break;
case 'n': bRet = OpcUa_False; break;
default:
printf("Invalid choice, please try again\n");
iChosen = -1;
break;
}
}
}
return bRet;
}
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.Identifier.Numeric = OpcUaId_Server_ServerStatus_State;
return UaClient_Session_BeginRead(pSession,
OpcUa_Null,
0,
1,
&nodeToRead,
Demo_Read_CB,
OpcUa_Null);
}
OpcUa_Void Demo_Call_CB(const UaClient_Session *a_pSession,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_DiagnosticInfo *a_pDiagnosticInfo,
OpcUa_Void *a_pUserData)
{
OpcUa_Int32 i;
OpcUa_ReferenceParameter(a_pSession);
OpcUa_ReferenceParameter(a_pDiagnosticInfo);
OpcUa_ReferenceParameter(a_pUserData);
uStatus = a_pResponseHeader->ServiceResult;
if (OpcUa_IsGood(uStatus))
{
uStatus = a_pResult->StatusCode;
}
if (OpcUa_IsGood(uStatus))
{
printf("Demo_Call_CB:\n");
if (a_pResult->NoOfOutputArguments == 2 &&
a_pResult->OutputArguments[0].ArrayType == OpcUa_VariantArrayType_Array &&
a_pResult->OutputArguments[0].Datatype == OpcUaType_UInt32 &&
a_pResult->OutputArguments[1].ArrayType == OpcUa_VariantArrayType_Array &&
a_pResult->OutputArguments[1].Datatype == OpcUaType_UInt32)
{
printf(" ServerHandles:\n");
for (i = 0; i < a_pResult->OutputArguments[0].Value.Array.Length; i++)
{
printf(" [%i]: %u\n", i, a_pResult->OutputArguments[0].Value.Array.Value.UInt32Array[i]);
}
printf(" ClientHandles:\n");
for (i = 0; i < a_pResult->OutputArguments[1].Value.Array.Length; i++)
{
printf(" [%i]: %u\n", i, a_pResult->OutputArguments[1].Value.Array.Value.UInt32Array[i]);
}
}
else
{
printf(" Unexpected output arguments!\n");
}
}
else
{
printf("Demo_Call_CB failed (0x%08x)\n", uStatus);
for (i = 0; i < a_pResult->NoOfInputArgumentResults; i++)
{
printf(" InputArgumentResult[%i]: 0x%08x\n", i, a_pResult->InputArgumentResults[i]);
}
}
PrintActions();
}
OpcUa_StatusCode Demo_Call(UaClient_Session *pSession, OpcUa_UInt32 subscriptionId)
{
OpcUa_CallMethodRequest callMethodRequest;
OpcUa_CallMethodRequest_Initialize(&callMethodRequest);
UaBase_CreateNumericNodeIdEx(&callMethodRequest.ObjectId, OpcUaId_Server, 0);
UaBase_CreateNumericNodeIdEx(&callMethodRequest.MethodId, OpcUaId_Server_GetMonitoredItems, 0);
callMethodRequest.InputArguments = OpcUa_Alloc(sizeof(OpcUa_Variant));
OpcUa_ReturnErrorIfAllocFailed(callMethodRequest.InputArguments);
callMethodRequest.NoOfInputArguments = 1;
OpcUa_Variant_Initialize(&callMethodRequest.InputArguments[0]);
callMethodRequest.InputArguments[0].ArrayType = OpcUa_VariantArrayType_Scalar;
callMethodRequest.InputArguments[0].Datatype = OpcUaType_UInt32;
callMethodRequest.InputArguments[0].Value.UInt32 = subscriptionId;
uStatus = UaClient_Session_BeginCall(pSession,
OpcUa_Null,
&callMethodRequest,
Demo_Call_CB,
OpcUa_Null);
OpcUa_CallMethodRequest_Clear(&callMethodRequest);
return uStatus;
}
OpcUa_StatusCode Demo_Browse(UaClient_Session *pSession, OpcUa_ByteString *pContinuationPoint);
OpcUa_Void Demo_BrowseList_CB(const UaClient_Session *a_pSession,
OpcUa_ResponseHeader *a_pResponseHeader,
OpcUa_Int32 a_NoOfResults,
OpcUa_BrowseResult *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);
/* we expect exactly one BrowseResult with any number of references,
so we can check both status codes at once */
uStatus = a_pResponseHeader->ServiceResult;
if (OpcUa_IsGood(uStatus) && a_NoOfResults == 1)
{
uStatus = a_pResults[0].StatusCode;
}
if (OpcUa_IsGood(uStatus))
{
OpcUa_Int32 i;
printf("Demo_BrowseList_CB:\n");
for (i = 0; i < a_pResults[0].NoOfReferences; i++)
{
printf(" [%i]:\n", i);
switch (a_pResults[0].References[i].NodeId.NodeId.IdentifierType)
{
printf(" NodeId: ns=%hu;i=%u\n",
a_pResults[0].References[i].NodeId.NodeId.NamespaceIndex,
a_pResults[0].References[i].NodeId.NodeId.Identifier.Numeric);
break;
printf(" NodeId: ns=%hu;s=%s\n",
a_pResults[0].References[i].NodeId.NodeId.NamespaceIndex,
OpcUa_String_GetRawString(&a_pResults[0].References[i].NodeId.NodeId.Identifier.String));
break;
default:
printf(" NodeId: Not supported\n");
break;
}
printf(" DisplayName: %s\n",
OpcUa_String_GetRawString(&a_pResults[0].References[i].DisplayName.Text));
printf(" BrowseName: %hu|%s\n",
a_pResults[0].References[i].BrowseName.NamespaceIndex,
OpcUa_String_GetRawString(&a_pResults[0].References[i].BrowseName.Name));
}
if (a_pResults[0].ContinuationPoint.Length > 0)
{
Demo_Browse((UaClient_Session*)a_pSession, &a_pResults[0].ContinuationPoint);
}
else
{
PrintActions();
}
}
else
{
printf("Demo_BrowseList_CB failed (0x%08x)\n", uStatus);
PrintActions();
}
}
OpcUa_StatusCode Demo_Browse(UaClient_Session *pSession, OpcUa_ByteString *pContinuationPoint)
{
if (pContinuationPoint == OpcUa_Null)
{
OpcUa_ViewDescription viewDescription;
OpcUa_BrowseDescription_Initialize(&nodeToBrowse);
OpcUa_ViewDescription_Initialize(&viewDescription);
UaBase_CreateNumericNodeIdEx(&nodeToBrowse.NodeId, OpcUaId_Server, 0);
UaBase_CreateNumericNodeIdEx(&nodeToBrowse.ReferenceTypeId, OpcUaId_HierarchicalReferences, 0);
nodeToBrowse.IncludeSubtypes = OpcUa_True;
nodeToBrowse.NodeClassMask = 0;
nodeToBrowse.ResultMask = OpcUa_BrowseResultMask_All;
/* We use a very small MaxReferencesToReturn value to force a BrowseNext call to be issued. */
OpcUa_Null,
&viewDescription,
5,
1,
&nodeToBrowse,
Demo_BrowseList_CB,
pContinuationPoint);
}
else
{
/* The UaClient_Session_BrowseList_CB has the same signature as UaClient_Session_BrowseListNext_CB,
so we can use the same callback function to handle Browse and BrowseNext responses. */
OpcUa_Null,
OpcUa_False,
1,
pContinuationPoint,
Demo_BrowseList_CB,
pContinuationPoint);
}
}
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_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_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.InitialDiscoveryUrl, "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.InitialDiscoveryUrl, szUrl);
OpcUa_GotoErrorIfBad(uStatus);
uStatus = OpcUa_String_AttachCopy(&pSession->EndpointDescription.EndpointUrl, szUrl);
OpcUa_GotoErrorIfBad(uStatus);
}
uStatus = OpcUa_String_CopyTo(&demoDiscovery.InitialDiscoveryUrl, &demoDiscovery.DiscoveryUrl);
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)
{
#if defined(OPCUA_P_PKI_TYPE_OPENSSL)
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);
#else /* defined(OPCUA_P_PKI_TYPE_OPENSSL) */
printf("Cannot use certificate tokens without OpenSSL\n");
OpcUa_GotoErrorWithStatus(OpcUa_BadConfigurationError);
#endif /* defined(OPCUA_P_PKI_TYPE_OPENSSL) */
}
/* StartUp Client */
uStatus = UaClient_StartUp( &g_UaClient );
OpcUa_GotoErrorIfBad( uStatus );
#if !defined(WIN32) && !defined(EUROS_VERSION)
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;
/* restore original DiscoveryUrl set at application start */
OpcUa_String_CopyTo(&demoDiscovery.InitialDiscoveryUrl, &demoDiscovery.DiscoveryUrl);
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_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 */
g_bAllowSuppressErrors = OpcUa_False;
g_bAllowSuppressErrors = OpcUa_True;
if (OpcUa_IsBad(uStatus))
{
int iTrust = 0;
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");
iTrust = _getch() - '0';
if (iTrust == 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':
case '2':
pSession->AutomaticReconnect = iChar == 1 ? OpcUa_False : OpcUa_True;
uStatus = UaClient_Session_BeginConnect(pSession);
if (OpcUa_IsBad(uStatus))
{
switch (OpcUa_GetCode(uStatus))
{
case OpcUa_BadInvalidState:
case OpcUa_BadCertificateUntrusted:
case OpcUa_BadCertificateRevocationUnknown:
case OpcUa_BadCertificateIssuerRevocationUnknown:
case OpcUa_BadCertificateTimeInvalid:
case OpcUa_BadCertificateIssuerTimeInvalid:
break;
default:
OpcUa_GotoError;
break;
}
}
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_Browse(pSession, OpcUa_Null);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) { OpcUa_GotoError; }
break;
case '5':
uStatus = Demo_Read(pSession);
if (OpcUa_IsBad(uStatus) && uStatus != OpcUa_BadInvalidState) { OpcUa_GotoError; }
break;
case '6':
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 '7':
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 '8':
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 '9':
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 'a':
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 'b':
uStatus = Demo_Call(pSession, pSubscription->SubscriptionId);
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 = UaBase_DoCom();
}
/******************************************************************************/
#if !defined(WIN32) && !defined(EUROS_VERSION)
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.InitialDiscoveryUrl);
OpcUa_String_Clear(&demoDiscovery.DiscoveryUrl);
/* Clean Up Client */
printf( "UA Client: Main stopped successfully.\n" );
return ( int )uStatus;
Error:
if ( bClientInitialized != OpcUa_False )
{
UaClient_Discovery_Delete(&demoDiscovery.pDiscovery);
OpcUa_List_Clear(&demoDiscovery.lstDiscoveryUrls);
OpcUa_List_Clear(&demoDiscovery.lstEndpoints);
OpcUa_String_Clear(&demoDiscovery.InitialDiscoveryUrl);
OpcUa_String_Clear(&demoDiscovery.DiscoveryUrl);
/* Clean up Client */
}
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. */
OpcUa_StrlCpyA( 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() );
}