static UA_StatusCode eventSetup(UA_NodeId *eventNodeId) { UA_StatusCode retval; retval = UA_Server_createEvent(server, eventType, eventNodeId); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); // add a severity to the event UA_Variant value; UA_RelativePathElement rpe; UA_RelativePathElement_init(&rpe); rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY); rpe.isInverse = false; rpe.includeSubtypes = false; UA_BrowsePath bp; UA_BrowsePath_init(&bp); bp.startingNode = *eventNodeId; bp.relativePath.elementsSize = 1; bp.relativePath.elements = &rpe; rpe.targetName = UA_QUALIFIEDNAME(0, "Severity"); UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); // number with no special meaning UA_UInt16 eventSeverity = 1000; UA_Variant_setScalar(&value, &eventSeverity, &UA_TYPES[UA_TYPES_UINT16]); UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); UA_BrowsePathResult_deleteMembers(&bpr); //add a message to the event rpe.targetName = UA_QUALIFIEDNAME(0, "Message"); bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); UA_LocalizedText message = UA_LOCALIZEDTEXT("en-US", "Generated Event"); UA_Variant_setScalar(&value, &message, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); UA_BrowsePathResult_deleteMembers(&bpr); return retval; }
static UA_NodeId addPubSubConnection(void){ UA_Variant publisherId; UA_Variant_init(&publisherId); UA_UInt32 publisherIdValue = 13245; UA_Variant_setScalar(&publisherId, &publisherIdValue , &UA_TYPES[UA_TYPES_UINT32]); UA_PubSubConnectionDataType pubSubConnection; UA_PubSubConnectionDataType_init(&pubSubConnection); pubSubConnection.name = UA_STRING("Model Connection 1"); pubSubConnection.enabled = UA_TRUE; pubSubConnection.publisherId = publisherId; pubSubConnection.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); UA_ExtensionObject eo; UA_NetworkAddressUrlDataType networkAddressDataType = {UA_STRING("eth0"), UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_NetworkAddressUrlDataType* identityToken = UA_NetworkAddressUrlDataType_new(); UA_NetworkAddressUrlDataType_init(identityToken); UA_NetworkAddressUrlDataType_copy(&networkAddressDataType, identityToken); eo.encoding = UA_EXTENSIONOBJECT_DECODED; eo.content.decoded.type = &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]; eo.content.decoded.data = identityToken; pubSubConnection.address = eo; pubSubConnection.connectionPropertiesSize = 2; UA_KeyValuePair connectionOptions[2]; memset(connectionOptions, 0, sizeof(UA_KeyValuePair)* 2); connectionOptions[0].key = UA_QUALIFIEDNAME(0, "ttl"); UA_UInt32 ttl = 10; UA_Variant_setScalar(&connectionOptions[0].value, &ttl, &UA_TYPES[UA_TYPES_UINT32]); connectionOptions[1].key = UA_QUALIFIEDNAME(0, "loopback"); UA_Boolean loopback = UA_FALSE; UA_Variant_setScalar(&connectionOptions[1].value, &loopback, &UA_TYPES[UA_TYPES_UINT32]); pubSubConnection.connectionProperties = connectionOptions; UA_Variant inputArguments; UA_Variant_init(&inputArguments); UA_Variant_setScalar(&inputArguments, &pubSubConnection, &UA_TYPES[UA_TYPES_PUBSUBCONNECTIONDATATYPE]); UA_CallMethodRequest callMethodRequest; UA_CallMethodRequest_init(&callMethodRequest); callMethodRequest.inputArgumentsSize = 1; callMethodRequest.inputArguments = &inputArguments; callMethodRequest.objectId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE); callMethodRequest.methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION); UA_NodeId connectionId = UA_NODEID_NULL; 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); if(result.outputArguments->type == &UA_TYPES[UA_TYPES_NODEID]) connectionId = *((UA_NodeId *) result.outputArguments->data); UA_ExtensionObject_deleteMembers(&eo); callMethodRequest.inputArguments = NULL; callMethodRequest.inputArgumentsSize = 0; UA_CallMethodRequest_deleteMembers(&callMethodRequest); UA_CallMethodResult_deleteMembers(&result); return connectionId; }
} END_TEST START_TEST(AddSingleConnectionWithMaximalConfiguration){ UA_NetworkAddressUrlDataType networkAddressUrlData = {UA_STRING("127.0.0.1"), UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant address; UA_Variant_setScalar(&address, &networkAddressUrlData, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_KeyValuePair connectionOptions[3]; connectionOptions[0].key = UA_QUALIFIEDNAME(0, "ttl"); UA_UInt32 ttl = 10; UA_Variant_setScalar(&connectionOptions[0].value, &ttl, &UA_TYPES[UA_TYPES_UINT32]); connectionOptions[1].key = UA_QUALIFIEDNAME(0, "loopback"); UA_Boolean loopback = UA_FALSE; UA_Variant_setScalar(&connectionOptions[1].value, &loopback, &UA_TYPES[UA_TYPES_UINT32]); connectionOptions[2].key = UA_QUALIFIEDNAME(0, "reuse"); UA_Boolean reuse = UA_TRUE; UA_Variant_setScalar(&connectionOptions[2].value, &reuse, &UA_TYPES[UA_TYPES_UINT32]); UA_PubSubConnectionConfig connectionConf; memset(&connectionConf, 0, sizeof(UA_PubSubConnectionConfig)); connectionConf.name = UA_STRING("UADP Connection"); connectionConf.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); connectionConf.enabled = true; connectionConf.publisherId.numeric = 223344; connectionConf.connectionPropertiesSize = 3; connectionConf.connectionProperties = connectionOptions; connectionConf.address = address; UA_NodeId connection; UA_StatusCode retVal = UA_Server_addPubSubConnection(server, &connectionConf, &connection); ck_assert_int_eq(server->pubSubManager.connectionsSize, 1); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); ck_assert(server->pubSubManager.connections[0].channel != NULL); } END_TEST
int main(int argc, char** argv) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_ServerConfig config = UA_ServerConfig_standard; UA_ServerNetworkLayer nl; nl = UA_ServerNetworkLayerUDP(UA_ConnectionConfig_standard, 16664); config.networkLayers = &nl; config.networkLayersSize = 1; UA_Server *server = UA_Server_new(config); // add a variable node to the adresspace UA_VariableAttributes attr; UA_VariableAttributes_init(&attr); UA_Int32 myInteger = 42; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); attr.description = UA_LOCALIZEDTEXT("en_US","the answer"); attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer"); UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, UA_NODEID_NULL, attr, NULL, NULL); UA_StatusCode retval = UA_Server_run(server, &running); UA_Server_delete(server); return (int) retval; }
int main(int argc, char **argv) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_PubSubTransportLayer udpLayer = UA_PubSubTransportLayerUDPMP(); UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(connectionConfig)); connectionConfig.name = UA_STRING("UADP Connection 1"); connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); connectionConfig.enabled = UA_TRUE; UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL , UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_PubSubChannel *psc = udpLayer.createPubSubChannel(&connectionConfig); psc->regist(psc, NULL, NULL); UA_StatusCode retval = UA_STATUSCODE_GOOD; while(running && retval == UA_STATUSCODE_GOOD) retval = subscriberListen(psc); psc->close(psc); return 0; }
} END_TEST START_TEST(AddNodeTwiceGivesError) { /* add a variable node to the address space */ UA_VariableAttributes attr = UA_VariableAttributes_default; UA_Int32 myInteger = 42; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); attr.description = UA_LOCALIZEDTEXT("en-US","the answer"); attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer"); UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_StatusCode res = UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL); ck_assert_int_eq(UA_STATUSCODE_GOOD, res); res = UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL); ck_assert_int_eq(res, UA_STATUSCODE_BADNODEIDEXISTS); } END_TEST
static int run(UA_String *transportProfile, UA_NetworkAddressUrlDataType *networkAddressUrl) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_Server *server = UA_Server_new(); UA_ServerConfig *config = UA_Server_getConfig(server); UA_ServerConfig_setMinimal(config, 4801, NULL); /* Details about the PubSubTransportLayer can be found inside the * tutorial_pubsub_connection */ config->pubsubTransportLayers = (UA_PubSubTransportLayer *) UA_calloc(2, sizeof(UA_PubSubTransportLayer)); if(!config->pubsubTransportLayers) { UA_Server_delete(server); return EXIT_FAILURE; } config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP(); config->pubsubTransportLayersSize++; #ifdef UA_ENABLE_PUBSUB_ETH_UADP config->pubsubTransportLayers[1] = UA_PubSubTransportLayerEthernet(); config->pubsubTransportLayersSize++; #endif UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(connectionConfig)); connectionConfig.name = UA_STRING("UADP Connection 1"); connectionConfig.transportProfileUri = *transportProfile; connectionConfig.enabled = UA_TRUE; UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_NodeId connectionIdent; UA_StatusCode retval = UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent); if(retval == UA_STATUSCODE_GOOD) UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "The PubSub Connection was created successfully!"); /* The following lines register the listening on the configured multicast * address and configure a repeated job, which is used to handle received * messages. */ UA_PubSubConnection *connection = UA_PubSubConnection_findConnectionbyId(server, connectionIdent); if(connection != NULL) { UA_StatusCode rv = connection->channel->regist(connection->channel, NULL, NULL); if (rv == UA_STATUSCODE_GOOD) { UA_UInt64 subscriptionCallbackId; UA_Server_addRepeatedCallback(server, (UA_ServerCallback)subscriptionPollingCallback, connection, 100, &subscriptionCallbackId); } else { UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "register channel failed: %s!", UA_StatusCode_name(rv)); } } retval |= UA_Server_run(server, &running); UA_Server_delete(server); return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;; }
UA_StatusCode __UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId, UA_AttributeId attributeId, const void *in, const UA_DataType *inDataType) { if(!in) return UA_STATUSCODE_BADTYPEMISMATCH; UA_WriteValue wValue; UA_WriteValue_init(&wValue); wValue.nodeId = *nodeId; wValue.attributeId = attributeId; if(attributeId == UA_ATTRIBUTEID_VALUE) wValue.value.value = *(const UA_Variant*)in; else UA_Variant_setScalar(&wValue.value.value, (void*)(uintptr_t)in, inDataType); /* hack. is never written into. */ wValue.value.hasValue = true; UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); wReq.nodesToWrite = &wValue; wReq.nodesToWriteSize = 1; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); UA_StatusCode retval = wResp.responseHeader.serviceResult; UA_WriteResponse_deleteMembers(&wResp); return retval; }
static UA_StatusCode setUInt32(UA_Client *thisClient, UA_NodeId node, UA_UInt32 value) { UA_Variant variant; UA_Variant_setScalar(&variant, &value, &UA_TYPES[UA_TYPES_UINT32]); return UA_Client_writeValueAttribute(thisClient, node, &variant); }
static void variables_variants(void) { /* Set a scalar value */ UA_Variant v; UA_Int32 i = 42; UA_Variant_setScalar(&v, &i, &UA_TYPES[UA_TYPES_INT32]); /* Make a copy */ UA_Variant v2; UA_Variant_copy(&v, &v2); UA_Variant_deleteMembers(&v2); /* Set an array value */ UA_Variant v3; UA_Double d[9] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; UA_Variant_setArrayCopy(&v3, d, 9, &UA_TYPES[UA_TYPES_DOUBLE]); /* Set array dimensions */ v3.arrayDimensions = (UA_UInt32 *)UA_Array_new(2, &UA_TYPES[UA_TYPES_UINT32]); v3.arrayDimensionsSize = 2; v3.arrayDimensions[0] = 3; v3.arrayDimensions[1] = 3; UA_Variant_deleteMembers(&v3); }
static void manuallyDefinePump(UA_Server *server) { UA_NodeId pumpId; /* get the nodeid assigned by the server */ UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Pump (Manual)"); UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Pump (Manual)"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &pumpId); UA_VariableAttributes mnAttr = UA_VariableAttributes_default; UA_String manufacturerName = UA_STRING("Pump King Ltd."); UA_Variant_setScalar(&mnAttr.value, &manufacturerName, &UA_TYPES[UA_TYPES_STRING]); mnAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ManufacturerName"); UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "ManufacturerName"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, NULL); UA_VariableAttributes modelAttr = UA_VariableAttributes_default; UA_String modelName = UA_STRING("Mega Pump 3000"); UA_Variant_setScalar(&modelAttr.value, &modelName, &UA_TYPES[UA_TYPES_STRING]); modelAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ModelName"); UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "ModelName"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, NULL); UA_VariableAttributes statusAttr = UA_VariableAttributes_default; UA_Boolean status = true; UA_Variant_setScalar(&statusAttr.value, &status, &UA_TYPES[UA_TYPES_BOOLEAN]); statusAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Status"); UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Status"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, NULL); UA_VariableAttributes rpmAttr = UA_VariableAttributes_default; UA_Double rpm = 50.0; UA_Variant_setScalar(&rpmAttr.value, &rpm, &UA_TYPES[UA_TYPES_DOUBLE]); rpmAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MotorRPM"); UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "MotorRPMs"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), rpmAttr, NULL, NULL); }
} END_TEST START_TEST(GetMaximalConnectionConfigurationAndCompareValues){ UA_NetworkAddressUrlDataType networkAddressUrlData = {UA_STRING("127.0.0.1"), UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant address; UA_Variant_setScalar(&address, &networkAddressUrlData, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_KeyValuePair connectionOptions[3]; connectionOptions[0].key = UA_QUALIFIEDNAME(0, "ttl"); UA_UInt32 ttl = 10; UA_Variant_setScalar(&connectionOptions[0].value, &ttl, &UA_TYPES[UA_TYPES_UINT32]); connectionOptions[1].key = UA_QUALIFIEDNAME(0, "loopback"); UA_Boolean loopback = UA_FALSE; UA_Variant_setScalar(&connectionOptions[1].value, &loopback, &UA_TYPES[UA_TYPES_UINT32]); connectionOptions[2].key = UA_QUALIFIEDNAME(0, "reuse"); UA_Boolean reuse = UA_TRUE; UA_Variant_setScalar(&connectionOptions[2].value, &reuse, &UA_TYPES[UA_TYPES_UINT32]); UA_PubSubConnectionConfig connectionConf; memset(&connectionConf, 0, sizeof(UA_PubSubConnectionConfig)); connectionConf.name = UA_STRING("UADP Connection"); connectionConf.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); connectionConf.enabled = true; connectionConf.publisherId.numeric = 223344; connectionConf.connectionPropertiesSize = 3; connectionConf.connectionProperties = connectionOptions; connectionConf.address = address; UA_NodeId connection; UA_StatusCode retVal = UA_Server_addPubSubConnection(server, &connectionConf, &connection); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); retVal |= UA_Server_getPubSubConnectionConfig(server, connection, &connectionConfig); ck_assert_int_eq(retVal, UA_STATUSCODE_GOOD); ck_assert(connectionConfig.connectionPropertiesSize == connectionConf.connectionPropertiesSize); ck_assert(UA_String_equal(&connectionConfig.name, &connectionConf.name) == UA_TRUE); ck_assert(UA_String_equal(&connectionConfig.transportProfileUri, &connectionConf.transportProfileUri) == UA_TRUE); UA_NetworkAddressUrlDataType networkAddressUrlDataCopy = *((UA_NetworkAddressUrlDataType *)connectionConfig.address.data); ck_assert(UA_NetworkAddressUrlDataType_calcSizeBinary(&networkAddressUrlDataCopy) == UA_NetworkAddressUrlDataType_calcSizeBinary(&networkAddressUrlData)); for(size_t i = 0; i < connectionConfig.connectionPropertiesSize; i++){ ck_assert(UA_String_equal(&connectionConfig.connectionProperties[i].key.name, &connectionConf.connectionProperties[i].key.name) == UA_TRUE); ck_assert(UA_Variant_calcSizeBinary(&connectionConfig.connectionProperties[i].value) == UA_Variant_calcSizeBinary(&connectionConf.connectionProperties[i].value)); } UA_PubSubConnectionConfig_deleteMembers(&connectionConfig); } END_TEST
} 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); signal(SIGTERM, stopHandler); UA_ServerConfig *config = UA_ServerConfig_new_minimal(4801, NULL); /* Details about the PubSubTransportLayer can be found inside the * tutorial_pubsub_connection */ config->pubsubTransportLayers = (UA_PubSubTransportLayer *) UA_malloc(sizeof(UA_PubSubTransportLayer)); if (!config->pubsubTransportLayers) { UA_ServerConfig_delete(config); return -1; } config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP(); config->pubsubTransportLayersSize++; UA_Server *server = UA_Server_new(config); UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(connectionConfig)); connectionConfig.name = UA_STRING("UDP-UADP Connection 1"); connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); connectionConfig.enabled = UA_TRUE; UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL , UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); UA_NodeId connectionIdent; UA_StatusCode retval = UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent); if(retval == UA_STATUSCODE_GOOD) UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "The PubSub Connection was created successfully!"); /* The following lines register the listening on the configured multicast * address and configure a repeated job, which is used to handle received * messages. */ UA_PubSubConnection *connection = UA_PubSubConnection_findConnectionbyId(server, connectionIdent); if(connection != NULL) { UA_StatusCode rv = connection->channel->regist(connection->channel, NULL); if (rv == UA_STATUSCODE_GOOD) { UA_UInt64 subscriptionCallbackId; UA_Server_addRepeatedCallback(server, (UA_ServerCallback)subscriptionPollingCallback, connection, 100, &subscriptionCallbackId); } else { UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "register channel failed: %s!", UA_StatusCode_name(rv)); } } retval |= UA_Server_run(server, &running); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }
END_TEST START_TEST(Nodes_createCustomObjectType) { // Create a custom object type "CustomDemoType" which has a "CustomStateType" component UA_StatusCode retval = UA_STATUSCODE_GOOD; /* create new object type node which has a subcomponent of the type StateType */ UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default; otAttr.displayName = UA_LOCALIZEDTEXT("", "CustomDemoType"); otAttr.description = UA_LOCALIZEDTEXT("", ""); retval = UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 6010), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, "CustomDemoType"), otAttr, NULL, NULL); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; oAttr.displayName = UA_LOCALIZEDTEXT("", "State"); oAttr.description = UA_LOCALIZEDTEXT("", ""); retval = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 6011), UA_NODEID_NUMERIC(1, 6010), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "State"), UA_NODEID_NUMERIC(1, 6000), oAttr, NULL, NULL); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* modelling rule is mandatory so it will be inherited for the object created from CustomDemoType */ retval = UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 6011), UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); /* assign a default value to the attribute "StateNumber" inside the state attribute (part of the MyDemoType) */ UA_Variant stateNum; UA_Variant_init(&stateNum); UA_Variant_setScalar(&stateNum, &valueToBeInherited, &UA_TYPES[UA_TYPES_UINT32]); UA_NodeId childID; findChildId(UA_NODEID_NUMERIC(1, 6011), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, "CustomStateNumber"), &childID); ck_assert(!UA_NodeId_isNull(&childID)); retval = UA_Server_writeValue(server, childID, stateNum); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); }
} 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(AddConnectionWithUnknownTransportURL){ UA_StatusCode retVal; UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("UADP Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL, UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/unknown-udp-uadp"); UA_NodeId connectionIdent; retVal = UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent); ck_assert_int_eq(server->pubSubManager.connectionsSize, 0); ck_assert_int_ne(retVal, UA_STATUSCODE_GOOD); } END_TEST
static void addVariableFail(UA_Server *server) { /* Prepare the node attributes */ UA_VariableAttributes vAttr = UA_VariableAttributes_default; vAttr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId; vAttr.valueRank = -1; /* a scalar. this is not allowed per the variable type */ vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "2DPoint Variable (fail)"); UA_String s = UA_STRING("2dpoint?"); UA_Variant_setScalar(&vAttr.value, &s, &UA_TYPES[UA_TYPES_STRING]); /* Add the node */ UA_Server_addVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "2DPoint Type (fail)"), pointTypeId, vAttr, NULL, NULL); }
static void setup(void) { server = UA_Server_new(); UA_ServerConfig *config = UA_Server_getConfig(server); UA_ServerConfig_setDefault(config); config->pubsubTransportLayers = (UA_PubSubTransportLayer *) UA_malloc(sizeof(UA_PubSubTransportLayer)); config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP(); config->pubsubTransportLayersSize++; UA_Server_run_startup(server); UA_PubSubConnectionConfig connectionConfig; memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig)); connectionConfig.name = UA_STRING("UADP Connection"); UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL, UA_STRING("opc.udp://224.0.0.22:4840/")}; UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); UA_Server_addPubSubConnection(server, &connectionConfig, &connection1); }
/* Convenience function to be wrapped into inline functions */ UA_StatusCode __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId, const UA_AttributeId attributeId, const UA_DataType *attr_type, const void *attr) { UA_WriteValue wvalue; UA_WriteValue_init(&wvalue); wvalue.nodeId = *nodeId; wvalue.attributeId = attributeId; wvalue.value.hasValue = true; if(attr_type != &UA_TYPES[UA_TYPES_VARIANT]) { /* hacked cast. the target WriteValue is used as const anyway */ UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)attr, attr_type); } else { wvalue.value.value = *(const UA_Variant*)attr; } return UA_Server_write(server, &wvalue); }
int main(int argc, char** argv) { signal(SIGINT, signalHandler); /* catch ctrl-c */ /* Create a server with one network layer listening on port 4840 */ UA_ServerConfig config = UA_ServerConfig_standard; UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 4840); config.networkLayers = &nl; config.networkLayersSize = 1; UA_Server *server = UA_Server_new(config); /* Add a variable node */ UA_VariableAttributes attr; UA_VariableAttributes_init(&attr); attr.displayName = UA_LOCALIZEDTEXT("en_US", "Test Var"); UA_Int32 myInteger = 2572; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); UA_NodeId newNodeId = UA_NODEID_STRING(1, "Test.Var"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_NodeId variableType = UA_NODEID_NULL; /* take the default variable type */ UA_QualifiedName browseName = UA_QUALIFIEDNAME(1, "Test Node"); UA_DataSource dateDataSource = (UA_DataSource) {.handle = &myInteger, .read = onRead, .write = NULL}; UA_Server_addDataSourceVariableNode(server, newNodeId, parentNodeId, parentReferenceNodeId, browseName, UA_NODEID_NULL, attr, dateDataSource, NULL); UA_Job job = {.type = UA_JOBTYPE_METHODCALL, .job.methodCall = {.method = testCallback, .data = NULL} }; UA_Server_addRepeatedJob(server, job, 2000, NULL); // call every 2 sec /* Run the server loop */ UA_StatusCode status = UA_Server_run(server, &running); UA_Server_delete(server); nl.deleteMembers(&nl); return status; }
static UA_StatusCode pumpTypeConstructor(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *typeId, void *typeContext, const UA_NodeId *nodeId, void **nodeContext) { UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "New pump created"); /* Find the NodeId of the status child variable */ UA_RelativePathElement rpe; UA_RelativePathElement_init(&rpe); rpe.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT); rpe.isInverse = false; rpe.includeSubtypes = false; rpe.targetName = UA_QUALIFIEDNAME(1, "Status"); UA_BrowsePath bp; UA_BrowsePath_init(&bp); bp.startingNode = *nodeId; bp.relativePath.elementsSize = 1; bp.relativePath.elements = &rpe; UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) return bpr.statusCode; /* Set the status value */ UA_Boolean status = true; UA_Variant value; UA_Variant_setScalar(&value, &status, &UA_TYPES[UA_TYPES_BOOLEAN]); UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); UA_BrowsePathResult_clear(&bpr); /* At this point we could replace the node context .. */ return UA_STATUSCODE_GOOD; }
int main(int argc, char** argv) { signal(SIGINT, stopHandler); /* catches ctrl-c */ UA_ServerConfig config = UA_ServerConfig_standard; UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664, logger); config.logger = Logger_Stdout; config.networkLayers = &nl; config.networkLayersSize = 1; UA_Server *server = UA_Server_new(config); /* add a variable node to the address space */ UA_VariableAttributes attr; UA_VariableAttributes_init(&attr); UA_Int32 myInteger = 42; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); attr.description = UA_LOCALIZEDTEXT("en_US","the answer"); attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer"); UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, UA_NODEID_NULL, attr, NULL, NULL); UA_ReadRequest request; UA_ReadRequest_init(&request); UA_ReadValueId rvi; rvi.nodeId = myIntegerNodeId; rvi.attributeId = UA_ATTRIBUTEID_VALUE; rvi.indexRange = UA_STRING_NULL; rvi.dataEncoding = UA_QUALIFIEDNAME(0, "DefaultBinary"); request.timestampsToReturn = UA_TIMESTAMPSTORETURN_NEITHER; request.nodesToReadSize = 1; request.nodesToRead = &rvi; UA_StatusCode retval = UA_STATUSCODE_GOOD; UA_ByteString request_msg; retval |= UA_ByteString_allocBuffer(&request_msg, 1000); UA_ByteString response_msg; retval |= UA_ByteString_allocBuffer(&response_msg, 1000); size_t offset = 0; retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_READREQUEST], &request_msg, &offset); clock_t begin, end; begin = clock(); UA_ReadRequest rq; UA_ReadResponse rr; for(int i = 0; i < 900000; i++) { offset = 0; retval |= UA_decodeBinary(&request_msg, &offset, &rq, &UA_TYPES[UA_TYPES_READREQUEST]); UA_ReadResponse_init(&rr); Service_Read(server, &adminSession, &rq, &rr); offset = 0; retval |= UA_encodeBinary(&rr, &UA_TYPES[UA_TYPES_READRESPONSE], &response_msg, &offset); UA_ReadRequest_deleteMembers(&rq); UA_ReadResponse_deleteMembers(&rr); } end = clock(); double time_spent = (double)(end - begin) / CLOCKS_PER_SEC; printf("duration was %f s\n", time_spent); printf("retval is %i\n", retval); UA_ByteString_deleteMembers(&request_msg); UA_ByteString_deleteMembers(&response_msg); retval |= UA_Server_run(server, &running); UA_Server_delete(server); nl.deleteMembers(&nl); return (int)retval; }
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(int argc, char *argv[]) { UA_Client *client = UA_Client_new(UA_ClientConfig_standard, Logger_Stdout); 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_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 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_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_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 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 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 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; }
static void setInformationModel(UA_Server *server) { /* add a static variable node to the server */ UA_VariableAttributes myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("en-US", "the answer"); myVar.displayName = UA_LOCALIZEDTEXT("en-US", "the answer"); myVar.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; myVar.dataType = UA_TYPES[UA_TYPES_INT32].typeId; myVar.valueRank = UA_VALUERANK_SCALAR; UA_Int32 myInteger = 42; UA_Variant_setScalar(&myVar.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, baseDataVariableType, myVar, NULL, NULL); /* add a static variable that is readable but not writable*/ myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("en-US", "the answer - not readable"); myVar.displayName = UA_LOCALIZEDTEXT("en-US", "the answer - not readable"); myVar.accessLevel = UA_ACCESSLEVELMASK_WRITE; myVar.dataType = UA_TYPES[UA_TYPES_INT32].typeId; myVar.valueRank = UA_VALUERANK_SCALAR; UA_Variant_setScalar(&myVar.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myInteger2Name = UA_QUALIFIEDNAME(1, "the answer - not readable"); const UA_NodeId myInteger2NodeId = UA_NODEID_STRING(1, "the.answer.no.read"); UA_Server_addVariableNode(server, myInteger2NodeId, parentNodeId, parentReferenceNodeId, myInteger2Name, baseDataVariableType, myVar, NULL, NULL); /* add a variable that is not readable or writable for the current user */ myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("en-US", "the answer - not current user"); myVar.displayName = UA_LOCALIZEDTEXT("en-US", "the answer - not current user"); myVar.accessLevel = UA_ACCESSLEVELMASK_WRITE; myVar.dataType = UA_TYPES[UA_TYPES_INT32].typeId; myVar.valueRank = UA_VALUERANK_SCALAR; myVar.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; UA_Variant_setScalar(&myVar.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName accessDeniedName = UA_QUALIFIEDNAME(1, "the answer - not current user"); UA_Server_addVariableNode(server, accessDenied, parentNodeId, parentReferenceNodeId, accessDeniedName, baseDataVariableType, myVar, NULL, NULL); /* add a variable with the datetime data source */ UA_DataSource dateDataSource; dateDataSource.read = readTimeData; dateDataSource.write = NULL; UA_VariableAttributes v_attr = UA_VariableAttributes_default; v_attr.description = UA_LOCALIZEDTEXT("en-US", "current time"); v_attr.displayName = UA_LOCALIZEDTEXT("en-US", "current time"); v_attr.accessLevel = UA_ACCESSLEVELMASK_READ; v_attr.dataType = UA_TYPES[UA_TYPES_DATETIME].typeId; v_attr.valueRank = UA_VALUERANK_SCALAR; const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time"); UA_Server_addDataSourceVariableNode(server, UA_NODEID_NUMERIC(1, 2345), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), dateName, baseDataVariableType, v_attr, dateDataSource, NULL, NULL); /* add a bytestring variable with some content */ myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("", ""); myVar.displayName = UA_LOCALIZEDTEXT("", "example bytestring"); myVar.dataType = UA_TYPES[UA_TYPES_BYTESTRING].typeId; myVar.valueRank = UA_VALUERANK_SCALAR; myVar.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; UA_ByteString myByteString = UA_BYTESTRING("test123\0test123"); UA_Variant_setScalar(&myVar.value, &myByteString, &UA_TYPES[UA_TYPES_BYTESTRING]); const UA_QualifiedName byteStringName = UA_QUALIFIEDNAME(1, "example bytestring"); UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "myByteString"), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), byteStringName, baseDataVariableType, myVar, NULL, NULL); /* Add HelloWorld method to the server */ #ifdef UA_ENABLE_METHODCALLS /* Method with IO Arguments */ UA_Argument inputArguments; UA_Argument_init(&inputArguments); inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId; inputArguments.description = UA_LOCALIZEDTEXT("en-US", "Say your name"); inputArguments.name = UA_STRING("Name"); inputArguments.valueRank = UA_VALUERANK_SCALAR; /* scalar argument */ UA_Argument outputArguments; UA_Argument_init(&outputArguments); outputArguments.arrayDimensionsSize = 0; outputArguments.arrayDimensions = NULL; outputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId; outputArguments.description = UA_LOCALIZEDTEXT("en-US", "Receive a greeting"); outputArguments.name = UA_STRING("greeting"); outputArguments.valueRank = UA_VALUERANK_SCALAR; UA_MethodAttributes addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "Hello World"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, 62541), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "hello_world"), addmethodattributes, &helloWorld, /* callback of the method node */ 1, &inputArguments, 1, &outputArguments, NULL, NULL); #endif /* Add folders for demo information model */ #define DEMOID 50000 #define SCALARID 50001 #define ARRAYID 50002 #define MATRIXID 50003 #define DEPTHID 50004 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; object_attr.description = UA_LOCALIZEDTEXT("en-US", "Demo"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Demo"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Scalar"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Scalar"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Array"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Array"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Matrix"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Matrix"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Matrix"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); /* Fill demo nodes for each type*/ UA_UInt32 matrixDims[2] = {3, 3}; UA_UInt32 id = 51000; // running id in namespace 0 for(UA_UInt32 type = 0; type < UA_TYPES_DIAGNOSTICINFO; type++) { if(type == UA_TYPES_VARIANT || type == UA_TYPES_DIAGNOSTICINFO) continue; UA_VariableAttributes attr = UA_VariableAttributes_default; attr.dataType = UA_TYPES[type].typeId; #ifndef UA_ENABLE_TYPENAMES char name[15]; UA_snprintf(name, 15, "%02d", type); attr.displayName = UA_LOCALIZEDTEXT("en-US", name); UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name); #else attr.displayName = UA_LOCALIZEDTEXT_ALLOC("en-US", UA_TYPES[type].typeName); UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME_ALLOC(1, UA_TYPES[type].typeName); #endif attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr.writeMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; attr.userWriteMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; /* add a scalar node for every built-in type */ attr.valueRank = UA_VALUERANK_SCALAR; void *value = UA_new(&UA_TYPES[type]); UA_Variant_setScalar(&attr.value, value, &UA_TYPES[type]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_clear(&attr.value); /* add an array node for every built-in type */ UA_UInt32 arrayDims = 0; attr.valueRank = UA_VALUERANK_ONE_DIMENSION; attr.arrayDimensions = &arrayDims; attr.arrayDimensionsSize = 1; UA_Variant_setArray(&attr.value, UA_Array_new(10, &UA_TYPES[type]), 10, &UA_TYPES[type]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_clear(&attr.value); /* add an matrix node for every built-in type */ attr.valueRank = UA_VALUERANK_TWO_DIMENSIONS; attr.arrayDimensions = matrixDims; attr.arrayDimensionsSize = 2; void *myMultiArray = UA_Array_new(9, &UA_TYPES[type]); attr.value.arrayDimensions = (UA_UInt32 *)UA_Array_new(2, &UA_TYPES[UA_TYPES_INT32]); attr.value.arrayDimensions[0] = 3; attr.value.arrayDimensions[1] = 3; attr.value.arrayDimensionsSize = 2; attr.value.arrayLength = 9; attr.value.data = myMultiArray; attr.value.type = &UA_TYPES[type]; UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_clear(&attr.value); #ifdef UA_ENABLE_TYPENAMES UA_LocalizedText_clear(&attr.displayName); UA_QualifiedName_clear(&qualifiedName); #endif } /* Add Integer and UInteger variables */ UA_VariableAttributes iattr = UA_VariableAttributes_default; iattr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_INTEGER); iattr.displayName = UA_LOCALIZEDTEXT("en-US", "Integer"); iattr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; iattr.writeMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; iattr.userWriteMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; iattr.valueRank = UA_VALUERANK_SCALAR; UA_QualifiedName iQualifiedName = UA_QUALIFIEDNAME(1, "integer"); UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "integer"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), iQualifiedName, baseDataVariableType, iattr, NULL, NULL); iattr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_UINTEGER); iattr.displayName = UA_LOCALIZEDTEXT("en-US", "UInteger"); UA_QualifiedName uQualifiedName = UA_QUALIFIEDNAME(1, "uinteger"); UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "uinteger"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), uQualifiedName, baseDataVariableType, iattr, NULL, NULL); UA_Variant_clear(&iattr.value); /* Hierarchy of depth 10 for CTT testing with forward and inverse references */ /* Enter node "depth 9" in CTT configuration - Project->Settings->Server Test->NodeIds->Paths->Starting Node 1 */ object_attr.description = UA_LOCALIZEDTEXT("en-US", "DepthDemo"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "DepthDemo"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, DEPTHID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "DepthDemo"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); id = DEPTHID; // running id in namespace 0 - Start with Matrix NODE for(UA_UInt32 i = 1; i <= 20; i++) { char name[15]; UA_snprintf(name, 15, "depth%i", i); object_attr.description = UA_LOCALIZEDTEXT("en-US", name); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", name); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, id + i), UA_NODEID_NUMERIC(1, i == 1 ? DEPTHID : id + i - 1), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, name), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); } /* Add the variable to some more places to get a node with three inverse references for the CTT */ UA_ExpandedNodeId answer_nodeid = UA_EXPANDEDNODEID_STRING(1, "the.answer"); UA_Server_addReference(server, UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), answer_nodeid, true); UA_Server_addReference(server, UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), answer_nodeid, true); /* Example for manually setting an attribute within the server */ UA_LocalizedText objectsName = UA_LOCALIZEDTEXT("en-US", "Objects"); UA_Server_writeDisplayName(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), objectsName); #define NOARGID 60000 #define INARGID 60001 #define OUTARGID 60002 #define INOUTARGID 60003 #ifdef UA_ENABLE_METHODCALLS /* adding some more method nodes to pass CTT */ /* Method without arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "noarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, NOARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "noarg"), addmethodattributes, &noargMethod, /* callback of the method node */ 0, NULL, 0, NULL, NULL, NULL); /* Method with in arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "inarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Argument_init(&inputArguments); inputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId; inputArguments.description = UA_LOCALIZEDTEXT("en-US", "Input"); inputArguments.name = UA_STRING("Input"); inputArguments.valueRank = UA_VALUERANK_SCALAR; //uaexpert will crash if set to 0 ;) UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, INARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "noarg"), addmethodattributes, &noargMethod, /* callback of the method node */ 1, &inputArguments, 0, NULL, NULL, NULL); /* Method with out arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "outarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Argument_init(&outputArguments); outputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId; outputArguments.description = UA_LOCALIZEDTEXT("en-US", "Output"); outputArguments.name = UA_STRING("Output"); outputArguments.valueRank = UA_VALUERANK_SCALAR; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, OUTARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "outarg"), addmethodattributes, &outargMethod, /* callback of the method node */ 0, NULL, 1, &outputArguments, NULL, NULL); /* Method with inout arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "inoutarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, INOUTARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "inoutarg"), addmethodattributes, &outargMethod, /* callback of the method node */ 1, &inputArguments, 1, &outputArguments, NULL, NULL); #endif }
} 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) { signal(SIGINT, stopHandler); /* catches ctrl-c */ signal(SIGTERM, stopHandler); #ifdef UA_ENABLE_ENCRYPTION if(argc < 3) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Missing arguments for encryption support. " "Arguments are <server-certificate.der> " "<private-key.der> [<trustlist1.crl>, ...]"); return 1; } /* Load certificate and private key */ UA_ByteString certificate = loadFile(argv[1]); UA_ByteString privateKey = loadFile(argv[2]); /* Load the trustlist */ size_t trustListSize = 0; if(argc > 3) trustListSize = (size_t)argc-3; UA_STACKARRAY(UA_ByteString, trustList, trustListSize); for(size_t i = 0; i < trustListSize; i++) trustList[i] = loadFile(argv[i+3]); /* Loading of a revocation list currently unsupported */ UA_ByteString *revocationList = NULL; size_t revocationListSize = 0; UA_ServerConfig *config = UA_ServerConfig_new_allSecurityPolicies(4840, &certificate, &privateKey, trustList, trustListSize, revocationList, revocationListSize); UA_ByteString_deleteMembers(&certificate); UA_ByteString_deleteMembers(&privateKey); for(size_t i = 0; i < trustListSize; i++) UA_ByteString_deleteMembers(&trustList[i]); if(!config) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Could not create the server config"); return 1; } #else if(argc < 2) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Missing argument for the server certificate"); return 1; } UA_ByteString certificate = loadFile(argv[1]); UA_ServerConfig *config = UA_ServerConfig_new_minimal(4840, &certificate); UA_ByteString_deleteMembers(&certificate); #endif /* uncomment next line to add a custom hostname */ // UA_ServerConfig_set_customHostname(config, UA_STRING("custom")); UA_Server *server = UA_Server_new(config); if(server == NULL) return 1; /* add a static variable node to the server */ UA_VariableAttributes myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("en-US", "the answer"); myVar.displayName = UA_LOCALIZEDTEXT("en-US", "the answer"); myVar.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; myVar.dataType = UA_TYPES[UA_TYPES_INT32].typeId; myVar.valueRank = -1; UA_Int32 myInteger = 42; UA_Variant_setScalarCopy(&myVar.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId, parentReferenceNodeId, myIntegerName, baseDataVariableType, myVar, NULL, NULL); UA_Variant_deleteMembers(&myVar.value); /* add a static variable that is readable but not writable*/ myVar = UA_VariableAttributes_default; myVar.description = UA_LOCALIZEDTEXT("en-US", "the answer - not readable"); myVar.displayName = UA_LOCALIZEDTEXT("en-US", "the answer - not readable"); myVar.accessLevel = UA_ACCESSLEVELMASK_WRITE; myVar.dataType = UA_TYPES[UA_TYPES_INT32].typeId; myVar.valueRank = -1; UA_Variant_setScalarCopy(&myVar.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myInteger2Name = UA_QUALIFIEDNAME(1, "the answer - not readable"); const UA_NodeId myInteger2NodeId = UA_NODEID_STRING(1, "the.answer.no.read"); UA_Server_addVariableNode(server, myInteger2NodeId, parentNodeId, parentReferenceNodeId, myInteger2Name, baseDataVariableType, myVar, NULL, NULL); UA_Variant_deleteMembers(&myVar.value); /* add a variable with the datetime data source */ UA_DataSource dateDataSource; dateDataSource.read = readTimeData; dateDataSource.write = NULL; UA_VariableAttributes v_attr = UA_VariableAttributes_default; v_attr.description = UA_LOCALIZEDTEXT("en-US", "current time"); v_attr.displayName = UA_LOCALIZEDTEXT("en-US", "current time"); v_attr.accessLevel = UA_ACCESSLEVELMASK_READ; v_attr.dataType = UA_TYPES[UA_TYPES_DATETIME].typeId; v_attr.valueRank = -1; const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time"); UA_Server_addDataSourceVariableNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), dateName, baseDataVariableType, v_attr, dateDataSource, NULL, NULL); /* Add HelloWorld method to the server */ #ifdef UA_ENABLE_METHODCALLS /* Method with IO Arguments */ UA_Argument inputArguments; UA_Argument_init(&inputArguments); inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId; inputArguments.description = UA_LOCALIZEDTEXT("en-US", "Say your name"); inputArguments.name = UA_STRING("Name"); inputArguments.valueRank = -1; /* scalar argument */ UA_Argument outputArguments; UA_Argument_init(&outputArguments); outputArguments.arrayDimensionsSize = 0; outputArguments.arrayDimensions = NULL; outputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId; outputArguments.description = UA_LOCALIZEDTEXT("en-US", "Receive a greeting"); outputArguments.name = UA_STRING("greeting"); outputArguments.valueRank = -1; UA_MethodAttributes addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "Hello World"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, 62541), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "hello_world"), addmethodattributes, &helloWorld, /* callback of the method node */ 1, &inputArguments, 1, &outputArguments, NULL, NULL); #endif /* Add folders for demo information model */ #define DEMOID 50000 #define SCALARID 50001 #define ARRAYID 50002 #define MATRIXID 50003 #define DEPTHID 50004 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; object_attr.description = UA_LOCALIZEDTEXT("en-US", "Demo"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Demo"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Scalar"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Scalar"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Array"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Array"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); object_attr.description = UA_LOCALIZEDTEXT("en-US", "Matrix"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Matrix"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "Matrix"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); /* Fill demo nodes for each type*/ UA_UInt32 id = 51000; // running id in namespace 0 for(UA_UInt32 type = 0; type < UA_TYPES_DIAGNOSTICINFO; type++) { if(type == UA_TYPES_VARIANT || type == UA_TYPES_DIAGNOSTICINFO) continue; UA_VariableAttributes attr = UA_VariableAttributes_default; attr.valueRank = -2; attr.dataType = UA_TYPES[type].typeId; #ifndef UA_ENABLE_TYPENAMES char name[15]; #if defined(_WIN32) && !defined(__MINGW32__) sprintf_s(name, 15, "%02d", type); #else sprintf(name, "%02d", type); #endif attr.displayName = UA_LOCALIZEDTEXT("en-US", name); UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name); #else attr.displayName = UA_LOCALIZEDTEXT_ALLOC("en-US", UA_TYPES[type].typeName); UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME_ALLOC(1, UA_TYPES[type].typeName); #endif attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr.writeMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; attr.userWriteMask = UA_WRITEMASK_DISPLAYNAME | UA_WRITEMASK_DESCRIPTION; /* add a scalar node for every built-in type */ void *value = UA_new(&UA_TYPES[type]); UA_Variant_setScalar(&attr.value, value, &UA_TYPES[type]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_deleteMembers(&attr.value); /* add an array node for every built-in type */ UA_Variant_setArray(&attr.value, UA_Array_new(10, &UA_TYPES[type]), 10, &UA_TYPES[type]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_deleteMembers(&attr.value); /* add an matrix node for every built-in type */ void *myMultiArray = UA_Array_new(9, &UA_TYPES[type]); attr.value.arrayDimensions = (UA_UInt32 *)UA_Array_new(2, &UA_TYPES[UA_TYPES_INT32]); attr.value.arrayDimensions[0] = 3; attr.value.arrayDimensions[1] = 3; attr.value.arrayDimensionsSize = 2; attr.value.arrayLength = 9; attr.value.data = myMultiArray; attr.value.type = &UA_TYPES[type]; UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, ++id), UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName, baseDataVariableType, attr, NULL, NULL); UA_Variant_deleteMembers(&attr.value); #ifdef UA_ENABLE_TYPENAMES UA_LocalizedText_deleteMembers(&attr.displayName); UA_QualifiedName_deleteMembers(&qualifiedName); #endif } /* Hierarchy of depth 10 for CTT testing with forward and inverse references */ /* Enter node "depth 9" in CTT configuration - Project->Settings->Server Test->NodeIds->Paths->Starting Node 1 */ object_attr.description = UA_LOCALIZEDTEXT("en-US", "DepthDemo"); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", "DepthDemo"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, DEPTHID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "DepthDemo"), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); id = DEPTHID; // running id in namespace 0 - Start with Matrix NODE for(UA_UInt32 i = 1; i <= 20; i++) { char name[15]; #if defined(_WIN32) && !defined(__MINGW32__) sprintf_s(name, 15, "depth%i", i); #else sprintf(name, "depth%i", i); #endif object_attr.description = UA_LOCALIZEDTEXT("en-US", name); object_attr.displayName = UA_LOCALIZEDTEXT("en-US", name); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, id + i), UA_NODEID_NUMERIC(1, i == 1 ? DEPTHID : id + i - 1), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, name), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), object_attr, NULL, NULL); } /* Add the variable to some more places to get a node with three inverse references for the CTT */ UA_ExpandedNodeId answer_nodeid = UA_EXPANDEDNODEID_STRING(1, "the.answer"); UA_Server_addReference(server, UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), answer_nodeid, true); UA_Server_addReference(server, UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), answer_nodeid, true); /* Example for manually setting an attribute within the server */ UA_LocalizedText objectsName = UA_LOCALIZEDTEXT("en-US", "Objects"); UA_Server_writeDisplayName(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), objectsName); #define NOARGID 60000 #define INARGID 60001 #define OUTARGID 60002 #define INOUTARGID 60003 #ifdef UA_ENABLE_METHODCALLS /* adding some more method nodes to pass CTT */ /* Method without arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "noarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, NOARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "noarg"), addmethodattributes, &noargMethod, /* callback of the method node */ 0, NULL, 0, NULL, NULL, NULL); /* Method with in arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "inarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Argument_init(&inputArguments); inputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId; inputArguments.description = UA_LOCALIZEDTEXT("en-US", "Input"); inputArguments.name = UA_STRING("Input"); inputArguments.valueRank = -1; //uaexpert will crash if set to 0 ;) UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, INARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "noarg"), addmethodattributes, &noargMethod, /* callback of the method node */ 1, &inputArguments, 0, NULL, NULL, NULL); /* Method with out arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "outarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Argument_init(&outputArguments); outputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId; outputArguments.description = UA_LOCALIZEDTEXT("en-US", "Output"); outputArguments.name = UA_STRING("Output"); outputArguments.valueRank = -1; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, OUTARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "outarg"), addmethodattributes, &outargMethod, /* callback of the method node */ 0, NULL, 1, &outputArguments, NULL, NULL); /* Method with inout arguments */ addmethodattributes = UA_MethodAttributes_default; addmethodattributes.displayName = UA_LOCALIZEDTEXT("en-US", "inoutarg"); addmethodattributes.executable = true; addmethodattributes.userExecutable = true; UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, INOUTARGID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "inoutarg"), addmethodattributes, &outargMethod, /* callback of the method node */ 1, &inputArguments, 1, &outputArguments, NULL, NULL); #endif /* run server */ UA_StatusCode retval = UA_Server_run(server, &running); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }
int main(void) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_ServerConfig *config = UA_ServerConfig_new_default(); UA_Server *server = UA_Server_new(config); /* Create a rudimentary objectType * * Type: * + MamalType * v- Class = "mamalia" * v- Species * o- Abilities * v- MakeSound * v- Breathe = True * + DogType * v- Species = "Canis" * v- Name * o- Abilities * v- MakeSound = "Wuff" * v- FetchNewPaper */ UA_StatusCode retval; UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default; otAttr.description = UA_LOCALIZEDTEXT("en-US", "A mamal"); otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MamalType"); UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 10000), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, "MamalType"), otAttr, NULL, NULL); UA_VariableAttributes vAttr = UA_VariableAttributes_default; vAttr.description = UA_LOCALIZEDTEXT("en-US", "This mamals class"); vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Class"); UA_String classVar = UA_STRING("mamalia"); UA_Variant_setScalar(&vAttr.value, &classVar, &UA_TYPES[UA_TYPES_STRING]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10001), UA_NODEID_NUMERIC(1, 10000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, "Class"), UA_NODEID_NULL, vAttr, NULL, NULL); vAttr = UA_VariableAttributes_default; vAttr.description = UA_LOCALIZEDTEXT("en-US", "This mamals species"); vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Species"); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10002), UA_NODEID_NUMERIC(1, 10000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NULL, vAttr, NULL, NULL); otAttr = UA_ObjectTypeAttributes_default; otAttr.description = UA_LOCALIZEDTEXT("en-US", "A dog, subtype of mamal"); otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "DogType"); UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 20000), UA_NODEID_NUMERIC(1, 10000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, "DogType"), otAttr, NULL, NULL); vAttr = UA_VariableAttributes_default; vAttr.description = UA_LOCALIZEDTEXT("en-US", "This dogs species"); vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Species"); UA_String defaultSpecies = UA_STRING("Canis"); UA_Variant_setScalar(&vAttr.value, &defaultSpecies, &UA_TYPES[UA_TYPES_STRING]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 20001), UA_NODEID_NUMERIC(1, 20000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NULL, vAttr, NULL, NULL); vAttr = UA_VariableAttributes_default; vAttr.description = UA_LOCALIZEDTEXT("en-US", "This dogs name"); vAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Name"); UA_String defaultName = UA_STRING("unnamed dog"); UA_Variant_setScalar(&vAttr.value, &defaultName, &UA_TYPES[UA_TYPES_STRING]); UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 20002), UA_NODEID_NUMERIC(1, 20000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), UA_QUALIFIEDNAME(1, "Name"), UA_NODEID_NULL, vAttr, NULL, NULL); /* Instatiate a dog named bello: * (O) Objects * + O Bello <DogType> * + Age * + Name */ UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; oAttr.description = UA_LOCALIZEDTEXT("en-US", "A dog named Bello"); oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Bello"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Bello"), UA_NODEID_NUMERIC(1, 20000), oAttr, NULL, NULL); oAttr = UA_ObjectAttributes_default; oAttr.description = UA_LOCALIZEDTEXT("en-US", "Another dog"); oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Dog2"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Dog2"), UA_NODEID_NUMERIC(1, 20000), oAttr, NULL, NULL); oAttr = UA_ObjectAttributes_default; oAttr.description = UA_LOCALIZEDTEXT("en-US", "A mamal"); oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Mamal1"); UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_QUALIFIEDNAME(1, "Mamal1"), UA_NODEID_NUMERIC(1, 10000), oAttr, NULL, NULL); /* Run the server */ retval = UA_Server_run(server, &running); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }