mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
Merge branch 'master' of https://github.com/acplt/open62541
This commit is contained in:
commit
1adbb44483
@ -174,6 +174,12 @@ if(ENABLE_EXTERNAL_NAMESPACES)
|
||||
add_definitions(-DUA_EXTERNAL_NAMESPACES)
|
||||
endif()
|
||||
|
||||
## enable dynamic nodeset
|
||||
option(ENABLE_ADDNODES "Enable dynamic addition of nodes" ON)
|
||||
if(ENABLE_ADDNODES)
|
||||
add_definitions(-DENABLE_ADDNODES )
|
||||
endif()
|
||||
|
||||
## set the precompiler flags
|
||||
configure_file("include/ua_config.h.in" "${PROJECT_BINARY_DIR}/src_generated/ua_config.h")
|
||||
|
||||
@ -210,8 +216,8 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.c
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${PROJECT_BINARY_DIR}/src_generated/ua_config.h ${PROJECT_SOURCE_DIR}/src/server/ua_nodestore_hash.inc ${lib_sources})
|
||||
|
||||
if(ENABLE_AMALGAMATION)
|
||||
add_custom_target(amalgamation ALL DEPENDS ${PROJECT_BINARY_DIR}/open62541.h)
|
||||
add_library(open62541-object OBJECT ${PROJECT_BINARY_DIR}/open62541.c)
|
||||
add_custom_target(amalgamation ALL DEPENDS ${PROJECT_BINARY_DIR}/open62541.h ${PROJECT_BINARY_DIR}/open62541.c)
|
||||
add_library(open62541-object OBJECT ${PROJECT_BINARY_DIR}/open62541.c ${PROJECT_BINARY_DIR}/open62541.h)
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
else()
|
||||
add_definitions(-DNOT_AMALGATED)
|
||||
@ -252,7 +258,10 @@ if(BUILD_EXAMPLESERVER)
|
||||
add_executable(server_static examples/server.c ${server_source})
|
||||
add_executable(server_simple examples/server_simple.c ${server_source})
|
||||
add_executable(server examples/server.c)
|
||||
target_link_libraries(server open62541)
|
||||
if(ENABLE_AMALGAMATION)
|
||||
ADD_DEPENDENCIES(server amalgamation)
|
||||
endif()
|
||||
target_link_libraries(server open62541)
|
||||
if(WIN32)
|
||||
target_link_libraries(server_static ws2_32)
|
||||
target_link_libraries(server_simple ws2_32)
|
||||
@ -288,7 +297,10 @@ if(BUILD_EXAMPLECLIENT)
|
||||
add_definitions(-DBENCHMARK)
|
||||
set(client_source $<TARGET_OBJECTS:open62541-object>)
|
||||
add_executable(client_static examples/client.c ${client_source})
|
||||
add_executable(client examples/client.c)
|
||||
add_executable(client examples/client.c)
|
||||
if(ENABLE_AMALGAMATION)
|
||||
ADD_DEPENDENCIES(client amalgamation)
|
||||
endif()
|
||||
target_link_libraries(client open62541)
|
||||
if(WIN32)
|
||||
target_link_libraries(client_static ws2_32)
|
||||
|
@ -4,8 +4,11 @@
|
||||
#include "ua_nodeids.h"
|
||||
#include "networklayer_tcp.h"
|
||||
#include "logger_stdout.h"
|
||||
#include "ua_types_encoding_binary.h"
|
||||
#else
|
||||
#include "open62541.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@ -86,14 +89,90 @@ int main(int argc, char *argv[]) {
|
||||
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;
|
||||
|
@ -259,6 +259,7 @@ int main(int argc, char** argv) {
|
||||
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
||||
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
|
||||
|
||||
#ifndef _WIN32
|
||||
//cpu temperature monitoring for linux machines
|
||||
if((temperatureFile = fopen("/sys/class/thermal/thermal_zone0/temp", "r"))){
|
||||
// add node with the data source
|
||||
@ -300,6 +301,7 @@ int main(int argc, char** argv) {
|
||||
UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "[Raspberry Pi] LED file exist, but I have no access (try to run server with sudo)");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// add a static variable node to the adresspace
|
||||
UA_Variant *myIntegerVariant = UA_Variant_new();
|
||||
|
@ -57,7 +57,27 @@ UA_AddReferencesResponse UA_EXPORT
|
||||
UA_DeleteNodesResponse UA_EXPORT UA_Client_deleteNodes(UA_Client *client, UA_DeleteNodesRequest *request);
|
||||
UA_DeleteReferencesResponse UA_EXPORT
|
||||
UA_Client_deleteReferences(UA_Client *client, UA_DeleteReferencesRequest *request);
|
||||
|
||||
|
||||
|
||||
/* Client-Side Macro/Procy functions */
|
||||
UA_AddNodesResponse UA_EXPORT *UA_Client_createObjectNode( UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition);
|
||||
|
||||
UA_AddNodesResponse UA_EXPORT *UA_Client_createVariableNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
|
||||
UA_NodeId dataType, UA_Variant *value );
|
||||
|
||||
UA_AddNodesResponse UA_EXPORT *UA_Client_createReferenceTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
|
||||
UA_LocalizedText inverseName );
|
||||
|
||||
UA_AddNodesResponse UA_EXPORT *UA_Client_createObjectTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -578,3 +578,173 @@ UA_DeleteReferencesResponse UA_Client_deleteReferences(UA_Client *client, UA_Del
|
||||
&response, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**********************************/
|
||||
/* User-Facing Macros-Function */
|
||||
/**********************************/
|
||||
#define ADDNODES_COPYDEFAULTATTRIBUTES(REQUEST,ATTRIBUTES) do { \
|
||||
ATTRIBUTES.specifiedAttributes = 0; \
|
||||
if(! UA_LocalizedText_copy(&description, &(ATTRIBUTES.description))) \
|
||||
ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_DESCRIPTION; \
|
||||
if(! UA_LocalizedText_copy(&displayName, &(ATTRIBUTES.displayName))) \
|
||||
ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_DISPLAYNAME; \
|
||||
ATTRIBUTES.userWriteMask = userWriteMask; \
|
||||
ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_USERWRITEMASK; \
|
||||
ATTRIBUTES.writeMask = writeMask; \
|
||||
ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_WRITEMASK; \
|
||||
UA_QualifiedName_copy(&browseName, &(REQUEST.nodesToAdd[0].browseName)); \
|
||||
UA_ExpandedNodeId_copy(&parentNodeId, &(REQUEST.nodesToAdd[0].parentNodeId)); \
|
||||
UA_NodeId_copy(&referenceTypeId, &(REQUEST.nodesToAdd[0].referenceTypeId)); \
|
||||
UA_ExpandedNodeId_copy(&typeDefinition, &(REQUEST.nodesToAdd[0].typeDefinition)); \
|
||||
UA_ExpandedNodeId_copy(&reqId, &(REQUEST.nodesToAdd[0].requestedNewNodeId )); \
|
||||
REQUEST.nodesToAddSize = 1; \
|
||||
} while(0)
|
||||
|
||||
#define ADDNODES_PACK_AND_SEND(PREQUEST,PATTRIBUTES,PNODETYPE) do { \
|
||||
PREQUEST.nodesToAdd[0].nodeAttributes.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING; \
|
||||
PREQUEST.nodesToAdd[0].nodeAttributes.typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_##PNODETYPE##ATTRIBUTES + UA_ENCODINGOFFSET_BINARY); \
|
||||
size_t encOffset = 0; \
|
||||
UA_ByteString_newMembers(&PREQUEST.nodesToAdd[0].nodeAttributes.body, client->connection.remoteConf.maxMessageSize); \
|
||||
UA_encodeBinary(&PATTRIBUTES,&UA_TYPES[UA_TYPES_##PNODETYPE##ATTRIBUTES], &(PREQUEST.nodesToAdd[0].nodeAttributes.body), &encOffset); \
|
||||
PREQUEST.nodesToAdd[0].nodeAttributes.body.length = encOffset; \
|
||||
*(adRes) = UA_Client_addNodes(client, &PREQUEST); \
|
||||
UA_AddNodesRequest_deleteMembers(&PREQUEST); \
|
||||
} while(0)
|
||||
|
||||
/* NodeManagement */
|
||||
UA_AddNodesResponse *UA_Client_createObjectNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition ) {
|
||||
UA_AddNodesRequest adReq;
|
||||
UA_AddNodesRequest_init(&adReq);
|
||||
|
||||
UA_AddNodesResponse *adRes;
|
||||
adRes = UA_AddNodesResponse_new();
|
||||
UA_AddNodesResponse_init(adRes);
|
||||
|
||||
UA_ObjectAttributes vAtt;
|
||||
UA_ObjectAttributes_init(&vAtt);
|
||||
adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
|
||||
UA_AddNodesItem_init(adReq.nodesToAdd);
|
||||
|
||||
// Default node properties and attributes
|
||||
ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
|
||||
|
||||
// Specific to objects
|
||||
adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_OBJECT;
|
||||
vAtt.eventNotifier = 0;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_EVENTNOTIFIER;
|
||||
|
||||
ADDNODES_PACK_AND_SEND(adReq,vAtt,OBJECT);
|
||||
|
||||
return adRes;
|
||||
}
|
||||
|
||||
UA_AddNodesResponse *UA_Client_createVariableNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
|
||||
UA_NodeId dataType, UA_Variant *value) {
|
||||
UA_AddNodesRequest adReq;
|
||||
UA_AddNodesRequest_init(&adReq);
|
||||
|
||||
UA_AddNodesResponse *adRes;
|
||||
adRes = UA_AddNodesResponse_new();
|
||||
UA_AddNodesResponse_init(adRes);
|
||||
|
||||
UA_VariableAttributes vAtt;
|
||||
UA_VariableAttributes_init(&vAtt);
|
||||
adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
|
||||
UA_AddNodesItem_init(adReq.nodesToAdd);
|
||||
|
||||
// Default node properties and attributes
|
||||
ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
|
||||
|
||||
// Specific to variables
|
||||
adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_VARIABLE;
|
||||
vAtt.accessLevel = 0;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ACCESSLEVEL;
|
||||
vAtt.userAccessLevel = 0;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_USERACCESSLEVEL;
|
||||
vAtt.minimumSamplingInterval = 100;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL;
|
||||
vAtt.historizing = UA_FALSE;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_HISTORIZING;
|
||||
|
||||
if (value != NULL) {
|
||||
UA_Variant_copy(value, &(vAtt.value));
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_VALUE;
|
||||
vAtt.valueRank = -2;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_VALUERANK;
|
||||
// These are defined by the variant
|
||||
//vAtt.arrayDimensionsSize = value->arrayDimensionsSize;
|
||||
//vAtt.arrayDimensions = NULL;
|
||||
}
|
||||
UA_NodeId_copy(&dataType, &(vAtt.dataType));
|
||||
|
||||
ADDNODES_PACK_AND_SEND(adReq,vAtt,VARIABLE);
|
||||
|
||||
return adRes;
|
||||
}
|
||||
|
||||
UA_AddNodesResponse *UA_Client_createReferenceTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
|
||||
UA_LocalizedText inverseName ) {
|
||||
UA_AddNodesRequest adReq;
|
||||
UA_AddNodesRequest_init(&adReq);
|
||||
|
||||
UA_AddNodesResponse *adRes;
|
||||
adRes = UA_AddNodesResponse_new();
|
||||
UA_AddNodesResponse_init(adRes);
|
||||
|
||||
UA_ReferenceTypeAttributes vAtt;
|
||||
UA_ReferenceTypeAttributes_init(&vAtt);
|
||||
adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
|
||||
UA_AddNodesItem_init(adReq.nodesToAdd);
|
||||
|
||||
// Default node properties and attributes
|
||||
ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
|
||||
|
||||
// Specific to referencetypes
|
||||
adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_REFERENCETYPE;
|
||||
UA_LocalizedText_copy(&inverseName, &(vAtt.inverseName));
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_INVERSENAME;
|
||||
vAtt.symmetric = UA_FALSE;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_SYMMETRIC;
|
||||
vAtt.isAbstract = UA_FALSE;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ISABSTRACT;
|
||||
|
||||
|
||||
ADDNODES_PACK_AND_SEND(adReq,vAtt,REFERENCETYPE);
|
||||
|
||||
return adRes;
|
||||
}
|
||||
|
||||
UA_AddNodesResponse *UA_Client_createObjectTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
|
||||
UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
|
||||
UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition) {
|
||||
UA_AddNodesRequest adReq;
|
||||
UA_AddNodesRequest_init(&adReq);
|
||||
|
||||
UA_AddNodesResponse *adRes;
|
||||
adRes = UA_AddNodesResponse_new();
|
||||
UA_AddNodesResponse_init(adRes);
|
||||
|
||||
UA_ObjectTypeAttributes vAtt;
|
||||
UA_ObjectTypeAttributes_init(&vAtt);
|
||||
adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
|
||||
UA_AddNodesItem_init(adReq.nodesToAdd);
|
||||
|
||||
// Default node properties and attributes
|
||||
ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
|
||||
|
||||
// Specific to referencetypes
|
||||
adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_OBJECTTYPE;
|
||||
vAtt.isAbstract = UA_FALSE;
|
||||
vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ISABSTRACT;
|
||||
|
||||
|
||||
ADDNODES_PACK_AND_SEND(adReq,vAtt,OBJECTTYPE);
|
||||
|
||||
return adRes;
|
||||
}
|
||||
|
@ -245,16 +245,23 @@ UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node, const UA_Node
|
||||
if(expand(ns) != UA_STATUSCODE_GOOD)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
// get a free slot
|
||||
struct nodeEntry **slot;
|
||||
if(UA_NodeId_isNull(&node->nodeId)) {
|
||||
//FIXME: a bit dirty workaround of preserving namespace
|
||||
//namespace index is assumed to be valid
|
||||
UA_NodeId tempNodeid;
|
||||
UA_NodeId_copy(&node->nodeId, &tempNodeid);
|
||||
tempNodeid.namespaceIndex = 0;
|
||||
if(UA_NodeId_isNull(&tempNodeid)) {
|
||||
// find a unique nodeid that is not taken
|
||||
node->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
|
||||
node->nodeId.namespaceIndex = 1; // namespace 1 is always in the local nodestore
|
||||
if(node->nodeClass==UA_NODECLASS_VARIABLE){ //set namespaceIndex in browseName in case id is generated
|
||||
((UA_VariableNode*)node)->browseName.namespaceIndex=node->nodeId.namespaceIndex;
|
||||
}
|
||||
|
||||
if(node->nodeId.namespaceIndex==0) //original request for ns=0 should yield ns=1
|
||||
node->nodeId.namespaceIndex=1;
|
||||
|
||||
//set namespaceIndex in browseName in case id is generated
|
||||
node->browseName.namespaceIndex=node->nodeId.namespaceIndex;
|
||||
|
||||
UA_Int32 identifier = ns->count+1; // start value
|
||||
UA_Int32 size = ns->size;
|
||||
hash_t increase = mod2(identifier, size);
|
||||
|
@ -154,7 +154,12 @@ UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node, const UA_Node
|
||||
entry->refcount++;
|
||||
|
||||
struct cds_lfht_node *result;
|
||||
if(!UA_NodeId_isNull(&node->nodeId)) {
|
||||
//FIXME: a bit dirty workaround of preserving namespace
|
||||
//namespace index is assumed to be valid
|
||||
UA_NodeId tempNodeid;
|
||||
UA_NodeId_copy(&node->nodeId, &tempNodeid);
|
||||
tempNodeid.namespaceIndex = 0;
|
||||
if(!UA_NodeId_isNull(&tempNodeid)) {
|
||||
hash_t h = hash(&node->nodeId);
|
||||
rcu_read_lock();
|
||||
result = cds_lfht_add_unique(ns->ht, h, compare, &entry->node.nodeId, &entry->htn);
|
||||
@ -168,10 +173,14 @@ UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node, const UA_Node
|
||||
} else {
|
||||
/* create a unique nodeid */
|
||||
((UA_Node *)&entry->node)->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
|
||||
((UA_Node *)&entry->node)->nodeId.namespaceIndex = 1; // namespace 1 is always in the local nodestore
|
||||
if(((UA_Node *)&entry->node)->nodeId.namespaceIndex == 0) //original request for ns=0 should yield ns=1
|
||||
((UA_Node *)&entry->node)->nodeId.namespaceIndex = 1;
|
||||
if(((UA_Node *)&entry->node)->nodeClass==UA_NODECLASS_VARIABLE){ //set namespaceIndex in browseName in case id is generated
|
||||
((UA_VariableNode*)&entry->node)->browseName.namespaceIndex=((UA_Node *)&entry->node)->nodeId.namespaceIndex;
|
||||
}
|
||||
//set namespaceIndex in browseName in case id is generated
|
||||
((UA_Node *)&entry->node)->browseName.namespaceIndex=node->nodeId.namespaceIndex;
|
||||
|
||||
unsigned long identifier;
|
||||
long before, after;
|
||||
rcu_read_lock();
|
||||
|
@ -331,8 +331,13 @@ UA_Server_addNodeWithSession(UA_Server *server, UA_Session *session, UA_Node *no
|
||||
}
|
||||
|
||||
// todo: test if the referencetype is hierarchical
|
||||
//FIXME: a bit dirty workaround of preserving namespace
|
||||
//namespace index is assumed to be valid
|
||||
const UA_Node *managed = UA_NULL;
|
||||
if(UA_NodeId_isNull(&node->nodeId)) {
|
||||
UA_NodeId tempNodeid;
|
||||
UA_NodeId_copy(&node->nodeId, &tempNodeid);
|
||||
tempNodeid.namespaceIndex = 0;
|
||||
if(UA_NodeId_isNull(&tempNodeid)) {
|
||||
if(UA_NodeStore_insert(server->nodestore, node, &managed) != UA_STATUSCODE_GOOD) {
|
||||
result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
goto ret2;
|
||||
|
@ -326,6 +326,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
|
||||
case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST:
|
||||
INVOKE_SERVICE(TranslateBrowsePathsToNodeIds, UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE);
|
||||
break;
|
||||
#ifdef ENABLE_ADDNODES
|
||||
case UA_NS0ID_ADDNODESREQUEST:
|
||||
INVOKE_SERVICE(AddNodes, UA_TYPES_ADDNODESRESPONSE);
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
if(requestType.namespaceIndex == 0 && requestType.identifier.numeric==787)
|
||||
UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION,
|
||||
|
@ -5,20 +5,21 @@
|
||||
#include "ua_session.h"
|
||||
#include "ua_util.h"
|
||||
|
||||
#define COPY_STANDARDATTRIBUTES do { \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME) { \
|
||||
vnode->displayName = attr.displayName; \
|
||||
UA_LocalizedText_init(&attr.displayName); \
|
||||
} \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DESCRIPTION) { \
|
||||
vnode->description = attr.description; \
|
||||
UA_LocalizedText_init(&attr.description); \
|
||||
} \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_WRITEMASK) \
|
||||
vnode->writeMask = attr.writeMask; \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK) \
|
||||
vnode->userWriteMask = attr.userWriteMask; \
|
||||
} while(0)
|
||||
#define COPY_STANDARDATTRIBUTES do { \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME) { \
|
||||
vnode->displayName = attr.displayName; \
|
||||
UA_LocalizedText_copy(&attr.displayName, &(vnode->displayName)); \
|
||||
UA_LocalizedText_init(&attr.displayName); \
|
||||
} \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DESCRIPTION) { \
|
||||
UA_LocalizedText_copy(&attr.description, &(vnode->description)); \
|
||||
UA_LocalizedText_init(&attr.description); \
|
||||
} \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_WRITEMASK) \
|
||||
vnode->writeMask = attr.writeMask; \
|
||||
if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK) \
|
||||
vnode->userWriteMask = attr.userWriteMask; \
|
||||
} while(0)
|
||||
|
||||
static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
|
||||
if(attributes->typeId.identifier.numeric !=
|
||||
@ -207,7 +208,12 @@ static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_Add
|
||||
|
||||
if(result->statusCode != UA_STATUSCODE_GOOD)
|
||||
return;
|
||||
|
||||
|
||||
// The BrowseName was not included with the NodeAttribute ExtensionObject
|
||||
UA_QualifiedName_init(&(node->browseName));
|
||||
UA_QualifiedName_copy(&(item->browseName), &(node->browseName));
|
||||
UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId);
|
||||
|
||||
// add the node
|
||||
*result = UA_Server_addNodeWithSession(server, session, node, item->parentNodeId,
|
||||
item->referenceTypeId);
|
||||
@ -244,7 +250,7 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
|
||||
response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UA_EXTERNAL_NAMESPACES
|
||||
#ifdef NO_ALLOCA
|
||||
UA_Boolean isExternal[size];
|
||||
|
Loading…
Reference in New Issue
Block a user