END_TEST /* Send an async message and receive the response when the securechannel timed out */ START_TEST(SecureChannel_networkfail) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_ReadRequest rq; UA_ReadRequest_init(&rq); UA_ReadValueId rvi; UA_ReadValueId_init(&rvi); rvi.attributeId = UA_ATTRIBUTEID_VALUE; rvi.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); rq.nodesToRead = &rvi; rq.nodesToReadSize = 1; /* Forward the clock after recv in the client */ UA_ClientConfig *cconfig = UA_Client_getConfig(client); UA_Client_recv = client->connection.recv; client->connection.recv = UA_Client_recvTesting; UA_Client_recvSleepDuration = cconfig->secureChannelLifeTime + 1; UA_Variant val; UA_Variant_init(&val); UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_msg(retval == UA_STATUSCODE_BADSECURECHANNELCLOSED); UA_Client_disconnect(client); UA_Client_delete(client); }
END_TEST /* Send the next message after the securechannel timed out */ START_TEST(SecureChannel_timeout_fail) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_ClientConfig *cconfig = UA_Client_getConfig(client); UA_fakeSleep(cconfig->secureChannelLifeTime + 1); UA_realSleep(50 + 1); // UA_MAXTIMEOUT+1 wait to be sure UA_Server_run_iterate can be completely executed UA_Variant val; UA_Variant_init(&val); UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert(retval != UA_STATUSCODE_GOOD); UA_Variant_deleteMembers(&val); UA_Client_disconnect(client); UA_Client_delete(client); }
END_TEST START_TEST(SecureChannel_cableunplugged) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant val; UA_Variant_init(&val); UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant_deleteMembers(&val); UA_Client_recv = client->connection.recv; client->connection.recv = UA_Client_recvTesting; /* Simulate network cable unplugged (no response from server) */ UA_Client_recvTesting_result = UA_STATUSCODE_GOODNONCRITICALTIMEOUT; UA_Variant_init(&val); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_BADCONNECTIONCLOSED); ck_assert_msg(UA_Client_getState(client) == UA_CLIENTSTATE_DISCONNECTED); UA_Client_recvTesting_result = UA_STATUSCODE_GOOD; UA_Client_delete(client); }
static void GetEndpointsAndCheck(const char* discoveryUrl, const char* filterTransportProfileUri, const UA_String expectedEndpointUrls[], size_t expectedEndpointUrlsSize) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); ck_assert_uint_eq(UA_Client_connect(client, discoveryUrl), UA_STATUSCODE_GOOD); UA_EndpointDescription* endpointArray = NULL; size_t endpointArraySize = 0; UA_String discoveryUrlUA = UA_String_fromChars(discoveryUrl); UA_StatusCode retval = GetEndpoints(client, &discoveryUrlUA, &endpointArraySize, &endpointArray, filterTransportProfileUri); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_String_deleteMembers(&discoveryUrlUA); ck_assert_uint_eq(endpointArraySize , expectedEndpointUrlsSize); for(size_t j = 0; j < endpointArraySize && j < expectedEndpointUrlsSize; j++) { UA_EndpointDescription* endpoint = &endpointArray[j]; ck_assert(UA_String_equal(&endpoint->endpointUrl, &expectedEndpointUrls[j])); } UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); UA_Client_delete(client); }
} END_TEST START_TEST(AddAndRemovePublishedDataSetItems){ UA_StatusCode retVal; UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); retVal = UA_Client_connect(client, "opc.tcp://localhost:4840"); if(retVal != UA_STATUSCODE_GOOD) { UA_Client_delete(client); } ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_Variant *inputArguments = (UA_Variant *) UA_calloc(4, (sizeof(UA_Variant))); UA_String pdsName = UA_STRING("Test PDS"); UA_Variant_setScalar(&inputArguments[0], &pdsName, &UA_TYPES[UA_TYPES_STRING]); UA_String *fieldNameAliases = (UA_String *) UA_calloc(2, sizeof(UA_String)); fieldNameAliases[0] = UA_STRING("field1"); fieldNameAliases[1] = UA_STRING("field2"); UA_Variant_setArray(&inputArguments[1], fieldNameAliases, 2, &UA_TYPES[UA_TYPES_STRING]); UA_DataSetFieldFlags *dataSetFieldFlags = (UA_DataSetFieldFlags *) UA_calloc(2, sizeof(UA_DataSetFieldFlags)); dataSetFieldFlags[0] = UA_DATASETFIELDFLAGS_PROMOTEDFIELD; dataSetFieldFlags[1] = UA_DATASETFIELDFLAGS_PROMOTEDFIELD; UA_Variant_setArray(&inputArguments[2], dataSetFieldFlags, 2, &UA_TYPES[UA_TYPES_DATASETFIELDFLAGS]); UA_PublishedVariableDataType *variablesToAdd = (UA_PublishedVariableDataType *) UA_calloc(2, sizeof(UA_PublishedVariableDataType)); variablesToAdd[0].publishedVariable = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_LOCALTIME); variablesToAdd[0].attributeId = UA_ATTRIBUTEID_VALUE; variablesToAdd[1].publishedVariable = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERREDUNDANCY_CURRENTSERVERID); variablesToAdd[1].attributeId = UA_ATTRIBUTEID_VALUE; UA_Variant_setArray(&inputArguments[3], variablesToAdd, 2, &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]); UA_CallMethodRequest callMethodRequest; UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 4; callMethodRequest.inputArguments = inputArguments; callMethodRequest.objectId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS); callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS); UA_CallMethodResult result; UA_CallMethodResult_init(&result); result = UA_Server_call(server, &callMethodRequest); ck_assert_int_eq(3, result.outputArgumentsSize); ck_assert_int_eq(result.statusCode, UA_STATUSCODE_GOOD); //TODO checked correctness of created items UA_CallMethodResult_deleteMembers(&result); UA_free(inputArguments); UA_free(fieldNameAliases); UA_free(dataSetFieldFlags); UA_free(variablesToAdd); UA_Client_disconnect(client); UA_Client_delete(client); } END_TEST
int main(void) { signal(SIGINT, stopHandler); /* catches ctrl-c */ UA_ClientConfig config = UA_ClientConfig_default; /* default timeout is 5 seconds. Set it to 1 second here for demo */ config.timeout = 1000; UA_Client *client = UA_Client_new(config); /* Read the value attribute of the node. UA_Client_readValueAttribute is a * wrapper for the raw read service available as UA_Client_Service_read. */ UA_Variant value; /* Variants can hold scalar values and arrays of any type */ UA_Variant_init(&value); /* Endless loop reading the server time */ while (running) { /* if already connected, this will return GOOD and do nothing */ /* if the connection is closed/errored, the connection will be reset and then reconnected */ /* Alternatively you can also use UA_Client_getState to get the current state */ UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); if (retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_CLIENT, "Not connected. Retrying to connect in 1 second"); /* The connect may timeout after 1 second (see above) or it may fail immediately on network errors */ /* E.g. name resolution errors or unreachable network. Thus there should be a small sleep here */ UA_sleep_ms(1000); continue; } /* NodeId of the variable holding the current time */ const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME); retval = UA_Client_readValueAttribute(client, nodeId, &value); if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_CLIENT, "Connection was closed. Reconnecting ..."); continue; } if (retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) { UA_DateTime raw_date = *(UA_DateTime *) value.data; UA_String string_date = UA_DateTime_toString(raw_date); UA_LOG_INFO(logger, UA_LOGCATEGORY_CLIENT, "string date is: %.*s", (int) string_date.length, string_date.data); UA_String_deleteMembers(&string_date); } UA_sleep_ms(1000); }; /* Clean up */ UA_Variant_deleteMembers(&value); UA_Client_delete(client); /* Disconnects the client internally */ return UA_STATUSCODE_GOOD; }
END_TEST START_TEST(SecureChannel_reconnect) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); client->state = UA_CLIENTSTATE_CONNECTED; retval = UA_Client_disconnect(client); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_ClientConfig *cconfig = UA_Client_getConfig(client); UA_fakeSleep(cconfig->secureChannelLifeTime + 1); UA_realSleep(50 + 1); retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Client_delete(client); }
} END_TEST START_TEST(AddAndRemoveWriterGroups){ UA_StatusCode retVal; UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); retVal = UA_Client_connect(client, "opc.tcp://localhost:4840"); if(retVal != UA_STATUSCODE_GOOD) { UA_Client_delete(client); } ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_NodeId createdConnection = addPubSubConnection(); UA_Variant *inputArgument = (UA_Variant *) UA_calloc(1, (sizeof(UA_Variant))); UA_WriterGroupDataType writerGroupDataType; UA_WriterGroupDataType_init(&writerGroupDataType); writerGroupDataType.name = UA_STRING("TestWriterGroup"); writerGroupDataType.enabled = UA_TRUE; writerGroupDataType.publishingInterval = 500; writerGroupDataType.writerGroupId = 1234; UA_Variant_setScalar(inputArgument, &writerGroupDataType, &UA_TYPES[UA_TYPES_WRITERGROUPDATATYPE]); UA_CallMethodRequest callMethodRequest; UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 1; callMethodRequest.inputArguments = inputArgument; callMethodRequest.objectId = createdConnection; callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP); UA_CallMethodResult result; UA_CallMethodResult_init(&result); result = UA_Server_call(server, &callMethodRequest); ck_assert_int_eq(result.statusCode, UA_STATUSCODE_GOOD); ck_assert_int_eq(1, result.outputArgumentsSize); UA_NodeId createdWriterGroup = UA_NODEID_NULL; if(result.outputArguments->type == &UA_TYPES[UA_TYPES_NODEID]) createdWriterGroup = *((UA_NodeId *) result.outputArguments->data); UA_LocalizedText writerGroupDisplayName; UA_LocalizedText_init(&writerGroupDisplayName); retVal = UA_Server_readDisplayName(server, createdWriterGroup, &writerGroupDisplayName); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_String compareText = UA_STRING("TestWriterGroup"); ck_assert(UA_String_equal(&writerGroupDisplayName.text, &compareText) == UA_TRUE); UA_free(inputArgument); UA_CallMethodResult_deleteMembers(&result); UA_Client_disconnect(client); UA_Client_delete(client); UA_LocalizedText_deleteMembers(&writerGroupDisplayName); } END_TEST
END_TEST START_TEST(Client_methodcall) { UA_Client *client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_UInt32 subId; retval = UA_Client_Subscriptions_new(client, UA_SubscriptionSettings_default, &subId); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* monitor the server state */ UA_UInt32 monId; retval = UA_Client_Subscriptions_addMonitoredItem(client, subId, UA_NODEID_NUMERIC(0, 2259), UA_ATTRIBUTEID_VALUE, NULL, NULL, &monId); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* call a method to get monitored item id */ UA_Variant input; UA_Variant_init(&input); UA_Variant_setScalarCopy(&input, &subId, &UA_TYPES[UA_TYPES_UINT32]); size_t outputSize; UA_Variant *output; retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), 1, &input, &outputSize, &output); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); ck_assert_uint_eq(outputSize, 2); ck_assert_uint_eq(output[0].arrayLength, 1); ck_assert_uint_eq(*((UA_UInt32*)output[0].data), monId); UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]); UA_Variant_deleteMembers(&input); /* call with invalid subscription id */ UA_Variant_init(&input); subId = 0; UA_Variant_setScalarCopy(&input, &subId, &UA_TYPES[UA_TYPES_UINT32]); retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), 1, &input, &outputSize, &output); ck_assert_uint_eq(retval, UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID); UA_Variant_deleteMembers(&input); UA_Client_disconnect(client); UA_Client_delete(client); }
void FORTE_OPC_UA_READ::executeEvent(int pa_nEIID){ switch(pa_nEIID){ case scm_nEventREQID: UA_Int32 value = 0; OUT() = value; UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout_new()); UA_StatusCode connected = UA_Client_connect(client, ClientNetworkLayerTCP_connect, SERVER()); if(connected != UA_STATUSCODE_GOOD) { UA_Client_delete(client); sendOutputEvent(scm_nEventCNFID); } UA_ReadRequest rReq; UA_ReadRequest_init(&rReq); rReq.nodesToRead = UA_ReadValueId_new(); rReq.nodesToReadSize = 1; rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, NODE()); /* assume this node exists */ rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; UA_ReadResponse rResp = UA_Client_read(client, &rReq); if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 && rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) && rResp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) { value = *(UA_Int32*)rResp.results[0].value.data; OUT() = value; }else{ sendOutputEvent(scm_nEventCNFID); } UA_ReadRequest_deleteMembers(&rReq); UA_ReadResponse_deleteMembers(&rResp); UA_Client_disconnect(client); UA_Client_delete(client); sendOutputEvent(scm_nEventCNFID); break; break; } }
END_TEST START_TEST(Client_reconnect) { UA_ClientConfig clientConfig = UA_ClientConfig_default; clientConfig.timeout = 100; UA_Client *client = UA_Client_new(clientConfig); setup(); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant val; UA_NodeId nodeId = UA_NODEID_STRING(1, "my.variable"); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant_deleteMembers(&val); // restart server to test reconnect teardown(); setup(); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_BADCONNECTIONCLOSED); retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant_deleteMembers(&val); UA_Client_disconnect(client); UA_Client_delete(client); teardown(); }
END_TEST START_TEST(Service_TranslateBrowsePathsToNodeIds) { UA_Client *client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode retVal = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); // Just for testing we want to translate the following path to its corresponding node id // /Objects/Server/ServerStatus/State // Equals the following node IDs: // /85/2253/2256/2259 #define BROWSE_PATHS_SIZE 3 char *paths[BROWSE_PATHS_SIZE] = {"Server", "ServerStatus", "State"}; UA_UInt32 ids[BROWSE_PATHS_SIZE] = {UA_NS0ID_ORGANIZES, UA_NS0ID_HASCOMPONENT, UA_NS0ID_HASCOMPONENT}; UA_BrowsePath browsePath; UA_BrowsePath_init(&browsePath); browsePath.startingNode = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); browsePath.relativePath.elements = (UA_RelativePathElement*)UA_Array_new(BROWSE_PATHS_SIZE, &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]); browsePath.relativePath.elementsSize = BROWSE_PATHS_SIZE; for(size_t i = 0; i < BROWSE_PATHS_SIZE; i++) { UA_RelativePathElement *elem = &browsePath.relativePath.elements[i]; elem->referenceTypeId = UA_NODEID_NUMERIC(0, ids[i]); elem->targetName = UA_QUALIFIEDNAME_ALLOC(0, paths[i]); } UA_TranslateBrowsePathsToNodeIdsRequest request; UA_TranslateBrowsePathsToNodeIdsRequest_init(&request); request.browsePaths = &browsePath; request.browsePathsSize = 1; UA_TranslateBrowsePathsToNodeIdsResponse response = UA_Client_Service_translateBrowsePathsToNodeIds(client, request); ck_assert_int_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_int_eq(response.resultsSize, 1); ck_assert_int_eq(response.results[0].targetsSize, 1); ck_assert_int_eq(response.results[0].targets[0].targetId.nodeId.identifierType, UA_NODEIDTYPE_NUMERIC); ck_assert_int_eq(response.results[0].targets[0].targetId.nodeId.identifier.numeric, UA_NS0ID_SERVER_SERVERSTATUS_STATE); UA_BrowsePath_deleteMembers(&browsePath); UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers(&response); retVal = UA_Client_disconnect(client); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_Client_delete(client); }
static void setup(void) { running = UA_Boolean_new(); *running = true; config = UA_ServerConfig_new_default(); config->maxPublishReqPerSession = 5; server = UA_Server_new(config); UA_Server_run_startup(server); addNewEventType(); setupSelectClauses(); THREAD_CREATE(server_thread, serverloop); client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); setupSubscription(); }
END_TEST START_TEST(Client_read) { UA_Client *client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant val; UA_NodeId nodeId = UA_NODEID_STRING(1, "my.variable"); retval = UA_Client_readValueAttribute(client, nodeId, &val); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_Variant_deleteMembers(&val); UA_Client_disconnect(client); UA_Client_delete(client); }
int main(int argc, char *argv[]) { UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout); UA_StatusCode retval = UA_Client_connect(client, UA_ClientConnectionTCP, "opc.tcp://localhost:16664"); if(retval != UA_STATUSCODE_GOOD) { UA_Client_delete(client); return retval; } // Browse some objects printf("Browsing nodes in objects folder:\n"); UA_BrowseRequest bReq; UA_BrowseRequest_init(&bReq); bReq.requestedMaxReferencesPerNode = 0; bReq.nodesToBrowse = UA_BrowseDescription_new(); bReq.nodesToBrowseSize = 1; bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); //browse objects folder bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq); printf("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); for (size_t i = 0; i < bResp.resultsSize; ++i) { for (size_t j = 0; j < bResp.results[i].referencesSize; ++j) { UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) { printf("%-9d %-16d %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length, ref->browseName.name.data, (int)ref->displayName.text.length, ref->displayName.text.data); } else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) { printf("%-9d %-16.*s %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, (int)ref->nodeId.nodeId.identifier.string.length, ref->nodeId.nodeId.identifier.string.data, (int)ref->browseName.name.length, ref->browseName.name.data, (int)ref->displayName.text.length, ref->displayName.text.data); } //TODO: distinguish further types } } UA_BrowseRequest_deleteMembers(&bReq); UA_BrowseResponse_deleteMembers(&bResp); #ifdef UA_ENABLE_SUBSCRIPTIONS // Create a subscription with interval 0 (immediate)... UA_UInt32 subId; UA_Client_Subscriptions_new(client, UA_SubscriptionSettings_standard, &subId); if(subId) printf("Create subscription succeeded, id %u\n", subId); // .. and monitor TheAnswer UA_NodeId monitorThis = UA_NODEID_STRING(1, "the.answer"); UA_UInt32 monId; UA_Client_Subscriptions_addMonitoredItem(client, subId, monitorThis, UA_ATTRIBUTEID_VALUE, &handler_TheAnswerChanged, NULL, &monId); if (monId) printf("Monitoring 'the.answer', id %u\n", subId); // First Publish always generates data (current value) and call out handler. UA_Client_Subscriptions_manuallySendPublishRequest(client); // This should not generate anything UA_Client_Subscriptions_manuallySendPublishRequest(client); #endif UA_Int32 value = 0; // Read node's value printf("\nReading the value of node (1, \"the.answer\"):\n"); UA_ReadRequest rReq; UA_ReadRequest_init(&rReq); rReq.nodesToRead = UA_Array_new(1, &UA_TYPES[UA_TYPES_READVALUEID]); rReq.nodesToReadSize = 1; rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; UA_ReadResponse rResp = UA_Client_Service_read(client, rReq); if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 && rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) && rResp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) { value = *(UA_Int32*)rResp.results[0].value.data; printf("the value is: %i\n", value); } UA_ReadRequest_deleteMembers(&rReq); UA_ReadResponse_deleteMembers(&rResp); value++; // Write node's value printf("\nWriting a value of node (1, \"the.answer\"):\n"); UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = UA_WriteValue_new(); wReq.nodesToWriteSize = 1; wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE; wReq.nodesToWrite[0].value.hasValue = UA_TRUE; wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32]; wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; //do not free the integer on deletion wReq.nodesToWrite[0].value.value.data = &value; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) printf("the new value is: %i\n", value); UA_WriteRequest_deleteMembers(&wReq); UA_WriteResponse_deleteMembers(&wResp); #ifdef UA_ENABLE_SUBSCRIPTIONS // Take another look at the.answer... this should call the handler. UA_Client_Subscriptions_manuallySendPublishRequest(client); // Delete our subscription (which also unmonitors all items) if(!UA_Client_Subscriptions_remove(client, subId)) printf("Subscription removed\n"); #endif #ifdef UA_ENABLE_METHODCALLS /* Note: This example requires Namespace 0 Node 11489 (ServerType -> GetMonitoredItems) FIXME: Provide a namespace 0 independant example on the server side */ UA_Variant input; UA_String argString = UA_STRING("Hello Server"); UA_Variant_init(&input); UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]); UA_Int32 outputSize; UA_Variant *output; retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); if(retval == UA_STATUSCODE_GOOD) { printf("Method call was successfull, and %i returned values available.\n", outputSize); UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]); } else { printf("Method call was unsuccessfull, and %x returned values available.\n", retval); } UA_Variant_deleteMembers(&input); #endif #ifdef UA_ENABLE_NODEMANAGEMENT /* New ReferenceType */ UA_NodeId ref_id; UA_ReferenceTypeAttributes ref_attr; UA_ReferenceTypeAttributes_init(&ref_attr); ref_attr.displayName = UA_LOCALIZEDTEXT("en_US", "NewReference"); ref_attr.description = UA_LOCALIZEDTEXT("en_US", "References something that might or might not exist"); ref_attr.inverseName = UA_LOCALIZEDTEXT("en_US", "IsNewlyReferencedBy"); retval = UA_Client_addReferenceTypeNode(client, UA_NODEID_NUMERIC(1, 12133), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, "NewReference"), ref_attr, &ref_id); if(retval == UA_STATUSCODE_GOOD ) printf("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric); /* New ObjectType */ UA_NodeId objt_id; UA_ObjectTypeAttributes objt_attr; UA_ObjectTypeAttributes_init(&objt_attr); objt_attr.displayName = UA_LOCALIZEDTEXT("en_US", "TheNewObjectType"); objt_attr.description = UA_LOCALIZEDTEXT("en_US", "Put innovative description here"); retval = UA_Client_addObjectTypeNode(client, UA_NODEID_NUMERIC(1, 12134), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "NewObjectType"), objt_attr, &objt_id); if(retval == UA_STATUSCODE_GOOD) printf("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric); /* New Object */ UA_NodeId obj_id; UA_ObjectAttributes obj_attr; UA_ObjectAttributes_init(&obj_attr); obj_attr.displayName = UA_LOCALIZEDTEXT("en_US", "TheNewGreatNode"); obj_attr.description = UA_LOCALIZEDTEXT("de_DE", "Hier koennte Ihre Webung stehen!"); retval = UA_Client_addObjectNode(client, UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "TheGreatNode"), UA_NODEID_NUMERIC(1, 12134), obj_attr, &obj_id); if(retval == UA_STATUSCODE_GOOD ) printf("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric); /* New Integer Variable */ UA_NodeId var_id; UA_VariableAttributes var_attr; UA_VariableAttributes_init(&var_attr); var_attr.displayName = UA_LOCALIZEDTEXT("en_US", "TheNewVariableNode"); var_attr.description = UA_LOCALIZEDTEXT("en_US", "This integer is just amazing - it has digits and everything."); UA_Int32 int_value = 1234; /* This does not copy the value */ UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]); var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; retval = UA_Client_addVariableNode(client, UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(0, "VariableNode"), UA_NODEID_NULL, // no variable type var_attr, &var_id); if(retval == UA_STATUSCODE_GOOD ) printf("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric); #endif UA_Client_disconnect(client); UA_Client_delete(client); return UA_STATUSCODE_GOOD; }
} END_TEST START_TEST(AddAndRemovePublishedDataSetFolders){ UA_StatusCode retVal; UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); retVal = UA_Client_connect(client, "opc.tcp://localhost:4840"); if(retVal != UA_STATUSCODE_GOOD) { UA_Client_delete(client); } ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_String folderName = UA_STRING("TestFolder"); UA_Variant inputArguments; UA_Variant_init(&inputArguments); UA_Variant_setScalar(&inputArguments, &folderName, &UA_TYPES[UA_TYPES_STRING]); UA_CallMethodRequest callMethodRequest; UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 1; callMethodRequest.inputArguments = &inputArguments; callMethodRequest.objectId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS); callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER); UA_CallMethodResult result; UA_CallMethodResult_init(&result); result = UA_Server_call(server, &callMethodRequest); ck_assert_int_eq(1, result.outputArgumentsSize); ck_assert_int_eq(result.statusCode, UA_STATUSCODE_GOOD); UA_NodeId createdFolder = UA_NODEID_NULL; if(result.outputArguments->type == &UA_TYPES[UA_TYPES_NODEID]) createdFolder = *((UA_NodeId *) result.outputArguments->data); UA_LocalizedText connectionDisplayName; UA_LocalizedText_init(&connectionDisplayName); retVal = UA_Server_readDisplayName(server, createdFolder, &connectionDisplayName); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_String compareText = UA_STRING("TestFolder"); ck_assert(UA_String_equal(&connectionDisplayName.text, &compareText) == UA_TRUE); retVal = UA_Server_readNodeId(server, createdFolder, &createdFolder); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_CallMethodResult_deleteMembers(&result); UA_LocalizedText_deleteMembers(&connectionDisplayName); //create folder inside the new folder folderName = UA_STRING("TestFolder2"); UA_Variant_init(&inputArguments); UA_Variant_setScalar(&inputArguments, &folderName, &UA_TYPES[UA_TYPES_STRING]); UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 1; callMethodRequest.inputArguments = &inputArguments; callMethodRequest.objectId = createdFolder; callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER); UA_CallMethodResult_init(&result); result = UA_Server_call(server, &callMethodRequest); ck_assert_int_eq(1, result.outputArgumentsSize); ck_assert_int_eq(result.statusCode, UA_STATUSCODE_GOOD); UA_NodeId createdFolder2 = UA_NODEID_NULL; if(result.outputArguments->type == &UA_TYPES[UA_TYPES_NODEID]) createdFolder2 = *((UA_NodeId *) result.outputArguments->data); UA_LocalizedText_init(&connectionDisplayName); retVal = UA_Server_readDisplayName(server, createdFolder2, &connectionDisplayName); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); compareText = UA_STRING("TestFolder2"); ck_assert(UA_String_equal(&connectionDisplayName.text, &compareText) == UA_TRUE); retVal = UA_Server_readNodeId(server, createdFolder2, &createdFolder2); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_CallMethodResult_deleteMembers(&result); //delete the folder UA_Variant_init(&inputArguments); UA_Variant_setScalar(&inputArguments, &createdFolder, &UA_TYPES[UA_TYPES_NODEID]); UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 1; callMethodRequest.inputArguments = &inputArguments; callMethodRequest.objectId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS); callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER); result = UA_Server_call(server, &callMethodRequest); ck_assert_int_eq(0, result.outputArgumentsSize); ck_assert_int_eq(result.statusCode, UA_STATUSCODE_GOOD); //check if the node is deleted retVal = UA_Server_readNodeId(server, createdFolder, NULL); ck_assert_int_eq(retVal, UA_STATUSCODE_BADNODEIDUNKNOWN); UA_CallMethodResult_deleteMembers(&result); UA_Client_disconnect(client); UA_Client_delete(client); UA_LocalizedText_deleteMembers(&connectionDisplayName); } END_TEST
int main(int argc, char *argv[]) { UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout_new()); UA_StatusCode retval = UA_Client_connect(client, ClientNetworkLayerTCP_connect, "opc.tcp://localhost:16664"); if(retval != UA_STATUSCODE_GOOD) { UA_Client_delete(client); return retval; } // Browse some objects printf("Browsing nodes in objects folder:\n"); UA_BrowseRequest bReq; UA_BrowseRequest_init(&bReq); bReq.requestedMaxReferencesPerNode = 0; bReq.nodesToBrowse = UA_BrowseDescription_new(); bReq.nodesToBrowseSize = 1; bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); //browse objects folder bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything UA_BrowseResponse bResp = UA_Client_browse(client, &bReq); printf("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); for (int i = 0; i < bResp.resultsSize; ++i) { for (int j = 0; j < bResp.results[i].referencesSize; ++j) { UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) { printf("%-9d %-16d %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, ref->nodeId.nodeId.identifier.numeric, ref->browseName.name.length, ref->browseName.name.data, ref->displayName.text.length, ref->displayName.text.data); } else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) { printf("%-9d %-16.*s %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, ref->nodeId.nodeId.identifier.string.length, ref->nodeId.nodeId.identifier.string.data, ref->browseName.name.length, ref->browseName.name.data, ref->displayName.text.length, ref->displayName.text.data); } //TODO: distinguish further types } } UA_BrowseRequest_deleteMembers(&bReq); UA_BrowseResponse_deleteMembers(&bResp); #ifdef ENABLE_SUBSCRIPTIONS // Create a subscription with interval 0 (immediate)... UA_Int32 subId = UA_Client_newSubscription(client, 0); if (subId) printf("Create subscription succeeded, id %u\n", subId); // .. and monitor TheAnswer UA_NodeId monitorThis; monitorThis = UA_NODEID_STRING_ALLOC(1, "the.answer"); UA_UInt32 monId = UA_Client_monitorItemChanges(client, subId, monitorThis, UA_ATTRIBUTEID_VALUE, &handler_TheAnswerChanged ); if (monId) printf("Monitoring 'the.answer', id %u\n", subId); UA_NodeId_deleteMembers(&monitorThis); // First Publish always generates data (current value) and call out handler. UA_Client_doPublish(client); // This should not generate anything UA_Client_doPublish(client); #endif UA_Int32 value = 0; // Read node's value printf("\nReading the value of node (1, \"the.answer\"):\n"); UA_ReadRequest rReq; UA_ReadRequest_init(&rReq); rReq.nodesToRead = UA_ReadValueId_new(); rReq.nodesToReadSize = 1; rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; UA_ReadResponse rResp = UA_Client_read(client, &rReq); if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 && rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) && rResp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) { value = *(UA_Int32*)rResp.results[0].value.data; printf("the value is: %i\n", value); } UA_ReadRequest_deleteMembers(&rReq); UA_ReadResponse_deleteMembers(&rResp); value++; // Write node's value printf("\nWriting a value of node (1, \"the.answer\"):\n"); UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = UA_WriteValue_new(); wReq.nodesToWriteSize = 1; wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE; wReq.nodesToWrite[0].value.hasValue = UA_TRUE; wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32]; wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; //do not free the integer on deletion wReq.nodesToWrite[0].value.value.data = &value; UA_WriteResponse wResp = UA_Client_write(client, &wReq); if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) printf("the new value is: %i\n", value); UA_WriteRequest_deleteMembers(&wReq); UA_WriteResponse_deleteMembers(&wResp); #ifdef ENABLE_SUBSCRIPTIONS // Take another look at the.answer... this should call the handler. UA_Client_doPublish(client); // Delete our subscription (which also unmonitors all items) if(!UA_Client_removeSubscription(client, subId)) printf("Subscription removed\n"); #endif #ifdef ENABLE_METHODCALLS /* Note: This example requires Namespace 0 Node 11489 (ServerType -> GetMonitoredItems) FIXME: Provide a namespace 0 independant example on the server side */ UA_Variant input; UA_String argString = UA_STRING("Hello Server"); UA_Variant_init(&input); UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]); UA_Int32 outputSize; UA_Variant *output; retval = UA_Client_CallServerMethod(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); if(retval == UA_STATUSCODE_GOOD) { printf("Method call was successfull, and %i returned values available.\n", outputSize); UA_Array_delete(output, &UA_TYPES[UA_TYPES_VARIANT], outputSize); } else { printf("Method call was unsuccessfull, and %x returned values available.\n", retval); } UA_Variant_deleteMembers(&input); #endif #ifdef ENABLE_ADDNODES /* Create a new object type node */ // New ReferenceType UA_AddNodesResponse *adResp = UA_Client_createReferenceTypeNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 12133), // Assign this NodeId (will fail if client is called multiple times) UA_QUALIFIEDNAME(0, "NewReference"), UA_LOCALIZEDTEXT("en_US", "TheNewReference"), UA_LOCALIZEDTEXT("en_US", "References something that might or might not exist."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_LOCALIZEDTEXT("en_US", "IsNewlyReferencedBy")); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewReference' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); // New ObjectType adResp = UA_Client_createObjectTypeNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 12134), // Assign this NodeId (will fail if client is called multiple times) UA_QUALIFIEDNAME(0, "NewObjectType"), UA_LOCALIZEDTEXT("en_US", "TheNewObjectType"), UA_LOCALIZEDTEXT("en_US", "Put innovative description here."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewObjectType' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } // New Object adResp = UA_Client_createObjectNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_QUALIFIEDNAME(0, "TheNewGreatNodeBrowseName"), UA_LOCALIZEDTEXT("en_US", "TheNewGreatNode"), UA_LOCALIZEDTEXT("de_DE", "Hier koennte Ihre Webung stehen!"), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewObject' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); // New Integer Variable UA_Variant *theValue = UA_Variant_new(); UA_Int32 *theValueDate = UA_Int32_new(); *theValueDate = 1234; theValue->type = &UA_TYPES[UA_TYPES_INT32]; theValue->data = theValueDate; adResp = UA_Client_createVariableNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_QUALIFIEDNAME(0, "VariableNode"), UA_LOCALIZEDTEXT("en_US", "TheNewVariableNode"), UA_LOCALIZEDTEXT("en_US", "This integer is just amazing - it has digits and everything."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_INT32), theValue); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewVariable' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); free(theValue); /* Done creating a new node*/ #endif UA_Client_disconnect(client); UA_Client_delete(client); return UA_STATUSCODE_GOOD; }
static UA_StatusCode register_server_with_discovery_server(UA_Server *server, const char* discoveryServerUrl, const UA_Boolean isUnregister, const char* semaphoreFilePath) { if(!discoveryServerUrl) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER, "No discovery server url provided"); return UA_STATUSCODE_BADINTERNALERROR; } /* Create the client */ UA_Client *client = UA_Client_new(UA_ClientConfig_default); if(!client) return UA_STATUSCODE_BADOUTOFMEMORY; /* Connect the client */ UA_StatusCode retval = UA_Client_connect(client, discoveryServerUrl); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT, "Connecting to the discovery server failed with statuscode %s", UA_StatusCode_name(retval)); UA_Client_delete(client); return retval; } /* Prepare the request. Do not cleanup the request after the service call, * as the members are stack-allocated or point into the server config. */ UA_RegisterServer2Request request; UA_RegisterServer2Request_init(&request); request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; request.server.isOnline = !isUnregister; request.server.serverUri = server->config.applicationDescription.applicationUri; request.server.productUri = server->config.applicationDescription.productUri; request.server.serverType = server->config.applicationDescription.applicationType; request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri; if(semaphoreFilePath) { #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE request.server.semaphoreFilePath = UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */ #else UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_CLIENT, "Ignoring semaphore file path. open62541 not compiled " "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON"); #endif } request.server.serverNames = &server->config.applicationDescription.applicationName; request.server.serverNamesSize = 1; /* Copy the discovery urls from the server config and the network layers*/ size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize; size_t nl_discurls = server->config.networkLayersSize; size_t total_discurls = config_discurls * nl_discurls; request.server.discoveryUrls = (UA_String*)UA_alloca(sizeof(UA_String) * total_discurls); request.server.discoveryUrlsSize = config_discurls + nl_discurls; for(size_t i = 0; i < config_discurls; ++i) request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i]; /* TODO: Add nl only if discoveryUrl not already present */ for(size_t i = 0; i < nl_discurls; ++i) { UA_ServerNetworkLayer *nl = &server->config.networkLayers[i]; request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl; } UA_MdnsDiscoveryConfiguration mdnsConfig; UA_MdnsDiscoveryConfiguration_init(&mdnsConfig); request.discoveryConfigurationSize = 1; request.discoveryConfiguration = UA_ExtensionObject_new(); UA_ExtensionObject_init(&request.discoveryConfiguration[0]); request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]; request.discoveryConfiguration[0].content.decoded.data = &mdnsConfig; mdnsConfig.mdnsServerName = server->config.mdnsServerName; mdnsConfig.serverCapabilities = server->config.serverCapabilities; mdnsConfig.serverCapabilitiesSize = server->config.serverCapabilitiesSize; // First try with RegisterServer2, if that isn't implemented, use RegisterServer UA_RegisterServer2Response response; UA_RegisterServer2Response_init(&response); __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]); UA_StatusCode serviceResult = response.responseHeader.serviceResult; UA_RegisterServer2Response_deleteMembers(&response); UA_ExtensionObject_delete(request.discoveryConfiguration); if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED || serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) { /* Try RegisterServer */ UA_RegisterServerRequest request_fallback; UA_RegisterServerRequest_init(&request_fallback); /* Copy from RegisterServer2 request */ request_fallback.requestHeader = request.requestHeader; request_fallback.server = request.server; UA_RegisterServerResponse response_fallback; UA_RegisterServerResponse_init(&response_fallback); __UA_Client_Service(client, &request_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], &response_fallback, &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]); serviceResult = response_fallback.responseHeader.serviceResult; UA_RegisterServerResponse_deleteMembers(&response_fallback); } if(serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT, "RegisterServer/RegisterServer2 failed with statuscode %s", UA_StatusCode_name(serviceResult)); } UA_Client_disconnect(client); UA_Client_delete(client); return serviceResult; }
int main(int argc, char *argv[]) { UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout_new()); UA_StatusCode retval = UA_Client_connect(client, ClientNetworkLayerTCP_connect, "opc.tcp://localhost:16664"); if(retval != UA_STATUSCODE_GOOD) { UA_Client_delete(client); return retval; } // Browse some objects printf("Browsing nodes in objects folder:\n"); UA_BrowseRequest bReq; UA_BrowseRequest_init(&bReq); bReq.requestedMaxReferencesPerNode = 0; bReq.nodesToBrowse = UA_BrowseDescription_new(); bReq.nodesToBrowseSize = 1; bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); //browse objects folder bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything UA_BrowseResponse bResp = UA_Client_browse(client, &bReq); printf("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); for (int i = 0; i < bResp.resultsSize; ++i) { for (int j = 0; j < bResp.results[i].referencesSize; ++j) { UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) { printf("%-9d %-16d %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, ref->nodeId.nodeId.identifier.numeric, ref->browseName.name.length, ref->browseName.name.data, ref->displayName.text.length, ref->displayName.text.data); } else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) { printf("%-9d %-16.*s %-16.*s %-16.*s\n", ref->browseName.namespaceIndex, ref->nodeId.nodeId.identifier.string.length, ref->nodeId.nodeId.identifier.string.data, ref->browseName.name.length, ref->browseName.name.data, ref->displayName.text.length, ref->displayName.text.data); } //TODO: distinguish further types } } UA_BrowseRequest_deleteMembers(&bReq); UA_BrowseResponse_deleteMembers(&bResp); UA_Int32 value = 0; // Read node's value printf("\nReading the value of node (1, \"the.answer\"):\n"); UA_ReadRequest rReq; UA_ReadRequest_init(&rReq); rReq.nodesToRead = UA_ReadValueId_new(); rReq.nodesToReadSize = 1; rReq.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; UA_ReadResponse rResp = UA_Client_read(client, &rReq); if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 && rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) && rResp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) { value = *(UA_Int32*)rResp.results[0].value.data; printf("the value is: %i\n", value); } UA_ReadRequest_deleteMembers(&rReq); UA_ReadResponse_deleteMembers(&rResp); value++; // Write node's value printf("\nWriting a value of node (1, \"the.answer\"):\n"); UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = UA_WriteValue_new(); wReq.nodesToWriteSize = 1; wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); /* assume this node exists */ wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE; wReq.nodesToWrite[0].value.hasValue = UA_TRUE; wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32]; wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; //do not free the integer on deletion wReq.nodesToWrite[0].value.value.data = &value; UA_WriteResponse wResp = UA_Client_write(client, &wReq); if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) printf("the new value is: %i\n", value); UA_WriteRequest_deleteMembers(&wReq); UA_WriteResponse_deleteMembers(&wResp); #ifdef ENABLE_ADDNODES /* Create a new object type node */ // New ReferenceType UA_AddNodesResponse *adResp = UA_Client_createReferenceTypeNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 12133), // Assign this NodeId (will fail if client is called multiple times) UA_QUALIFIEDNAME(0, "NewReference"), UA_LOCALIZEDTEXT("en_US", "TheNewReference"), UA_LOCALIZEDTEXT("en_US", "References something that might or might not exist."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_LOCALIZEDTEXT("en_US", "IsNewlyReferencedBy")); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewReference' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); // New ObjectType adResp = UA_Client_createObjectTypeNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 12134), // Assign this NodeId (will fail if client is called multiple times) UA_QUALIFIEDNAME(0, "NewObjectType"), UA_LOCALIZEDTEXT("en_US", "TheNewObjectType"), UA_LOCALIZEDTEXT("en_US", "Put innovative description here."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewObjectType' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } // New Object adResp = UA_Client_createObjectNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_QUALIFIEDNAME(0, "TheNewGreatNodeBrowseName"), UA_LOCALIZEDTEXT("en_US", "TheNewGreatNode"), UA_LOCALIZEDTEXT("de_DE", "Hier koennte Ihre Webung stehen!"), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER)); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewObject' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); // New Integer Variable UA_Variant *theValue = UA_Variant_new(); UA_Int32 *theValueDate = UA_Int32_new(); *theValueDate = 1234; theValue->type = &UA_TYPES[UA_TYPES_INT32]; theValue->data = theValueDate; adResp = UA_Client_createVariableNode(client, UA_EXPANDEDNODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_QUALIFIEDNAME(0, "VariableNode"), UA_LOCALIZEDTEXT("en_US", "TheNewVariableNode"), UA_LOCALIZEDTEXT("en_US", "This integer is just amazing - it has digits and everything."), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), (UA_UInt32) 0, (UA_UInt32) 0, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_INT32), theValue); if (adResp->resultsSize > 0 && adResp->results[0].statusCode == UA_STATUSCODE_GOOD ) { printf("Created 'NewVariable' with numeric NodeID %u\n", adResp->results[0].addedNodeId.identifier.numeric ); } UA_AddNodesResponse_deleteMembers(adResp); free(adResp); free(theValue); /* Done creating a new node*/ #endif UA_Client_disconnect(client); UA_Client_delete(client); return UA_STATUSCODE_GOOD; }
static void setup(void) { if (!(MUTEX_INIT(serverMutex))) { fprintf(stderr, "Server mutex was not created correctly.\n"); exit(1); } running = true; server = UA_Server_new(); UA_ServerConfig *config = UA_Server_getConfig(server); UA_ServerConfig_setDefault(config); #ifdef UA_ENABLE_HISTORIZING gathering = (UA_HistoryDataGathering*)UA_calloc(1, sizeof(UA_HistoryDataGathering)); *gathering = UA_HistoryDataGathering_Default(1); config->historyDatabase = UA_HistoryDatabase_default(*gathering); #endif UA_StatusCode retval = UA_Server_run_startup(server); if(retval != UA_STATUSCODE_GOOD) { fprintf(stderr, "Error while calling Server_run_startup. %s\n", UA_StatusCode_name(retval)); UA_Server_delete(server); exit(1); } THREAD_CREATE(server_thread, serverloop); /* Define the attribute of the uint32 variable node */ UA_VariableAttributes attr = UA_VariableAttributes_default; UA_UInt32 myUint32 = 40; UA_Variant_setScalar(&attr.value, &myUint32, &UA_TYPES[UA_TYPES_UINT32]); attr.description = UA_LOCALIZEDTEXT("en-US","the answer"); attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer"); attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId; attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_HISTORYREAD | UA_ACCESSLEVELMASK_HISTORYWRITE; attr.historizing = true; /* Add the variable node to the information model */ UA_NodeId uint32NodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName uint32Name = UA_QUALIFIEDNAME(1, "the answer"); parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_NodeId_init(&outNodeId); retval = UA_Server_addVariableNode(server, uint32NodeId, parentNodeId, parentReferenceNodeId, uint32Name, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, &outNodeId); if (retval != UA_STATUSCODE_GOOD) { fprintf(stderr, "Error adding variable node. %s\n", UA_StatusCode_name(retval)); UA_Server_delete(server); exit(1); } client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); if (retval != UA_STATUSCODE_GOOD) { fprintf(stderr, "Client can not connect to opc.tcp://localhost:4840. %s\n", UA_StatusCode_name(retval)); UA_Client_delete(client); UA_Server_delete(server); exit(1); } UA_Client_recv = client->connection.recv; client->connection.recv = UA_Client_recvTesting; }
int main(void) { UA_Client *clt; //client UA_StatusCode retval; UA_ReadRequest req; //read request UA_ReadResponse resp; //response /* * Step 1. * create & init the client */ clt = UA_Client_new(UA_ClientConfig_standard); retval = UA_Client_connect(clt, URL); if(retval != UA_STATUSCODE_GOOD){ UA_Client_delete(clt); return retval; } /* * Step 2. * Create read request */ UA_ReadRequest_init(&req); // memset 0 in req req.nodesToRead = UA_Array_new(1, &UA_TYPES[UA_TYPES_READVALUEID]); req.nodesToReadSize = 1; /* * Step 3. * define which node and attribute to be read */ req.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.f****r"); req.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE; /* * Step 4. * call the `UA_Client_Service_read` to read */ UA_ReadResponse_init(&resp); resp = UA_Client_Service_read(clt, req); /* if(resp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && resp.resultsSize > 0 && resp.results[0].hasValue && UA_Variant_isScalar(&resp.results[0].value) && resp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) {*/ if(resp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && resp.resultsSize > 0 && resp.results[0].hasValue && UA_Variant_isScalar(&resp.results[0].value) && resp.results[0].value.type == &UA_TYPES[UA_TYPES_STRING]) { UA_String *str = (UA_String *)resp.results[0].value.data; printf("The string : %s\n", str->data); /* UA_Int32 *val = (UA_Int32 *)resp.results[0].value.data; printf("The value is: %d\n", *val);*/ } /* * Step 5. * free resource */ UA_ReadRequest_deleteMembers(&req); UA_ReadResponse_deleteMembers(&resp); UA_Client_disconnect(clt); UA_Client_delete(clt); return UA_STATUSCODE_GOOD; }