This commit is contained in:
FlorianPalm 2015-06-24 18:00:18 +02:00
commit 1adbb44483
10 changed files with 347 additions and 32 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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,

View File

@ -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];